> Keiro Labs API documentation - Tool Calling
> Page: https://docs.keirolabs.ai/tool-calling.html
> Markdown: https://docs.keirolabs.ai/tool-calling.md
> Agent index: https://docs.keirolabs.ai/llms.txt
> API base URL: https://api.keirolabs.ai/v1
> Auth: send "Authorization: Bearer <api-key>" with a key created in the
> Keiro console (https://console.keirolabs.ai/api-keys). Use credentials saved by
> `keiro setup`, or resolve the key from a secret manager or an owner-only
> secret file and pass it to the client explicitly. Never read another
> provider's variable, and never put raw key material in environment
> variables, code, docs, or logs.

# Tool calling

Keiro supports client-executed function tools on Responses, Chat Completions,
and Messages. The model chooses a function and produces arguments; your
application validates those arguments, runs the function, and sends the result
back for the next model turn.

Keiro never executes your function code.

## Define a function with Responses

```bash
printf 'Keiro API key: '
IFS= read -rs KEIRO_BEARER
printf '\n'

curl -sS https://api.keirolabs.ai/v1/responses \
  -H "Content-Type: application/json" \
  -d '{
    "model": "eb1-preview",
    "input": "What is the weather in Seoul?",
    "tools": [
      {
        "type": "function",
        "name": "get_weather",
        "description": "Return the current weather for a city.",
        "parameters": {
          "type": "object",
          "properties": {
            "city": {"type": "string"}
          },
          "required": ["city"],
          "additionalProperties": false
        }
      }
    ],
    "tool_choice": "auto"
  }' \
  -H @- <<<"Authorization: Bearer $KEIRO_BEARER"
```

When the model selects the function, `output` contains a `function_call` item:

```json
{
  "type": "function_call",
  "call_id": "call_...",
  "name": "get_weather",
  "arguments": "{\"city\":\"Seoul\"}"
}
```

Parse `arguments` as JSON, validate it against your own schema and
authorization rules, execute the function, and retain `call_id` for the
continuation.

## Return the result

Send the complete conversation state with a `function_call_output` item that
uses the same call ID:

```json
{
  "model": "eb1-preview",
  "input": [
    {
      "role": "user",
      "content": "What is the weather in Seoul?"
    },
    {
      "type": "function_call",
      "call_id": "call_...",
      "name": "get_weather",
      "arguments": "{\"city\":\"Seoul\"}"
    },
    {
      "type": "function_call_output",
      "call_id": "call_...",
      "output": "18 C, light rain"
    }
  ]
}
```

Public eb1 clients should resend full conversation input for continuation;
stateful `previous_response_id` continuation is not a portable eb1 contract.
The next response can contain final text or another tool call. Bound the number
of turns in your application and require explicit authorization for tools with
side effects.

## Surface shapes

| Surface | Tool declaration | Model call | Tool result |
|---|---|---|---|
| Responses | `tools[].type: function`, with flat `name` and `parameters` | `output[]` item with `type: function_call` | `input[]` item with `type: function_call_output` and matching `call_id` |
| Chat Completions | `tools[].function` | `choices[0].message.tool_calls[]` | `role: tool` message with matching `tool_call_id` |
| Messages | tool with `name` and `input_schema` | `tool_use` content block | user `tool_result` content block with matching `tool_use_id` |

Keiro preserves call identity and requires function arguments to represent a
JSON object on portable function-tool paths. A capability mismatch fails
closed; do not silently resend the request without its tools.

## Parallel calls and streaming

Set `parallel_tool_calls` only when your application can execute and correlate
more than one call from the same model turn. Each call keeps its own ID.

Streaming exposes the native tool-delta events for the selected surface. eb1
models can finish a tool call before streaming it, so tool arguments sometimes
arrive as one assembled delta rather than many small fragments. Always
assemble by call ID and wait for the surface's completed tool item before
executing it.

## Portability boundary

Function tools are the documented cross-surface contract. Hosted web search is
the documented hosted tool on OpenAI-format surfaces
(`{"type": "web_search"}`, `tool_choice: "auto"`, billed per search); see
[SDKs and CLI](sdks.md) for the request shape and default behavior. Other
hosted and provider-specific custom tool types can be account-, model-, or
surface-specific; do not assume they are portable unless Keiro documents the
exact tool type for your account.

JSON mode and JSON Schema structured output are separate features and are not
currently supported by strict validation. A function's `parameters` schema is
supported; a response-format schema is not the same contract.

## Related pages

- [Responses](responses.md)
- [Chat Completions](chat-completions.md)
- [Messages](messages.md)
- [Errors](errors.md)
