BuildParallel tool calls

Parallel tool calls

⚠️
Preview — this feature is being built; the design below is the spec.

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

FieldTypeDefaultDetails
parallel_tool_callsbooleantruefalse 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

  1. Add the assistant message unchanged.
  2. Add one tool message per call, each with the matching tool_call_id.
  3. Put all of them directly after the assistant message, before any new user message.
  4. 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

Unified envelope.

StatuscodeparamCause
400invalid_typeparallel_tool_callsNot a boolean.
400unmatched_tool_resultmessages[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_calls to the model service where supported; otherwise keep only the first call and set header x-syntic-tool-calls-truncated: true.
  • The truncation must happen before any call is streamed to the client.
Was this page helpful?