Combining Server and Client Tools
On this page
Hybrid Workflows
The true power of the Responses API emerges when you combine server tools (executed automatically by xAI) and client tools (your custom functions) in a single request. The model orchestrates these tools autonomously, creating complex workflows in just a few lines of code.
Combining Server Tools and Functions
response = client.responses.create(
model="grok-4.20-0309-reasoning",
input="Search for the latest Ligue 1 soccer results and send a summary to my team.",
tools=[
{"type": "web_search"},
{
"type": "function",
"name": "send_team_message",
"description": "Sends a message to the team via Slack",
"parameters": {
"type": "object",
"properties": {
"channel": {"type": "string"},
"message": {"type": "string"}
},
"required": ["channel", "message"]
}
}
]
)
In this scenario, the model:
- Triggers
web_searchautomatically (server-side) to find the results - Incorporates the data into a summary
- Calls
send_team_message(client-side) so your code sends the Slack message
The Hybrid Execution Flow
The flow differs depending on the tool type:
Server Tools Only
Request → [model → web_search → result → model] → Final response
Everything happens on the xAI side. You receive the final response directly with the results integrated.
Client Tools Only
Request → [model → function_call] → PAUSE
Your code executes the function
Result → [model] → Final response
The model pauses, your code executes, then you send the result back.
Hybrid Flow
Request → [model → web_search → result → model → function_call] → PAUSE
Your code executes the function
Result → [model] → Final response
The model uses server tools first (automatically), then calls your function when it needs your infrastructure.
Common Combination Patterns
Search + Action
Combine web_search or x_search with an action function:
tools = [
{"type": "web_search"},
{"type": "x_search"},
{
"type": "function",
"name": "create_report",
"description": "Creates a report in the CRM",
"parameters": {
"type": "object",
"properties": {
"title": {"type": "string"},
"content": {"type": "string"},
"tags": {"type": "array", "items": {"type": "string"}}
},
"required": ["title", "content"]
}
}
]
Calculation + Notification
Combine code_interpreter with a notification function:
tools = [
{"type": "code_interpreter"},
{
"type": "function",
"name": "send_alert",
"description": "Sends an alert if a threshold is exceeded",
"parameters": {
"type": "object",
"properties": {
"metric": {"type": "string"},
"value": {"type": "number"},
"threshold": {"type": "number"}
},
"required": ["metric", "value"]
}
}
]
max_turns and Hybrid Tools
max_turns behavior is important in a hybrid context:
max_turnslimits server-side turns within a single request- When the model calls a client function and your code returns the result, a new allocation of
max_turnsbegins
In practice, this means client calls do not exhaust your server turn budget. The model can perform 3 web searches, call your function, then perform 3 additional searches after receiving the result.
Multi-turn Context with Storage
For complex workflows that span multiple interactions, combine storage and chaining:
# Turn 1: initial search
r1 = client.responses.create(
model="grok-4.20-0309-reasoning",
input="Analyze AI market trends.",
tools=[{"type": "web_search"}, {"type": "code_interpreter"}],
store=True,
max_turns=5
)
# Turn 2: deepen with your internal data
r2 = client.responses.create(
model="grok-4.20-0309-reasoning",
input="Compare with our internal data.",
tools=[{
"type": "function",
"name": "query_internal_db",
"description": "Queries the internal database",
"parameters": {"type": "object", "properties": {"query": {"type": "string"}}}
}],
previous_response_id=r1.id,
store=True
)
Key Takeaways
- Combine server tools and client functions in a single request for hybrid workflows
- Server tools execute automatically; client functions pause generation
max_turnsresets after each client round-trip- Common patterns: search + action, calculation + notification, multi-source aggregation
- Use
store: trueandprevious_response_idfor multi-turn workflows