{"record":{"id":"79e30a97de7ce02e","repo":"microsoft/semantic-kernel","slug":"tool-id-tool-id-must-be-in-format-pluginname-f","errorCode":null,"errorMessage":"Tool id '{tool_id}' must be in format PluginName.FunctionName","messagePattern":"Tool id '(.+?)' must be in format PluginName\\.FunctionName","errorType":"validation","errorClass":"AgentInitializationException","httpStatus":null,"severity":"error","filePath":"python/semantic_kernel/agents/agent.py","lineNumber":1057,"sourceCode":"        return fields, kernel\n\n    @classmethod\n    def _validate_tools(cls: type[_D], tools_list: list[dict], kernel: Kernel) -> None:\n        \"\"\"Validate tool references in the declarative spec against kernel's registered plugins.\n\n        This validates the declared tools in the YAML spec, and only checks whether those references resolve\n        properly in the current kernel.\n        \"\"\"\n        if not kernel:\n            raise AgentInitializationException(\"Kernel instance is required for tool resolution.\")\n\n        for tool in tools_list:\n            tool_id = tool.get(\"id\")\n            if not tool_id or tool.get(\"type\") != \"function\":\n                continue\n\n            if \".\" not in tool_id:\n                raise AgentInitializationException(f\"Tool id '{tool_id}' must be in format PluginName.FunctionName\")\n\n            plugin_name, function_name = tool_id.split(\".\", 1)\n\n            plugin = kernel.plugins.get(plugin_name)\n            if not plugin:\n                raise AgentInitializationException(f\"Plugin '{plugin_name}' not found in kernel.\")\n\n            if function_name not in plugin.functions:\n                raise AgentInitializationException(f\"Function '{function_name}' not found in plugin '{plugin_name}'.\")\n\n\n# endregion\n","sourceCodeStart":1039,"sourceCodeEnd":1070,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/python/semantic_kernel/agents/agent.py#L1039-L1070","documentation":"Thrown by _validate_tools when a function-type tool's `id` does not contain a '.' separator. The loader splits on '.' to derive PluginName.FunctionName, so an id like 'search' is rejected. Non-function tools or tools without an id are skipped, so this only applies to entries with type=='function' and a non-empty id.","triggerScenarios":"A YAML `tools:` entry `{id: search, type: function}` instead of `{id: WebPlugin.search, type: function}`.","commonSituations":"Authoring tool ids by function name only; importing a spec from a system that uses bare function names; copy-paste that dropped the plugin prefix.","solutions":["Format every function tool id as `PluginName.FunctionName` in the spec.","Ensure the plugin name matches the name used when kernel.add_plugin(..., plugin_name=...) was called.","Validate tool ids programmatically before loading (see validationCode)."],"exampleFix":"# before\ntools:\n  - id: search\n    type: function\n\n# after\ntools:\n  - id: WebPlugin.search\n    type: function","handlingStrategy":"validation","validationCode":"for t in spec.get('tools', []):\n    if t.get('type') == 'function' and t.get('id') and '.' not in t['id']:\n        raise ValueError(f\"tool id {t['id']!r} must be PluginName.FunctionName\")","typeGuard":"def tool_id_is_well_formed(tool: dict) -> bool:\n    tid = tool.get('id')\n    return not (tool.get('type') == 'function' and tid) or '.' in tid","tryCatchPattern":"from semantic_kernel.exceptions.agent_exceptions import AgentInitializationException\ntry:\n    agent = await AgentRegistry.create_from_yaml(yaml_str, kernel=kernel)\nexcept AgentInitializationException as e:\n    if 'must be in format' in str(e):\n        # fix tool ids to PluginName.FunctionName then retry\n        raise\n    raise","preventionTips":["Author every function tool id as PluginName.FunctionName.","Lint tool ids before loading the spec."],"tags":["tools","validation","declarative-spec","semantic-kernel"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}