{"record":{"id":"2257061b02e487fd","repo":"BerriAI/litellm","slug":"oci-only-supports-function-tools","errorCode":null,"errorMessage":"OCI only supports function tools","messagePattern":"OCI only supports function tools","errorType":"exception","errorClass":"OCIError","httpStatus":400,"severity":"error","filePath":"litellm/llms/oci/chat/generic.py","lineNumber":222,"sourceCode":"            new_messages.append(adapt_messages_to_generic_oci_standard_tool_response(role, tool_call_id, content))\n\n    return new_messages\n\n\n# ---------------------------------------------------------------------------\n# Tool definition adaptation\n# ---------------------------------------------------------------------------\n\n\ndef adapt_tool_definition_to_oci_standard(tools: list[dict], vendor: OCIVendors) -> list[OCIToolDefinition]:\n    \"\"\"Convert OpenAI-format tool definitions to OCI GENERIC format.\n\n    Resolves ``$ref``/``$defs`` and ``anyOf`` that the OCI endpoint rejects.\n    \"\"\"\n    new_tools: Final = []\n    for tool in tools:\n        if tool[\"type\"] != \"function\":\n            raise OCIError(status_code=400, message=\"OCI only supports function tools\")\n\n        tool_function = tool.get(\"function\")\n        if not isinstance(tool_function, dict):\n            raise OCIError(status_code=400, message=\"Tool `function` must be a dictionary\")\n\n        raw_params = tool_function.get(\"parameters\", {})\n        resolved_params = sanitize_oci_schema(resolve_oci_schema_anyof(resolve_oci_schema_refs(raw_params)))\n\n        new_tools.append(\n            OCIToolDefinition(\n                type=\"FUNCTION\",\n                name=tool_function.get(\"name\"),\n                description=tool_function.get(\"description\", \"\"),\n                parameters=resolved_params,\n            )\n        )\n\n    return new_tools","sourceCodeStart":204,"sourceCodeEnd":240,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/llms/oci/chat/generic.py#L204-L240","documentation":"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.","triggerScenarios":"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\":{...}}).","commonSituations":"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.","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)"],"exampleFix":"# before\ntools = [{\"name\": \"get_weather\", \"description\": \"...\", \"input_schema\": {...}}]  # Anthropic-style\n\n# after\ntools = [{\n  \"type\": \"function\",\n  \"function\": {\"name\": \"get_weather\", \"description\": \"...\", \"parameters\": {...}}\n}]","handlingStrategy":"validation","validationCode":"def to_openai_function_tools(tools: list) -> list:\n    out = []\n    for t in tools:\n        if t.get(\"type\") == \"function\":\n            out.append(t)\n        elif \"function\" not in t and \"name\" in t:  # Anthropic-style schema\n            out.append({\"type\": \"function\", \"function\": {\n                \"name\": t[\"name\"],\n                \"description\": t.get(\"description\", \"\"),\n                \"parameters\": t.get(\"input_schema\", t.get(\"parameters\", {})),\n            }})\n    return out\n\ntools = to_openai_function_tools(tools)\nassert all(t.get(\"type\") == \"function\" for t in tools)","typeGuard":"def is_function_tool_def(tool) -> bool:\n    return isinstance(tool, dict) and tool.get(\"type\") == \"function\" and isinstance(tool.get(\"function\"), dict)","tryCatchPattern":null,"preventionTips":["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"],"tags":["oci","tools","function-calling","request-validation"],"backgroundTag":"unsupported-tool-type","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}