Skip to content

Parallel Tool Execution

The ParallelToolExecutor runs independent tool calls concurrently, significantly reducing agent turn time when multiple tools can run simultaneously.

The Problem

Sequential execution wastes time when tools are independent:

Sequential (slow):
  read(a.ts) ──► read(b.ts) ──► read(c.ts) ──► grep(TODO)
  Total: 400ms + 350ms + 380ms + 200ms = 1330ms

Parallel (fast):
  read(a.ts) ──┐
  read(b.ts) ──┤──► grep(TODO)
  read(c.ts) ──┘
  Total: max(400, 350, 380) + 200 = 600ms (2.2x faster)

Usage

typescript
import { ParallelToolExecutor } from '@opensin/sdk'

const executor = new ParallelToolExecutor({
  maxWorkers: 8,
  timeout: 30_000,
})

const results = await executor.execute([
  { tool: 'read', args: { path: 'src/auth.ts' } },
  { tool: 'read', args: { path: 'src/db.ts' } },
  { tool: 'read', args: { path: 'src/api.ts' } },
  { tool: 'grep', args: { pattern: 'TODO', path: 'src/' } },
])

Path-Scoped Concurrency

The executor prevents conflicting operations on the same file:

typescript
// These run in PARALLEL (different files):
executor.execute([
  { tool: 'write', args: { path: 'a.ts', content: '...' } },
  { tool: 'write', args: { path: 'b.ts', content: '...' } },
])

// These run SEQUENTIALLY (same file):
executor.execute([
  { tool: 'read', args: { path: 'a.ts' } },
  { tool: 'write', args: { path: 'a.ts', content: '...' } },
])

The locking is automatic — the executor extracts file paths from tool arguments and acquires per-path locks.

Configuration

OptionTypeDefaultDescription
maxWorkersnumber8Maximum concurrent tool executions
timeoutnumber30000Per-tool timeout in milliseconds
pathLockingbooleantrueEnable path-scoped concurrency control

Error Handling

Errors in one tool don't block others:

typescript
const results = await executor.execute([
  { tool: 'read', args: { path: 'exists.ts' } },     // succeeds
  { tool: 'read', args: { path: 'missing.ts' } },     // fails
  { tool: 'grep', args: { pattern: 'fn', path: '.' } }, // succeeds
])

// results[0] = { content: '...' }
// results[1] = { content: 'Error: ENOENT', isError: true }
// results[2] = { content: '...' }

Integration with Agent Loop

The agent loop uses parallel execution automatically when the LLM returns multiple tool calls in a single response:

typescript
const agent = new AgentLoop({
  model: 'claude-sonnet-4-6',
  tools: toolRegistry,
  parallelExecution: new ParallelToolExecutor({
    maxWorkers: 8,
  }),
})

When the LLM says "I'll read these 5 files," all 5 reads happen concurrently instead of one at a time.

Released under the Apache 2.0 License.