docs(design): plan event-driven tool relay (remove relay polling latency)#5232
docs(design): plan event-driven tool relay (remove relay polling latency)#5232mmabrouk wants to merge 3 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
@coderabbitai review |
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughThis documentation set defines the event-driven tool relay design, records current polling behavior and runtime constraints, specifies watcher-assisted wakeups with polling fallback, and tracks open questions, validation status, rollout planning, and next steps. ChangesEvent-driven tool relay
Estimated code review effort: 3 (Moderate) | ~20 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
docs/design/agent-workflows/projects/event-driven-tool-relay/plan.md (1)
184-197: 🩺 Stability & Availability | 🔵 TrivialTreat Daytona capacity assumptions as rollout gates, not settled facts.
open-questions.mdsays concurrent-exec and proxy limits are unverified, but this section presents connection/fd usage as approximately unchanged and one held exec per turn as a safe baseline. Validate per-sandbox and per-organization concurrency, saturation behavior, and recovery before enabling the flag by default.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 90042a55-c167-49ee-8a2f-72e8e784b01e
📒 Files selected for processing (6)
docs/design/agent-workflows/projects/event-driven-tool-relay/README.mddocs/design/agent-workflows/projects/event-driven-tool-relay/context.mddocs/design/agent-workflows/projects/event-driven-tool-relay/open-questions.mddocs/design/agent-workflows/projects/event-driven-tool-relay/plan.mddocs/design/agent-workflows/projects/event-driven-tool-relay/research.mddocs/design/agent-workflows/projects/event-driven-tool-relay/status.md
Adopt the Codex review: atomic temp-plus-rename publication in both relay directions (correcting the seen-set partial-file claim), a coalesced single-flight RelayActivitySource wait contract replacing the bare promise race, arm-watch-then-list ordering in the Daytona exec script, and a Daytona mode where a healthy watch suspends the runner's remote polling (kept 30 s safety poll, justified) with honest request-volume numbers. Make the relay-client.ts/relay-protocol.ts extraction slice 0 of this project (the in-sandbox-tool-mcp sibling consumes it), fold in the watcher-hardening list, rename the flags per hop with a validated clamped window, and merge the expanded test list. Address the four CodeRabbit comments (held-request abort, argv-safe script args, window clamping, three-way latency accounting with capacity assumptions as rollout gates) and the owner's framing points (writer coverage stated up front; rejected alternatives unmistakably rejected). Claude-Session: https://claude.ai/code/session_0127AM79khCdvD2b8BG2joZL
b43de15 to
633df7b
Compare
|
Review round addressed in 633df7b. What changed, per source: Codex P0s (all adopted)
Codex P1s
CodeRabbit (4 inline comments, replied on each thread)
Owner framing points
open-questions.md marks what the review answered (flag naming, backoff fate, sequencing, default-on timing) and adds the new items (Daytona |
…relay modules, shrink v1 Fold the Codex xhigh review into the in-sandbox tool MCP plan. Gate A2 on a new slice 0 restart spike (session/load after a VM stop is adapter behavior, not correct by construction; orphan exit weakened to an expectation). Hand the relay-client/relay-protocol extraction to PR #5232 slice 0 and consume it here, reversing the earlier ordering. Cut the standalone transport-neutral mcp-handler slice and rewrite the unification section honestly (Pi never speaks MCP; the real sharing is the relay client and file protocol). Decide specs delivery now: a file, not an unbounded env variable. Move client tools, Codex-on-Daytona, snapshot bake, Pi-as-MCP-client, watch adoption, and mandatory replay capture to explicit follow-ups. Add the missing warm-reuse edges (session/load, sanitized-ID collision, bundle skew, partial visibility via #5232's atomic rename). Make the internal/user stdio separation structural and fix naming (tool-mcp-stdio.ts, internal-tool-mcp-handler.ts, helpers under engines/sandbox_agent/, ACP entry shapes out of mcp-bridge.ts). Claude-Session: https://claude.ai/code/session_0127AM79khCdvD2b8BG2joZL
Context
Every gateway tool call from a sandboxed harness pays a polling tax today: the in-sandbox writer sleeps in 300 ms steps waiting for the response file, and the runner discovers request files by listing the relay dir every 300 ms (backing off to 1.5 s when idle). That adds roughly 0.3 to 1.8 s of pure waiting per tool call, and on Daytona it also costs ~3 remote
lsexecs per second for the whole turn.This follows the owner decision (2026-07-11, recorded in
mcp-delivery-architecture/gateway-mcp-location.md): the API-hosted tool gateway is rejected, the sandbox talks only to the runner, tool calls stay on the file relay, and the relay's polling latency is addressed as its own feature. This PR is that feature's planning workspace.What the plan proposes
Design only, no runtime code. New workspace at
docs/design/agent-workflows/projects/event-driven-tool-relay/(README, context, research with verified file:line anchors, plan, open-questions, status).The core idea: events are wake signals only; the poll loops stay as the correctness fallback. Each
await sleep(delay)becomesPromise.race([sleep(delay), watcher.wake()]), so a dead watcher degrades to today's behavior, never to a hang.res.json):fs.watchin the sharedrelayToolCall, so Pi's extension and the future Claude MCP shim both get it. Same trick runner-side on the local backend.req.jsonon Daytona): one bounded (25 s) blockingrunProcessholding a tiny node script that lists first (closes the created-before-armed race), watches, prints, exits; the runner re-issues it per window. Replaces ~180 daemon requests/min with ~2.4/min.extNotificationdoorbell (Pi-only, does not cover the MCP shim), tighter polling.What review is needed
This is a plan to interview, not code. Please read
plan.md(five decisions, each with options and why) andopen-questions.md(six questions; Daytona held-exec limits gate the default-on step). Push back on decision 2 (bounded watch exec vs persistent watcher) and decision 5 (flag shape) in particular.https://claude.ai/code/session_01Fr4A5zjs5rsufRaWgWiUNC