Parallel Tool Calls
Control whether the model can request multiple tool calls simultaneously for efficient multi-step operations.
What are Parallel Tool Calls?
When using tool calling, models can request multiple tools to be executed at once. This is useful for independent operations but may complicate execution logic. The parallel_tool_calls parameter lets you control this behavior.
🔄 Parallel (Default)
Model can request multiple tools at once
Faster for independent operations
1️⃣ Sequential
Model requests one tool at a time
Simpler execution logic, better for dependent operations
Default Behavior (Parallel Enabled)
parallel-default.ts
import OpenAI from 'openai';
const client = new OpenAI({
baseURL: 'https://www.superagentstack.com/api/v1',
apiKey: process.env.OPENROUTER_KEY,
defaultHeaders: { 'superAgentKey': process.env.SUPER_AGENT_KEY },
});
const tools = [
{
type: 'function',
function: {
name: 'get_weather',
description: 'Get weather for a city',
parameters: {
type: 'object',
properties: { city: { type: 'string' } },
required: ['city']
}
}
},
{
type: 'function',
function: {
name: 'get_time',
description: 'Get current time for a timezone',
parameters: {
type: 'object',
properties: { timezone: { type: 'string' } },
required: ['timezone']
}
}
}
];
const response = await client.chat.completions.create({
model: 'openai/gpt-4o',
messages: [{
role: 'user',
content: 'What is the weather and time in Tokyo and New York?'
}],
tools
// parallel_tool_calls defaults to true
});
// Model may return multiple tool calls at once:
// [
// { function: { name: 'get_weather', arguments: '{"city":"Tokyo"}' } },
// { function: { name: 'get_weather', arguments: '{"city":"New York"}' } },
// { function: { name: 'get_time', arguments: '{"timezone":"Asia/Tokyo"}' } },
// { function: { name: 'get_time', arguments: '{"timezone":"America/New_York"}' } }
// ]
const toolCalls = response.choices[0].message.tool_calls;
console.log(`Received ${toolCalls?.length || 0} tool calls`);Disabling Parallel Tool Calls
Set parallel_tool_calls: false to force the model to request only one tool at a time.
sequential-tools.ts
const response = await client.chat.completions.create({
model: 'openai/gpt-4o',
messages: [{
role: 'user',
content: 'What is the weather and time in Tokyo and New York?'
}],
tools,
parallel_tool_calls: false // Force sequential tool calls
});
// Model will return only ONE tool call:
// [{ function: { name: 'get_weather', arguments: '{"city":"Tokyo"}' } }]
// You'll need multiple round trips to complete all operationsWhen to Disable Parallel Tool Calls
| Scenario | Recommendation | Reason |
|---|---|---|
| Independent operations | ✅ Keep parallel | Faster execution |
| Dependent operations | ❌ Disable parallel | Results depend on previous calls |
| Rate-limited APIs | ❌ Disable parallel | Avoid hitting rate limits |
| Simple execution logic | ❌ Disable parallel | Easier to implement |
| Stateful operations | ❌ Disable parallel | Order matters |
Handling Parallel Tool Calls
handle-parallel.ts
const response = await client.chat.completions.create({
model: 'openai/gpt-4o',
messages: [{ role: 'user', content: 'Get weather for Tokyo and New York' }],
tools,
parallel_tool_calls: true
});
const message = response.choices[0].message;
if (message.tool_calls && message.tool_calls.length > 0) {
// Execute all tool calls in parallel
const toolResults = await Promise.all(
message.tool_calls.map(async (toolCall) => {
const args = JSON.parse(toolCall.function.arguments);
let result;
switch (toolCall.function.name) {
case 'get_weather':
result = await getWeather(args.city);
break;
case 'get_time':
result = await getTime(args.timezone);
break;
default:
result = { error: 'Unknown function' };
}
return {
role: 'tool' as const,
content: JSON.stringify(result),
tool_call_id: toolCall.id
};
})
);
// Send all results back to the model
const finalResponse = await client.chat.completions.create({
model: 'openai/gpt-4o',
messages: [
{ role: 'user', content: 'Get weather for Tokyo and New York' },
message,
...toolResults
],
tools
});
console.log(finalResponse.choices[0].message.content);
}Sequential Tool Call Workflow
sequential-workflow.ts
async function runSequentialTools(userMessage: string) {
const messages: any[] = [{ role: 'user', content: userMessage }];
while (true) {
const response = await client.chat.completions.create({
model: 'openai/gpt-4o',
messages,
tools,
parallel_tool_calls: false // One tool at a time
});
const message = response.choices[0].message;
messages.push(message);
// Check if model wants to call a tool
if (!message.tool_calls || message.tool_calls.length === 0) {
// No more tool calls, return final response
return message.content;
}
// Execute the single tool call
const toolCall = message.tool_calls[0];
const args = JSON.parse(toolCall.function.arguments);
const result = await executeFunction(toolCall.function.name, args);
// Add tool result to messages
messages.push({
role: 'tool',
content: JSON.stringify(result),
tool_call_id: toolCall.id
});
// Continue loop for next tool call or final response
}
}
const answer = await runSequentialTools('What is the weather in Tokyo?');
console.log(answer);curl Example
bash
curl -X POST https://www.superagentstack.com/api/v1/chat/completions \
-H "Authorization: Bearer $OPENROUTER_KEY" \
-H "superAgentKey: $SUPER_AGENT_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-4o",
"messages": [{"role": "user", "content": "Get weather for Tokyo and NYC"}],
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get weather for a city",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"]
}
}
}],
"parallel_tool_calls": false
}'Best Practices
Start with Sequential
If you're new to tool calling, start with
parallel_tool_calls: falsefor simpler implementation, then enable parallel calls for optimization.Handle All Results
When parallel calls are enabled, make sure to handle all tool results before sending them back to the model.
Error Handling
With parallel calls, one failure shouldn't block others. Use
Promise.allSettledinstead of Promise.all if you want to continue despite errors.