SPB Git forge

spb/doc-api

Public
2commits 1branches 0releases
15.7 MBsize
maindefault branch
13 days agolast push
Python 88.3% TypeScript 7.6% Shell 4.1%
4.2 KB

# The xAI agentic tool loop — server-side tools, client-side functions, state, max_turns

Status: DOCUMENTED + LIVE_VERIFIED (2026-09-19, grok-4.3: Responses function_call → function_call_output via previous_response_id; server tools web_search / x_search / code_interpreter / mcp / file_search inside single requests; Chat Completions function round trip).

Sources: https://docs.x.ai/developers/tools/overview · https://docs.x.ai/developers/tools/advanced-usage · https://docs.x.ai/developers/tools/tool-usage-details · https://docs.x.ai/developers/tools/streaming-and-sync · https://docs.x.ai/developers/tools/function-calling Last verified: 2026-09-19

# 1. Who executes what (Responses API)

output[] item type Executed by You send back
function_call you {type:"function_call_output", call_id, output}
shell_call (tool shell, env local) you shell_call_output {call_id, output:[{stdout, stderr, outcome}]}
web_search_call, custom_tool_call (x_search sub-tools), code_interpreter_call, file_search_call, mcp_call, image_generation_call, tool_search_call/output xAI (server side, inside the same request) nothing

Stop when a response contains no client-side calls (normally it ends with a message). There is no approval step for MCP (require_approval ignored).

# 2. Loop with previous_response_id (verified)

python
resp = client.responses.create(model="grok-4.3", input="…", tools=tools)
while True:
    outs = [{"type":"function_call_output","call_id":i.call_id,"output":run(i)} for i in resp.output if i.type == "function_call"]
    if not outs: break
    resp = client.responses.create(model="grok-4.3", tools=tools, input=outs, previous_response_id=resp.id)

Server keeps reasoning, server-tool calls and their outputs. Follow-ups may use different tools/params.

# 3. Loop with encrypted state (ZDR / store:false)

Request include:["reasoning.encrypted_content"], keep an input_list, input_list.extend(resp.output) then append your function_call_output items and resend everything (store:false allowed). Verified: replayed reasoning + message items → 200.

# 4. Turns, limits, billing

  • max_turns bounds assistant/server-tool turns within one request; a client-side call ends the request, and the follow-up request gets a fresh budget. Default = server cap. Recommended 1–2 quick, 3–5 balanced, 10+ deep.
  • One turn may run several tools in parallel; parallel_tool_calls:false limits to one call.
  • Billing: only successful server-tool executions count (usage.server_side_tool_usage_details.*_calls, num_server_side_tools_used) — failed attempts (e.g. file_search_call status:"failed") are free; tokens for every intermediate step are billed (input_tokens is cumulative across steps, heavily cached: 7 467 input / 704 cached on a one-search request). Prices: web_search $5/1k, x_search $5/1k (→ per-post/profile pricing from 2026-09-21), code_interpreter $5/1k, file_search $2.50/1k, attachment search $10/1k, MCP tokens only.
  • Rejected-before-generation policy violations on Responses cost $0.05.

# 5. Observability

  • Streaming recommended: watch response.output_item.added for tool items, response.reasoning_summary_text.delta for thinking, response.function_call_arguments.done for client calls.
  • Citations: output_text.annotations[] (url_citation) + inline [[N]](url) (disable with include:["no_inline_citations"]); collections citations collections://….
  • xai-sdk: get_tool_call_type(tool_call) → client_side_tool | web_search_tool | x_search_tool | code_execution_tool | collections_search_tool | mcp_tool; response.server_side_tool_usage map (e.g. {'SERVER_SIDE_TOOL_X_SEARCH': 3}), response.tool_calls (all attempts incl. failed).

# 6. Chat Completions variant

Only client functions: tools:[{type:"function", function:{…}}] → choices[0].message.tool_calls (finish_reason:"tool_calls") → append the assistant message + {"role":"tool","tool_call_id":id,"content":…} → resend full history (stateless). Server-side tools are not available there (422 / 410).

Shared runnable loop: examples/xai/tools/function-calling/ (py/ts/sh) and examples/xai/responses/tool_loop.py.