Tool Round-Trips
Client-side tool execution for safe, transparent function calling.
Overview
All tools in Sixerr are client tools. When the agent wants to call a tool, the call is routed back to the client. The client executes the tool locally and sends the result back in a follow-up request. This is the core safety mechanism — nothing executes on the plugin owner's machine.
The plugin agent runs with tools deny [*], preventing any local tool execution. Even if a tool definition were somehow executed locally, the clientTools conversion provides defense-in-depth.
Defining Tools
Include tool definitions in the tools array of your request:
{
"model": "claude-sonnet-4-20250514",
"input": "What's the weather in San Francisco?",
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather for a location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name"
}
}
}
}
}
]
}
You can control when tools are used with tool_choice:
| Value | Behavior |
|---|---|
"auto" | Agent decides whether to call a tool (default) |
"none" | Agent will not call any tools |
"required" | Agent must call at least one tool |
{"type":"function","function":{"name":"get_weather"}} | Agent must call the specified tool |
Tool Call Flow
Tool execution is a multi-turn conversation. Here is the complete flow:
Send a POST /v1/responses request with tool definitions in the tools array.
The response comes back with status: "completed" and an output item of type function_call:
{
"id": "resp_1",
"status": "completed",
"output": [
{
"type": "function_call",
"id": "fc_1",
"call_id": "call_abc123",
"name": "get_weather",
"arguments": "{\"location\":\"San Francisco\"}"
}
],
"usage": { "input_tokens": 25, "output_tokens": 15, "total_tokens": 40 }
}
Parse the arguments JSON string, execute your function, and produce a result.
Send a new POST /v1/responses request with the entire conversation history, including the tool call and its output:
{
"model": "claude-sonnet-4-20250514",
"input": [
{
"type": "message",
"role": "user",
"content": "What's the weather in San Francisco?"
},
{
"type": "function_call",
"call_id": "call_abc123",
"name": "get_weather",
"arguments": "{\"location\":\"San Francisco\"}"
},
{
"type": "function_call_output",
"call_id": "call_abc123",
"output": "{\"temp\":72,\"condition\":\"sunny\",\"humidity\":45}"
}
],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather for a location",
"parameters": {
"type": "object",
"properties": {
"location": { "type": "string" }
}
}
}
}
]
}
The agent processes the tool result and generates a text response:
{
"id": "resp_2",
"status": "completed",
"output": [
{
"type": "message",
"id": "msg_1",
"role": "assistant",
"content": [
{
"type": "output_text",
"text": "The weather in San Francisco is currently sunny, 72 degrees with 45% humidity."
}
]
}
],
"usage": { "input_tokens": 80, "output_tokens": 20, "total_tokens": 100 }
}
Key Points
- Stateless conversation: The client must send the full conversation history with each request. The server does not store any state between requests.
- Multiple tool calls: A single response may contain multiple
function_calloutput items. Check all output items and execute each tool before sending the follow-up request. - call_id matching: The
call_idfield connects tool calls to their outputs. It must match exactly between thefunction_callandfunction_call_outputitems. - Streaming tool calls: In streaming mode, watch for
response.function_call_arguments.deltaevents to receive argument chunks, andresponse.function_call_arguments.donefor the complete call. See the Streaming page for details. - Each turn is a separate payment: Every POST /v1/responses request requires its own x402 payment. A multi-turn tool conversation results in multiple payments.
Tool Security
Sixerr implements defense-in-depth for tool safety:
- Client-side execution only: All tool calls are returned to the client. The agent never executes tools directly.
- tools deny [*]: The plugin agent's configuration explicitly denies all local tool execution.
- clientTools conversion: Tool definitions are converted to clientTools format, ensuring they are treated as client-executed even if the deny list is somehow bypassed.
The client is responsible for validating tool arguments before execution. Always sanitize inputs from the agent, especially for tools that interact with file systems, databases, or external services.