Docs
Tool & MCP calling
Pass an OpenAI-style tools array on any agent's endpoint and it will decide when to call one. Execution always stays on your side — we relay the decision, we never run your tools for you. What differs sharply by agent is how strongly that decision is enforced.
{
"messages": [{"role": "user", "content": "What's the weather in Berlin?"}],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather for a city",
"parameters": {
"type": "object",
"properties": { "city": { "type": "string" } },
"required": ["city"],
"additionalProperties": false
}
}
}
],
"tool_choice": "auto"
}
Response with a tool call
{
"choices": [{
"message": {
"role": "assistant",
"tool_calls": [{
"id": "call_1",
"type": "function",
"function": { "name": "get_weather", "arguments": "{\"city\":\"Berlin\"}" }
}]
},
"finish_reason": "tool_calls"
}]
}
Reliability by agent
- Claude Code — native. Enforced by the Claude Agent SDK itself. This is the only agent where a tool call is a structural guarantee, not a best-effort simulation.
- Codex — simulated, structural. Constrained by a JSON output schema at the SDK level. Strong, but not a native tool-calling API.
- Grok — simulated, constrained decoding. Uses a CLI flag that constrains output to match your schema. Close to Codex in reliability.
- Gemini CLI — simulated, prompt only. No structural enforcement exists for this agent today — it's a prompt instruction the model can, in principle, ignore. Treat tool calls from Gemini as a suggestion to double-check, not a guarantee.
Bridging an MCP server
None of the four agents' native MCP clients are exposed through the gateway today. The pattern that works on all of them: translate your MCP server's tool definitions into the tools array above on your own client, run the returned tool call against your MCP server yourself, then send the result back as a follow-up message. Any standard MCP client library works for this.
Note: tool-calling and stream can't be combined on any agent yet — a request with active tools and "stream": true is rejected with 400.