microsoft/autogen · error · ValueError

Unsupported tool type: {type(tool)}

Error message

Unsupported tool type: {type(tool)}

What it means

OpenAIAgent's constructor validates each entry in the tools list: it accepts plain strings (built-in tool names) and dicts that contain a 'type' key (pre-configured tool payloads). Anything else — an int, a Tool instance, a function, a dict without 'type' — hits the else branch and raises ValueError with the offending type.

Source

Thrown at python/packages/autogen-ext/src/autogen_ext/agents/openai/_openai_agent.py:433

        self._instructions: str = instructions
        self._temperature: Optional[float] = temperature
        self._max_output_tokens: Optional[int] = max_output_tokens
        self._json_mode: bool = json_mode
        self._store: bool = store
        self._truncation: str = truncation
        self._last_response_id: Optional[str] = None
        self._message_history: List[Dict[str, Any]] = []
        self._tools: List[Dict[str, Any]] = []
        if tools is not None:
            for tool in tools:
                if isinstance(tool, str):
                    # Handle built-in tool types
                    self._add_builtin_tool(tool)
                elif isinstance(tool, dict) and "type" in tool:
                    # Handle configured built-in tools
                    self._tools.append(cast(dict[str, Any], tool))
                else:
                    raise ValueError(f"Unsupported tool type: {type(tool)}")

    def _add_builtin_tool(self, tool_name: str) -> None:
        """Add a built-in tool by name."""
        # Skip if an identical tool has already been registered (idempotent behaviour)
        if any(td.get("type") == tool_name for td in self._tools):
            return  # Duplicate – ignore rather than raise to stay backward-compatible
        # Only allow string format for tools that don't require parameters
        if tool_name == "web_search_preview":
            self._tools.append({"type": "web_search_preview"})
        elif tool_name == "image_generation":
            self._tools.append({"type": "image_generation"})
        elif tool_name == "local_shell":
            # Special handling for local_shell - very limited model support
            if self._model != "codex-mini-latest":
                raise ValueError(
                    f"Tool 'local_shell' is only supported with model 'codex-mini-latest', "
                    f"but current model is '{self._model}'. "
                    f"This tool is available exclusively through the Responses API and has severe limitations. "

View on GitHub (pinned to 027ecf0a37)

Solutions

  1. Use string names for parameterless built-ins: tools=["web_search_preview", "image_generation"].
  2. Use full dict configuration for parameterized tools: tools=[{"type": "file_search", "vector_store_ids": ["vs_..."]}].
  3. If you want an LLM to call Python functions, do not put them in tools=; use the tool schema produced by your ChatCompletionClient / function-calling setup instead.

Example fix

# before
agent = OpenAIAgent(
    name="a",
    model="gpt-4o",
    client=client,
    tools=[my_python_function],  # ValueError: Unsupported tool type: <class 'function'>
)

# after (built-in via string, configured tool via dict)
agent = OpenAIAgent(
    name="a",
    model="gpt-4o",
    client=client,
    tools=[
        "web_search_preview",
        {"type": "file_search", "vector_store_ids": ["vs_123"]},
    ],
)
Defensive patterns

Strategy: validation

Validate before calling

def is_valid_openai_agent_tool(tool: object) -> bool:
    if isinstance(tool, str):
        return True
    return isinstance(tool, dict) and "type" in tool

assert all(is_valid_openai_agent_tool(t) for t in tools)

Type guard

from typing import Any

def is_agent_tool(t: Any) -> bool:
    return isinstance(t, str) or (isinstance(t, dict) and "type" in t)

Prevention

When it happens

Trigger: Passing tools=[some_python_function] or tools=[FunctionTool(...)] (autogen-core tool objects) to OpenAIAgent; passing a dict like {"function": {...}} that lacks the "type" key; passing None inside the list.

Common situations: Copy-pasting a tools list from OpenAIAssistantAgent (which DOES accept Tool/callable objects) into OpenAIAgent; mixing autogen-core Tool instances with the Responses-API dict format; malformed JSON loaded tool configs missing the type field.

Related errors


AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15). Data as JSON: /api/errors/a2926688dfba5096. Report an issue: GitHub.