Add bounded wait_for poll tool for MCP workers - #449
Conversation
ccdac80 to
bf09e65
Compare
fb39109 to
68d9980
Compare
Greptile SummaryThis PR adds a
|
| Filename | Overview |
|---|---|
| crates/aura/src/orchestration/tools/wait_for.rs | New 1,315-line polling tool implementing bounded probe-and-wait logic with correct invariant enforcement, seam-injectable sleeper/dispatcher for testing, and comprehensive test coverage including edge cases for clamping, timeouts, quiescence, and hanging probes. |
| crates/aura/src/orchestration/orchestrator.rs | Wires WaitForTool into all six provider arms via a lazy closure that correctly defers construction so each arm gets its own Box instance (required because ToolDyn is not Clone); tool is only added when shared_mcp is present. |
| crates/aura/src/mcp_tool_execution.rs | Four log lines that hardcoded "HTTP Streamable" are corrected to "MCP tool" to accurately reflect all transports; doc comment updated to match. |
| crates/aura/src/orchestration/tools/mod.rs | Adds the wait_for module and re-exports its public surface; no issues. |
| crates/aura/src/orchestration/mod.rs | Re-exports StopReason, WaitForError, WaitForOutput, WaitForTool from the top-level orchestration module; straightforward plumbing, no issues. |
Sequence Diagram
sequenceDiagram
participant Model as Worker Model
participant WFT as WaitForTool
participant Eval as ConditionEvaluator
participant Disp as McpProbeDispatcher
participant MCP as MCP Server
Model->>WFT: call wait_for(probe, until, poll_sec, max_wait_sec)
WFT->>WFT: "WaitForCall::parse() — validate & apply defaults/ceiling"
loop each poll cycle (until condition met or bound elapsed)
WFT->>Disp: sample(probe) [raced against remaining budget]
Disp->>MCP: execute_mcp_tool(tool, args)
MCP-->>Disp: observation
Disp-->>WFT: Ok(observation)
WFT->>Eval: observe(observation, elapsed)
alt condition held
Eval-->>WFT: "Some(Matched | Settled)"
WFT-->>Model: "WaitForOutput { reason: matched/settled }"
else "elapsed >= bound"
WFT-->>Model: "WaitForOutput { reason: timeout, last_observation }"
else probe timed out
WFT-->>Model: "Err(ProbeTimedOut) or WaitForOutput { reason: timeout }"
else continue
Eval-->>WFT: None
WFT->>WFT: sleep(min(poll, remaining))
end
end
Reviews (2): Last reviewed commit: "docs(mcp): update execute_mcp_tool doc-c..." | Re-trigger Greptile
68d9980 to
fadc2ee
Compare
workers can now call wait_for to poll an mcp tool repeatedly until a stop condition holds, instead of issuing blind keystrokes sleeps. the tool accepts a probe (any mcp tool with its arguments), a stop condition (regex match, regex not-match, or quiet period), and optional poll and bound seconds. it returns the stop reason, last output, elapsed time, and sample count. a 300s hard ceiling clamps max_wait_sec silently. timeout is a normal result, not an error. registration follows the existing additional_tools seam in build_worker_provider_agent: each provider arm receives a WaitForTool instance when shared mcp is available, via a closure that constructs a fresh Box<dyn ToolDyn> per provider variant. closes #420
execute_mcp_tool is transport-agnostic but its log lines said "http streamable mcp tool" unconditionally. a stdio mcp call would log the wrong transport, which misleads operators tracing execution. replaced with "mcp tool" at all four log sites (call, completed, cancelled, failed).
the function doc-comment still read "execute an http mcp tool" after the log-line rename in 333c812. updated to "execute an mcp tool" to stay consistent with the four log sites changed in that commit.
fadc2ee to
afbd4ff
Compare
Implements the
wait_fortool described in #420.Workers currently sleep blind for a fixed duration or burn model turns on a check/sleep loop. As noted in the issue, this accounts for ~63% of wall-clock time in TerminalBench (7,976s across 436 calls) because the model tends to overestimate. The worker guesses a duration and guesses high.
This adds a polling tool that waits for a caller-supplied condition rather than a fixed timeout. The condition is expressed at call time, so the model has to reason about what done looks like. Stop reasons (
matched,settled,timeout) reflect whether it did.Takes a probe (any MCP tool plus its arguments), a stop condition (
matches,not_matches, orquiet_for_sec), and optionalpoll_sec/max_wait_sec(capped at 300s). Returns the stop reason, last probe output, elapsed seconds, and sample count. A timeout returns the last observation as a normal result, not an error.Hooked up via
additional_toolsinbuild_worker_provider_agentfor all providers when shared MCP is available.Also fixes four log lines in
execute_mcp_toolthat hardcoded "HTTP Streamable" regardless of actual transport.Fixes: #420