Skip to content

[API Proposal] Parallel and sequential tool support #4105

@apascal07

Description

@apascal07

Goal

Add ability to mark tools as parallel or sequential, communicate this to LLMs, and execute tool calls in batches grouped by execution mode.


1. Definition-Time API

Go (go/ai/tools.go, go/ai/option.go)

// Parallel (default)
searchTool := ai.DefineTool(r, "search", "Search the web", searchFn)

// Sequential
paymentTool := ai.DefineTool(r, "payment", "Process payment", paymentFn, ai.WithRunSeq())
  • Add Sequential bool to toolOptions in option.go
  • Add WithRunSeq() ToolOption function
  • Store in action metadata under tool.sequential

JavaScript (js/ai/src/tool.ts)

// Parallel (default)
const searchTool = defineTool(registry, { name: 'search', ... }, fn);

// Sequential
const paymentTool = defineTool(registry, { name: 'payment', sequential: true, ... }, fn);
  • Add sequential?: boolean to ToolConfig
  • Store in action metadata

2. Runtime Wrappers

Go (go/ai/tools.go)

ai.Generate(ctx, r, ai.WithTools(searchTool, ai.SeqTool(paymentTool)))
  • SeqTool(t Tool) Tool - wraps tool to run sequentially
  • ParallelTool(t Tool) Tool - wraps tool to run in parallel

Implementation note: Works like existing dynamic tools (NewTool). The wrapper implements Tool, delegates execution to the wrapped tool, and overrides Definition() to set sequential in metadata. Gets registered in child registry via resolveUniqueTools, shadowing parent.

JavaScript (js/ai/src/tool.ts)

generate({ tools: [searchTool, seqTool(paymentTool)] });
  • seqTool(tool: ToolAction): ToolAction - wraps tool to run sequentially
  • parallelTool(tool: ToolAction): ToolAction - wraps tool to run in parallel

Implementation note: Simpler than Go - no registry round-trip. Just returns a new ToolAction with modified __action.metadata.sequential. The tool objects are used directly in resolveToolRequests.


3. LLM Communication

Append hint to description AND include in metadata:

description += " [SEQUENTIAL: Will be executed one at a time, in order]"
metadata["sequential"] = true
  • Go: In Definition() method
  • JS: In toToolDefinition() function

4. Batch Execution

Group tool calls by execution mode, preserving order:

Input:  [search (parallel), fetch (parallel), payment (sequential), notify (parallel)]

Batches:
  Batch 1 (parallel):   [search, fetch]  → run concurrently
  Batch 2 (sequential): [payment]        → run alone
  Batch 3 (parallel):   [notify]         → run
  • Go: Modify handleToolRequests() in generate.go - look up sequential from tool definition metadata
  • JS: Modify resolveToolRequests() in resolve-tool-requests.ts - check tool.__action.metadata?.sequential

5. Backward Compatibility

  • Tools are parallel by default (matches current behavior)
  • Existing tools continue to work unchanged

Metadata

Metadata

Labels

featureNew feature or requestgojs

Type

No type

Projects

Status

No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions