microsoft/semantic-kernel · error · AgentInitializationException
Unresolved placeholders in spec: {', '.join(f'${{{key}}}' fo
Error message
Unresolved placeholders in spec: {', '.join(f'${{{key}}}' for key in unresolved)} What it means
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.
Source
Thrown at python/semantic_kernel/agents/azure_ai/azure_ai_agent.py:627
if extras:
field_mapping.update(extras)
def replacer(match: re.Match[str]) -> str:
"""Replace the matched placeholder with the corresponding value from field_mapping."""
full_key = match.group(1) # for example, AzureAI:AzureAISearchConnectionId
section, _, key = full_key.partition(":")
if section != "AzureAI":
return match.group(0)
# Try short key first (AzureAISearchConnectionId), then full (AzureAI:AzureAISearchConnectionId)
return str(field_mapping.get(key) or field_mapping.get(full_key) or match.group(0))
result = pattern.sub(replacer, yaml_str)
# Safety check for unresolved placeholders
unresolved = pattern.findall(result)
if unresolved:
raise AgentInitializationException(
f"Unresolved placeholders in spec: {', '.join(f'${{{key}}}' for key in unresolved)}"
)
return result
# endregion
# region Invocation Methods
@trace_agent_get_response
@override
async def get_response(
self,
messages: str | ChatMessageContent | list[str | ChatMessageContent] | None = None,
*,
thread: AgentThread | None = None,
arguments: KernelArguments | None = None,
kernel: Kernel | None = None,View on GitHub (pinned to c028a0c7dc)
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.
Example fix
// before
yaml: "model: ${AzureAI:ChatModelId}" // model_deployment_name unset -> unresolved
// after
export AZURE_AI_AGENT_MODEL_DEPLOYMENT_NAME=gpt-4o-deployment
# or pass extras:
resolve_placeholders(yaml, extras={"ChatModelId": "gpt-4o-deployment"}) Defensive patterns
Strategy: validation
Validate before calling
import re
_ALLOWED = {'ChatModelId','Endpoint','AgentId','BingConnectionId','AzureAISearchConnectionId','AzureAISearchIndexName'}
def validate_placeholders(yaml_str, extras=None):
keys = set(re.findall(r'\$\{AzureAI:([^}]+)\}', yaml_str))
missing = {k for k in keys if k not in _ALLOWED and (not extras or k not in extras)}
if missing:
raise ValueError(f'Unresolved placeholders need values or extras: {missing}')
return yaml_str Type guard
def all_placeholders_resolvable(yaml_str, extras=None) -> bool:
keys = set(re.findall(r'\$\{AzureAI:([^}]+)\}', yaml_str))
return all(k in _ALLOWED or (extras and k in extras) for k in keys) Try / catch
try:
AzureAIAgent.resolve_placeholders(yaml, settings=settings, extras=extras)
except AgentInitializationException as e:
if 'Unresolved placeholders' in str(e):
log.error('Provide env vars or extras for the listed keys')
raise Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- OpenAPI tool '{spec.id}' is missing required 'specification'
- Tool spec must include a 'type' field.
- Please provide a valid Azure AI endpoint.
- Missing required 'client' in AzureAIAgent._from_dict()
- model.id required when creating a new Azure AI agent
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/8956a017ea6926b6.
Report an issue: GitHub.