Skip to content
API referenceClient tools (functions)

Client tools (functions)

The model selects a function; your application executes it and returns the result.

Model protocol

Claude client functions use the tool_use → tool_result loop with and without a server prompt. Your client executes the function. Formats and restrictions depend on the selected API.

json
{
  "model": "claude-opus-5",
  "max_tokens": 1024,
  "tools": [{
    "name": "get_weather",
    "description": "Weather by city",
    "input_schema": {
      "type": "object",
      "properties": {"city": {"type": "string"}},
      "required": ["city"]
    }
  }],
  "messages": [{"role": "user", "content": "What's the weather in Moscow?"}]
}

The response includes a tool_use block with the tool name and arguments — run it on your side and return the result as a tool_result block.

json
{
  "role": "user",
  "content": [{
    "type": "tool_result",
    "tool_use_id": "toolu_…",
    "content": "Moscow: 18 °C, clear"
  }]
}

Codex tools

Codex supports the client tool loop on Responses, Chat Completions, and Messages; the client executes functions. GPT-6 Sol and GPT-6 Luna advertise parallel tool calls. Preserve original tool/call IDs when returning results and do not translate them across formats yourself.

Kimi, Composer and Grok

FamilyClient tools
KimiAvailable in Messages, Chat Completions and Responses; tool and selection formats depend on the API
ComposerAvailable on all three surfaces; the client executes the tool. Only automatic tool_choice is supported
GrokAvailable on all three surfaces; the client executes the tool. Only automatic tool_choice is supported

Kimi: what is checked locally

  • tools must be an array of objects, a function must have a name, names must be unique.
  • The argument schema is checked for up to 32 levels of depth, 4096 nodes and 256 KiB in canonical form. Going over returns a local 400 before any charge.
  • On kimi-for-coding and kimi-for-coding-highspeed the value tool_choice: "required" is not supported and is rejected locally. On k3 and k3-256k it passes.

Composer and Grok: what a call looks like

The loop works on all three surfaces in their own format. The model returns a call; the client executes the tool and returns its result in the same conversation. Until the result arrives, the request remains unfinished.

SurfaceWhat arrives instead of an answerWhat you answer with
/v1/messagestool_use blocks in content and stop_reason: "tool_use"a tool_result block with the same tool_use_id
/v1/chat/completionschoices[0].message.tool_calls and finish_reason: "tool_calls"a message with role tool and a tool_call_id
/v1/responsesa type: "function_call" item in output with a call_ida function_call_output item with the same call_id

Our own ceilings

An unfinished tool loop has a result-wait limit and a total duration limit. Complete calls in the same conversation and account for the limits below.

LimitValueWhat happens past it
Answering a tool call120 seconds from the moment you received the turn with the callthe run is closed and the part of it already spent is charged. Coming back later starts the conversation from scratch, and you pay for the input a second time
Length of one run600 seconds504 cursor_run_timeout, or an error event with the same code in a stream. The run is charged
Unfinished conversations per keyConcurrent loops waiting for tool results are limited per key429 cursor_key_pause_limit before money is reserved, so the refusal is free. Finish or drop one conversation to start the next

GLM client tools: full roundtrip

The model only selects a function and produces arguments. Your application executes it and returns the result through the same API. Guard does not execute client functions.

  1. Send tools and the user request.
  2. Receive the tool/function call and preserve its ID plus the complete assistant item/message.
  3. Execute the function locally.
  4. Return the result with the original ID and request the final answer.
APICallResult
Chatmessage.tool_calls[].idassistant message + role: tool, tool_call_id
Messagestool_use.idassistant content + user tool_result.tool_use_id
Responsesfunction_call.call_idprevious_response_id + function_call_output.call_id
javascript
const apiKey = process.env.GUARD_API_KEY;
if (!apiKey) throw new Error("GUARD_API_KEY is not set");
const url = "https://api.guardrelay.ai/glm/v1/chat/completions";
async function request(body) {
  const response = await fetch(url, {
    method: "POST",
    headers: {
      authorization: "Bearer " + apiKey,
      "content-type": "application/json",
    },
    body: JSON.stringify(body),
  });
  if (!response.ok) throw new Error(await response.text());
  return response.json();
}
const tools = [{
  type: "function",
  function: {

Messages: return all assistant content

Do not rebuild the assistant message from only tool_use: preserve all content, including thinking blocks and the original tool_use.id.

javascript
const toolUse = first.content.find(block => block.type === "tool_use");
if (!toolUse) throw new Error("GLM did not request the tool");
const nextMessages = [
  { role: "user", content: "Look up invoice QA-42" },
  { role: "assistant", content: first.content },
  {
    role: "user",
    content: [{
      type: "tool_result",
      tool_use_id: toolUse.id,
      content: JSON.stringify({ amount: 7319 }),
    }],
  },
];

Responses: call_id and previous_response_id

json
{
  "model": "glm-5.3",
  "previous_response_id": "<first response.id>",
  "input": [{
    "type": "function_call_output",
    "call_id": "<function_call.call_id>",
    "output": "{\"amount\":7319}"
  }],
  "max_output_tokens": 4096
}

Gemini client tools

Client tools work in all three APIs: the model returns a call, your client runs the function and sends the result. tool_choice takes auto, none, a required call (required or any), and a call of a specific function; none turns off both functions and search. A required call and a call of a specific function cannot be combined with search in one request: such a request gets the error gemini_tool_choice_unsupported. Function names do not repeat within one request, and strict: true is not accepted. Gemini accepts no tools other than functions and search (gemini_tool_unsupported). Send an image in a tool result as base64: a link there gets gemini_inline_media_required.

Muse client tools

Client tools work in all three APIs and go to Meta unchanged: the model returns a call, your client runs the function and sends the result. Provider-side MCP tools are not available through Guard: a request with them gets the error unsupported_tool.

Sections

On this page