Parallel tool calls
One reply can ask for several tool calls at once, for example checking stock in two warehouses, or reading three files. Your code can run them side by side and send all the results back in the next request, which saves round trips. parallel_tool_calls lets you turn this off when your tools must run one at a time.
Today models can already return several calls in one reply, but there is no switch to turn it off.
When to turn it off
| Keep it on (default) | Turn it off |
|---|---|
| Calls are independent lookups. | Each call depends on the previous one’s result. |
| You want fewer round trips and lower latency. | Your tools change shared state (bookings, payments) and must run in order. |
| Your UI asks the user to approve each call. |
Endpoint and auth
POST https://app.syntic.ai/v1/chat/completions (and Messages), Authorization: Bearer sk_live_....
Request field
| Field | Type | Default | Details |
|---|---|---|---|
parallel_tool_calls | boolean | true | false means the reply contains at most one tool call. |
It only matters when tools is set; without tools it is allowed but ignored. With built-in tools, Syntic may still run its own searches in parallel; the setting covers calls returned to you.
Response
With parallel calls, tool_calls holds several entries, each with its own id:
{
"role": "assistant",
"content": "",
"tool_calls": [
{ "id": "call_a1", "type": "function", "function": { "name": "check_stock", "arguments": "{\"sku\":\"LAV-2L\",\"warehouse\":\"leeds\"}" } },
{ "id": "call_b2", "type": "function", "function": { "name": "check_stock", "arguments": "{\"sku\":\"LAV-2L\",\"warehouse\":\"bristol\"}" } }
]
}Rules for returning results
- Add the assistant message unchanged.
- Add one
toolmessage per call, each with the matchingtool_call_id. - Put all of them directly after the assistant message, before any new user message.
- Order does not matter, but keeping the same order as the calls is easiest to debug.
A missing result returns 400 unmatched_tool_result. If one call failed, send an error description as its result rather than leaving it out (see When a tool fails).
Streaming
Each call’s pieces carry an index (0, 1, 2…). Join pieces per index; see Tool calls in a stream.
Examples
curl https://app.syntic.ai/v1/chat/completions \
-H "Authorization: Bearer $SYNTIC_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "Amara S1.2",
"stream": false,
"parallel_tool_calls": false,
"tools": [{ "type": "function", "function": {
"name": "book_slot",
"description": "Book a delivery slot. Fails if the slot is taken.",
"parameters": { "type": "object", "properties": { "slot": { "type": "string" } }, "required": ["slot"] } } }],
"messages": [{ "role": "user", "content": "Book me Tuesday 9am, or Wednesday 9am if Tuesday is gone." }]
}'Errors
| Status | code | param | Cause |
|---|---|---|---|
| 400 | invalid_type | parallel_tool_calls | Not a boolean. |
| 400 | unmatched_tool_result | messages[i] | A call has no result, or a result answers no call. |
Limits
- Up to 16 tool calls in one reply.
- Every call in one reply sees the same conversation; calls cannot depend on each other’s results within one reply.
Build notes for the platform team
- Forward
parallel_tool_callsto the model service where supported; otherwise keep only the first call and set headerx-syntic-tool-calls-truncated: true. - The truncation must happen before any call is streamed to the client.