{"record":{"id":"8956a017ea6926b6","repo":"microsoft/semantic-kernel","slug":"unresolved-placeholders-in-spec-join-f","errorCode":null,"errorMessage":"Unresolved placeholders in spec: {', '.join(f'${{{key}}}' for key in unresolved)}","messagePattern":"Unresolved placeholders in spec: (.+?)\\}' for key in unresolved\\)\\}","errorType":"exception","errorClass":"AgentInitializationException","httpStatus":null,"severity":"error","filePath":"python/semantic_kernel/agents/azure_ai/azure_ai_agent.py","lineNumber":627,"sourceCode":"        if extras:\n            field_mapping.update(extras)\n\n        def replacer(match: re.Match[str]) -> str:\n            \"\"\"Replace the matched placeholder with the corresponding value from field_mapping.\"\"\"\n            full_key = match.group(1)  # for example, AzureAI:AzureAISearchConnectionId\n            section, _, key = full_key.partition(\":\")\n            if section != \"AzureAI\":\n                return match.group(0)\n\n            # Try short key first (AzureAISearchConnectionId), then full (AzureAI:AzureAISearchConnectionId)\n            return str(field_mapping.get(key) or field_mapping.get(full_key) or match.group(0))\n\n        result = pattern.sub(replacer, yaml_str)\n\n        # Safety check for unresolved placeholders\n        unresolved = pattern.findall(result)\n        if unresolved:\n            raise AgentInitializationException(\n                f\"Unresolved placeholders in spec: {', '.join(f'${{{key}}}' for key in unresolved)}\"\n            )\n\n        return result\n\n    # endregion\n\n    # region Invocation Methods\n\n    @trace_agent_get_response\n    @override\n    async def get_response(\n        self,\n        messages: str | ChatMessageContent | list[str | ChatMessageContent] | None = None,\n        *,\n        thread: AgentThread | None = None,\n        arguments: KernelArguments | None = None,\n        kernel: Kernel | None = None,","sourceCodeStart":609,"sourceCodeEnd":645,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/python/semantic_kernel/agents/azure_ai/azure_ai_agent.py#L609-L645","documentation":"Raised by AzureAIAgent.resolve_placeholders when, after substitution, ${...} placeholders remain in the YAML. Each placeholder must resolve via the AzureAI settings field mapping or the extras dict; any leftover means a referenced value was not provided. Surfaced as AgentInitializationException listing the unresolved keys.","triggerScenarios":"Spec references ${AzureAI:SomeKey} where SomeKey is not one of ChatModelId, Endpoint, AgentId, BingConnectionId, AzureAISearchConnectionId, AzureAISearchIndexName and is not in extras; the corresponding settings field is empty/None so the replacer falls through to the raw placeholder; a typo in the key.","commonSituations":"Forgetting to set AZURE_AI_AGENT_MODEL_DEPLOYMENT_NAME so ChatModelId is None; referencing a custom value not supplied via extras; placeholder key casing mismatch (e.g. chatmodelid vs ChatModelId); settings loaded from env that was empty.","solutions":["Set the required AzureAIAgentSettings env vars (model_deployment_name, endpoint, etc.) so each referenced field is non-empty.","Pass any custom values via the extras dict keyed by the short name used in the placeholder.","Match the placeholder key exactly (case-sensitive) to the field_mapping keys.","Ensure the placeholder uses the AzureAI: section prefix."],"exampleFix":"// before\nyaml: \"model: ${AzureAI:ChatModelId}\"  // model_deployment_name unset -> unresolved\n// after\nexport AZURE_AI_AGENT_MODEL_DEPLOYMENT_NAME=gpt-4o-deployment\n# or pass extras:\nresolve_placeholders(yaml, extras={\"ChatModelId\": \"gpt-4o-deployment\"})","handlingStrategy":"validation","validationCode":"import re\n_ALLOWED = {'ChatModelId','Endpoint','AgentId','BingConnectionId','AzureAISearchConnectionId','AzureAISearchIndexName'}\ndef validate_placeholders(yaml_str, extras=None):\n    keys = set(re.findall(r'\\$\\{AzureAI:([^}]+)\\}', yaml_str))\n    missing = {k for k in keys if k not in _ALLOWED and (not extras or k not in extras)}\n    if missing:\n        raise ValueError(f'Unresolved placeholders need values or extras: {missing}')\n    return yaml_str","typeGuard":"def all_placeholders_resolvable(yaml_str, extras=None) -> bool:\n    keys = set(re.findall(r'\\$\\{AzureAI:([^}]+)\\}', yaml_str))\n    return all(k in _ALLOWED or (extras and k in extras) for k in keys)","tryCatchPattern":"try:\n    AzureAIAgent.resolve_placeholders(yaml, settings=settings, extras=extras)\nexcept AgentInitializationException as e:\n    if 'Unresolved placeholders' in str(e):\n        log.error('Provide env vars or extras for the listed keys')\n    raise","preventionTips":["Set all referenced AzureAIAgentSettings env vars (model_deployment_name, endpoint, etc.).","Supply custom values via the extras dict using the exact placeholder key.","Pre-validate placeholders with a regex scan before calling resolve_placeholders."],"tags":["azure-ai","declarative-spec","placeholders","configuration","environment"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}