{"record":{"id":"c1327fb1d39adefa","repo":"agentscope-ai/agentscope","slug":"each-schema-must-be-a-dict-with-type-as-functio","errorCode":null,"errorMessage":"Each schema must be a dict with 'type' as 'function' and 'function' key, got {value}","messagePattern":"Each schema must be a dict with 'type' as 'function' and 'function' key, got (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/agentscope/model/_dashscope/_model.py","lineNumber":516,"sourceCode":"            `tuple[list[dict] | None, str | dict | None]`:\n                A tuple of (formatted_tools, formatted_tool_choice).\n        \"\"\"\n        if tool_choice and tools:\n            self._validate_tool_choice(tool_choice, tools)\n            if tool_choice.tools:\n                allowed = set(tool_choice.tools)\n                tools = [t for t in tools if t[\"function\"][\"name\"] in allowed]\n\n        fmt_tools = None\n        if tools:\n            for value in tools:\n                if (\n                    not isinstance(value, dict)\n                    or \"type\" not in value\n                    or value[\"type\"] != \"function\"\n                    or \"function\" not in value\n                ):\n                    raise ValueError(\n                        f\"Each schema must be a dict with 'type' as \"\n                        f\"'function' and 'function' key, got {value}\",\n                    )\n            fmt_tools = tools\n\n        if not tool_choice:\n            return fmt_tools, None\n\n        mode = tool_choice.mode\n\n        if mode not in _TOOL_CHOICE_LITERAL_MODES:\n            return fmt_tools, {\n                \"type\": \"function\",\n                \"function\": {\"name\": mode},\n            }\n\n        if mode == \"required\":\n            warnings.warn(","sourceCodeStart":498,"sourceCodeEnd":534,"githubUrl":"https://github.com/agentscope-ai/agentscope/blob/e90f1c7592896cc95f6e5ee506194f533378247d/src/agentscope/model/_dashscope/_model.py#L498-L534","documentation":"The DashScope model adapter requires each tool schema to be an OpenAI-style dict with type=='function' and a 'function' key. Passing raw function dicts (missing the wrapper), malformed schemas, or non-dict entries raises ValueError in _format_tools.","triggerScenarios":"Passing tools=[{'name': 'foo', 'parameters': {...}}] (no type/function wrapper), or mixing in JSON-schema objects directly instead of the {'type':'function','function':{...}} envelope.","commonSituations":"Hand-building tool schemas; converting from other frameworks (Anthropic-style input_schema) without wrapping; passing toolkit.get_schemas() output of the wrong shape.","solutions":["Wrap each tool in the OpenAI function envelope: {'type': 'function', 'function': {'name': ..., 'description': ..., 'parameters': ...}}","Prefer registering tools via agentscope Toolkit so schemas are generated in the correct format","Validate each entry with the check shown in the error before submitting"],"exampleFix":"# before\ntools = [{'name': 'get_weather', 'parameters': {...}}]\n\n# after\ntools = [{'type': 'function',\n          'function': {'name': 'get_weather', 'description': '...', 'parameters': {...}}}]","handlingStrategy":"validation","validationCode":"def check_tools(tools):\n    for t in tools:\n        assert isinstance(t, dict) and t.get('type') == 'function' and 'function' in t, f'bad tool schema: {t}'","typeGuard":"def is_openai_tool_schema(t) -> bool:\n    return isinstance(t, dict) and t.get('type') == 'function' and isinstance(t.get('function'), dict) and 'name' in t['function']","tryCatchPattern":null,"preventionTips":["Generate schemas via agentscope Toolkit instead of hand-writing","Validate tool payloads in tests before sending to the provider"],"tags":["agentscope","dashscope","tools","schema-format","validation"],"backgroundTag":"invalid-tool-schema","analyzedSha":"e90f1c7592896cc95f6e5ee506194f533378247d","analyzedAt":"2026-08-28T18:24:12.087Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}