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 operations

When to Disable Parallel Tool Calls

ScenarioRecommendationReason
Independent operations✅ Keep parallelFaster execution
Dependent operations❌ Disable parallelResults depend on previous calls
Rate-limited APIs❌ Disable parallelAvoid hitting rate limits
Simple execution logic❌ Disable parallelEasier to implement
Stateful operations❌ Disable parallelOrder 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.

Next Steps