BerriAI/litellm · error · OCIError

OCI only supports function tools

Error message

OCI only supports function tools

What it means

The `tools` parameter for OCI GENERIC models only accepts tool definitions with type "function" (OpenAI's function-tools subset). The first check in adapt_tool_definition_to_oci_standard rejects any other type — including missing type — with OCIError 400 before schema translation ($ref/$defs/anyOf resolution) even starts.

Solutions

  1. Wrap every tool as {"type": "function", "function": {"name": ..., "description": ..., "parameters": ...}}
  2. Filter your tool registry to function-type tools when routing to OCI
  3. Convert other providers' schemas: rename input_schema -> parameters, nest under function
  4. Verify with a quick assert before the call: all(t.get("type")=="function" for t in tools)

Example fix

# before
tools = [{"name": "get_weather", "description": "...", "input_schema": {...}}]  # Anthropic-style

# after
tools = [{
  "type": "function",
  "function": {"name": "get_weather", "description": "...", "parameters": {...}}
}]
Defensive patterns

Strategy: validation

Validate before calling

def to_openai_function_tools(tools: list) -> list:
    out = []
    for t in tools:
        if t.get("type") == "function":
            out.append(t)
        elif "function" not in t and "name" in t:  # Anthropic-style schema
            out.append({"type": "function", "function": {
                "name": t["name"],
                "description": t.get("description", ""),
                "parameters": t.get("input_schema", t.get("parameters", {})),
            }})
    return out

tools = to_openai_function_tools(tools)
assert all(t.get("type") == "function" for t in tools)

Type guard

def is_function_tool_def(tool) -> bool:
    return isinstance(tool, dict) and tool.get("type") == "function" and isinstance(tool.get("function"), dict)

Prevention

When it happens

Trigger: litellm.completion(model="oci/generic...", tools=[{"type":"code_interpreter",...}]) or a tool dict without a type key. Also triggered by non-OpenAI tool shapes (bare function schemas not wrapped in {"type":"function","function":{...}}).

Common situations: Copying tool configs from OpenAI Assistants (code_interpreter, retrieval, file_search types); passing Anthropic-style tool schemas (top-level name/description/input_schema); omitting type when hand-writing tools; multi-provider tool registries forwarded wholesale.

Related errors


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/2257061b02e487fd. Report an issue: GitHub.

Appendix: source

Thrown at litellm/llms/oci/chat/generic.py:222

            new_messages.append(adapt_messages_to_generic_oci_standard_tool_response(role, tool_call_id, content))

    return new_messages


# ---------------------------------------------------------------------------
# Tool definition adaptation
# ---------------------------------------------------------------------------


def adapt_tool_definition_to_oci_standard(tools: list[dict], vendor: OCIVendors) -> list[OCIToolDefinition]:
    """Convert OpenAI-format tool definitions to OCI GENERIC format.

    Resolves ``$ref``/``$defs`` and ``anyOf`` that the OCI endpoint rejects.
    """
    new_tools: Final = []
    for tool in tools:
        if tool["type"] != "function":
            raise OCIError(status_code=400, message="OCI only supports function tools")

        tool_function = tool.get("function")
        if not isinstance(tool_function, dict):
            raise OCIError(status_code=400, message="Tool `function` must be a dictionary")

        raw_params = tool_function.get("parameters", {})
        resolved_params = sanitize_oci_schema(resolve_oci_schema_anyof(resolve_oci_schema_refs(raw_params)))

        new_tools.append(
            OCIToolDefinition(
                type="FUNCTION",
                name=tool_function.get("name"),
                description=tool_function.get("description", ""),
                parameters=resolved_params,
            )
        )

    return new_tools

View on GitHub (pinned to 77b7c6c40c)