BerriAI/litellm · error · ValueError

advisor tool definition must include a 'model' field specify

Error message

advisor tool definition must include a 'model' field specifying the advisor model

What it means

Raised by the advisor interceptor when it finds a tool of type 'advisor' in the tools list but that tool definition has no (or empty) 'model' field. The advisor pattern routes pre-execution advice through a separate advisor model, so the interceptor must know which model to call; the field is mandatory.

Source

Thrown at litellm/llms/anthropic/experimental_pass_through/messages/interceptors/advisor.py:80

        stream: bool | None,
        max_tokens: int,
        custom_llm_provider: str | None,
        **kwargs,
    ) -> AnthropicMessagesResponse | AsyncIterator:
        from litellm.llms.anthropic.experimental_pass_through.messages.fake_stream_iterator import (
            FakeAnthropicMessagesStreamIterator,
        )

        # Extract advisor tool config.
        advisor_tool: Final = next(
            (t for t in (tools or []) if t.get("type") == ANTHROPIC_ADVISOR_TOOL_TYPE),
            None,
        )
        if advisor_tool is None:
            raise ValueError(f"handle() called but no {ANTHROPIC_ADVISOR_TOOL_TYPE} tool found in tools list")
        advisor_model: Final[str] = advisor_tool.get("model") or ""
        if not advisor_model:
            raise ValueError("advisor tool definition must include a 'model' field specifying the advisor model")
        _raw_max_uses: Final = advisor_tool.get("max_uses")
        max_uses: Final[int] = ADVISOR_MAX_USES if _raw_max_uses is None else int(_raw_max_uses)
        advisor_api_key, advisor_api_base = _resolve_advisor_credentials(advisor_tool)

        # Build the synthetic tool definition the provider will receive.
        synthetic_advisor_tool: Final = _make_synthetic_advisor_tool()

        # Executor tools = all original tools with advisor replaced by the synthetic one.
        executor_tools: Final[list[dict]] = [
            (synthetic_advisor_tool if t.get("type") == ANTHROPIC_ADVISOR_TOOL_TYPE else t) for t in (tools or [])
        ]

        # Strip prior advisor blocks from history, preserving advice text as context.
        current_messages: list[dict] = strip_advisor_blocks_from_messages(
            [dict(m) for m in messages], replace_with_text=True
        )

        parent_request_id: Final[str] = str(kwargs.pop("litellm_call_id", None) or uuid.uuid4())

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Add a 'model' field to the advisor tool definition naming the model that gives advice, e.g. {"type": "advisor", "model": "claude-haiku-4-5", "max_uses": 1}.
  2. If the model name comes from config, assert it is non-empty before attaching the advisor tool.
  3. Omit the advisor tool entirely if you do not want advisory behavior.

Example fix

# before
tools = [{"type": "advisor", "max_uses": 1}]

# after
tools = [{"type": "advisor", "model": "claude-haiku-4-5", "max_uses": 1}]
Defensive patterns

Strategy: validation

Validate before calling

def make_advisor_tool(model: str, max_uses: int | None = None) -> dict:
    if not model:
        raise ValueError("advisor tool requires a non-empty 'model'")
    tool = {"type": "advisor", "model": model}
    if max_uses is not None:
        tool["max_uses"] = max_uses
    return tool

Type guard

def is_valid_advisor_tool(tool: object) -> bool:
    return (
        isinstance(tool, dict)
        and tool.get("type") == "advisor"
        and isinstance(tool.get("model"), str)
        and bool(tool["model"].strip())
    )

Try / catch

try:
    resp = litellm.anthropic_messages(tools=tools, ...)
except ValueError as e:
    if "advisor tool definition must include a 'model'" in str(e):
        return http_error(400, str(e))
    raise

Prevention

When it happens

Trigger: Sending a /v1/messages request with tools=[{"type": "advisor", "max_uses": 1}] — any advisor tool dict lacking 'model' or with model="". The interceptor extracts advisor_tool.get('model') and rejects empty strings.

Common situations: Enabling the advisor tool based on docs that only mention type/max_uses; refactoring that renames 'model' to 'advisor_model'; conditionally building the tool dict and dropping the model key when a config value is unset.

Related errors


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/e862b38b50aa0e60. Report an issue: GitHub.