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
- Wrap every tool as {"type": "function", "function": {"name": ..., "description": ..., "parameters": ...}}
- Filter your tool registry to function-type tools when routing to OCI
- Convert other providers' schemas: rename input_schema -> parameters, nest under function
- 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
- Keep one canonical OpenAI function-tool schema in your registry and derive provider formats from it
- Assert tool types in tests for every provider you route to
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
- OCI only supports function tool calls
- Content item of type `text` must have a string `text` field
- Content type ` ` is not supported by OCI
- Exception - Use 'watsonx_text' route instead. IBM WatsonX…
- Each content item must be a dictionary
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_toolsView on GitHub (pinned to 77b7c6c40c)