{"record":{"id":"e933846c64803f65","repo":"microsoft/semantic-kernel","slug":"missing-or-malformed-tool-connections-in-spec","errorCode":null,"errorMessage":"Missing or malformed 'tool_connections' in: {spec}","messagePattern":"Missing or malformed 'tool_connections' in: (.+?)","errorType":"validation","errorClass":"AgentInitializationException","httpStatus":null,"severity":"error","filePath":"python/semantic_kernel/agents/azure_ai/azure_ai_agent.py","lineNumber":105,"sourceCode":"\n_TOOL_BUILDERS: dict[str, Callable[[ToolSpec, Kernel | None], ToolDefinition]] = {}\n\n\ndef _register_tool(tool_type: str):\n    def decorator(fn: Callable[[ToolSpec, Kernel | None], ToolDefinition]):\n        _TOOL_BUILDERS[tool_type.lower()] = fn\n        return fn\n\n    return decorator\n\n\n@_register_tool(\"azure_ai_search\")\ndef _azure_ai_search(spec: ToolSpec) -> AzureAISearchTool:\n    opts = spec.options or {}\n\n    connections = opts.get(\"tool_connections\")\n    if not connections or not isinstance(connections, list) or not connections[0]:\n        raise AgentInitializationException(f\"Missing or malformed 'tool_connections' in: {spec}\")\n    conn_id = connections[0]\n\n    index_name = opts.get(\"index_name\")\n    if not index_name or not isinstance(index_name, str):\n        raise AgentInitializationException(f\"Missing or malformed 'index_name' in: {spec}\")\n\n    raw_query_type = opts.get(\"query_type\", AzureAISearchQueryType.SIMPLE)\n    if type(raw_query_type) is str:\n        try:\n            query_type = AzureAISearchQueryType(raw_query_type.lower())\n        except ValueError:\n            raise AgentInitializationException(f\"Invalid query_type '{raw_query_type}' in: {spec}\")\n    else:\n        query_type = raw_query_type\n\n    filter_expr = opts.get(\"filter\", \"\")\n\n    top_k = opts.get(\"top_k\", 5)","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/python/semantic_kernel/agents/azure_ai/azure_ai_agent.py#L87-L123","documentation":"Raised when building an azure_ai_search tool from a declarative ToolSpec and spec.options.tool_connections is absent, not a list, or an empty/falsy first element. tool_connections provides the Azure AI Search index connection ID and is mandatory.","triggerScenarios":"Declarative spec YAML/JSON omits tool_connections, provides it as a string instead of a list, or passes an empty list for an azure_ai_search tool.","commonSituations":"Developer hand-writes the declarative spec and forgets the connection ID; copies a template that used a placeholder; env-specific connection IDs not substituted.","solutions":["Add tool_connections as a list with the Azure AI Search index connection ID: tool_connections: [\"/subscriptions/.../connection\"]","Ensure the connection ID is copied from the Azure AI project's Connections blade, not the search service URL.","Validate the spec dict shape (list, non-empty, first element truthy) before passing to the agent factory."],"exampleFix":"// before\ntools:\n  - type: azure_ai_search\n    options:\n      index_name: my-index\n\n// after\ntools:\n  - type: azure_ai_search\n    options:\n      tool_connections:\n        - \"/subscriptions/.../projects/myproj/connections/mySearchConn\"\n      index_name: my-index","handlingStrategy":"validation","validationCode":"def validate_ai_search_spec(spec_opts: dict) -> None:\n    conns = spec_opts.get(\"tool_connections\")\n    if not isinstance(conns, list) or not conns or not conns[0]:\n        raise ValueError(\"azure_ai_search requires non-empty list 'tool_connections'\")","typeGuard":"def has_valid_connections(opts: dict) -> bool:\n    c = opts.get(\"tool_connections\")\n    return isinstance(c, list) and bool(c) and bool(c[0])","tryCatchPattern":null,"preventionTips":["Validate declarative spec dicts against a schema (Pydantic model) before passing to the agent factory.","Centralize connection-ID constants in config, not inline in specs."],"tags":["azure-ai-agent","declarative-spec","azure-ai-search","configuration"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}