Expand description
The async worker side of the ECS tool stage - the sync-ECS ↔ async-I/O bridge for tool execution.
When the pipeline decides an agent’s response has tool calls to run, the
tool-dispatch system builds a ToolJob (the agent plus a boxed async
closure that executes that agent’s batch of calls against its own tool
registry / workdir / policy) and sends it to the tool lane. The lane runs the
batch and reports its ToolOutcome back on the results channel, waking the
tick loop; the tool-collect system applies the results on a later tick.
Concurrency: the lane is a semaphore, not a pool of workers.
ToolLane::serve reads jobs off the channel and spawns one task per batch;
each task holds a permit for as long as it is executing, so
max_concurrent_tools batches run at a time.
It used to be a fixed pool of worker tasks, and that deadlocked. Several
things a batch can await have no time bound at all: a tool-approval prompt, an
ask_user, a wait_for_agent poll that only ends when some other run
finishes. A worker sitting in one of those was a unit of capacity spent on
waiting rather than working, and a parent waiting on a child it had spawned
was holding capacity that child needed to finish. Eight of those and no
agent’s tools ran again, for as long as the daemon lived (issue #191).
A permit, unlike a worker, can be handed back in the middle of a batch. That
is what off_lane does, and it is what makes the deadlock impossible:
waiting costs the lane nothing, and the batch takes a permit again when it has
something to do.
Order: which of two batches submitted together gets in first is not fixed - they race for the permit as separate tasks. Nothing depends on it, since an agent only ever has one batch in flight, and once both are actually waiting the semaphore hands out permits first-come-first-served, so nothing is starved either.
Structs§
- ToolJob
- A batch of tool calls to execute for one agent.
- Tool
Lane - The tool lane: the capacity that bounds how many batches execute at once, and the plumbing a batch needs to report its outcome.
- Tool
Lane Stats - Live occupancy of the tool lane.
- Tool
Outcome - The result of a
ToolJob, applied on a later tick by the tool-collect system.
Functions§
- off_
lane - Await something with no time bound without holding the tool lane.
Type Aliases§
- Boxed
Tool Exec - A boxed, per-agent tool-execution closure. Built by the dispatch system so it captures that agent’s own tool registry, workdir, and policy; run once by the tool lane.
- Tool
Exec Future - The future produced by a boxed tool-execution closure: resolves to
(tool_call_id, result)pairs - the same shape the engine’s tool executors already return.