Repository navigation
feat(sdk): spawnFleetSandbox, /fleet and /attach subpaths, sandbox readonlyPaths - #1787
agent-relay-code[bot] wants to merge 23 commits into
Conversation
|
Important Review skippedBot user detected. To trigger a single review, invoke the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
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 |
Ports main's attach changes (relay#1829 decoded repaint, terminal-session replacement) and workspace-transport changes (fallbackBaseUrl, DEV Relaycast route) into the moved @agent-relay/cloud/attach and @agent-relay/cloud/workspace-transport modules. Keeps readonlyPaths in the async-v1 ensure request. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Session-Id: 5fe0438a-3323-4877-8199-91318ed6457a
@agent-relay/sdk/fleet now exports spawnFleetSandbox (D4 option 1): it provisions the sandbox, starts the agent harness, confirms the node the agent landed on, and returns a handle with attach() and an idempotent destroy(). agent-relay fleet spawn --sandbox drives the same function, so the CLI and the SDK contract cannot drift. - An agent that lands on a node other than the ensured sandbox fails closed: the agent is released and an owned sandbox is deleted. - A caller-declared sandboxId is retained by failure cleanup and destroy(). - A non-empty env is rejected rather than silently dropped. - persistWorkspaceRelaycastTarget moves to @agent-relay/cloud/workspace-transport (the CLI re-exports it). - attach tests send base64 terminal.ready screens, matching relay#1829. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Session-Id: 5fe0438a-3323-4877-8199-91318ed6457a
@agent-relay/sdk now imports @agent-relay/cloud/{attach,fleet,workspace-transport},
so the offline-evals job and eval:build must build session, config and cloud first.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Session-Id: 5fe0438a-3323-4877-8199-91318ed6457a
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8c980d44a6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- spawnFleetSandbox: run resolveWorkerCwd/resolveTask inside the cleanup boundary so a throwing hook cannot strand an owned sandbox. - Landing check uses the dispatch receipt (dispatchedNodeId/handlerNodeId); invocation.node/placement.node only echo the requested target. - spawnMetadata is spread before name/cli/task/worker_cwd so it can never replace the fields the handle attaches to and releases. - A reused node without a sandbox identity is refused instead of returning an empty sandboxId. - attach: buffer output for a not-yet-ready raw socket separately from the event-listener replay buffer (reset at each terminal.ready snapshot). - attach: trust the DEV Relaycast origin so a DEV spawn's handle.attach() works. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Session-Id: 5fe0438a-3323-4877-8199-91318ed6457a
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 31968ec0d8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…dary verifySandbox, resolveWorkerCwd and resolveTask may return promises; awaiting them keeps a late rejection inside the cleanup that deletes an owned sandbox. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Session-Id: 5fe0438a-3323-4877-8199-91318ed6457a
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0cdd92b35d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…ed sandbox type - spawnFleetSandbox fails closed unless at least one dispatch receipt id (dispatchedNodeId/handlerNodeId) proves the ensured sandbox node, and none names another node. Verified live: production receipts carry both ids and they equal Cloud's sandbox nodeId. - handle.sandbox is typed RedactedFleetSandboxResult, which omits relaycastTarget.relaycastApiKey, instead of the credential-bearing type. - Test harness stubs persistRelaycastTarget so tests never write a project session or credential store; CLI placement doubles return receipts like the engine does. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Session-Id: 5fe0438a-3323-4877-8199-91318ed6457a
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 813a003617
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
With no /ws listener and a ready raw client, output is now retained as a bounded newest-first ring for a later listener instead of being dropped; the raw client draining the stream is not backpressure, so the session is never ended for it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Session-Id: 5fe0438a-3323-4877-8199-91318ed6457a
A request-less connection-fatal terminal.error after ready now closes the raw stdio socket and settles finished with 1, as broker input sockets are already closed, so socketPath consumers stop writing to a dead session. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Session-Id: 5fe0438a-3323-4877-8199-91318ed6457a
|
@codex review |
… API) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Session-Id: 5fe0438a-3323-4877-8199-91318ed6457a
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e3c17c78bf
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…t at spawn - attach: while the terminal transport reconnects, raw input is paused and unshifted, then resumed at the next terminal.ready, instead of ending a recoverable session. Input overflow on an open transport still ends it. - spawnFleetSandbox resolves the compatibility (no relaycastTarget) transport once at spawn and pins it for attach(), so a later rebind or env change cannot redirect attach to another workspace. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Session-Id: 5fe0438a-3323-4877-8199-91318ed6457a
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1ce7c7c121
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…fatal error - spawnFleetSandbox creates the launcher client on the base URL of the transport it resolved at spawn (verified target or compatibility transport), not the ambient process environment. - attach refuses later raw socketPath clients once a connection-fatal session error has been reported through finished, even when no client was attached. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Session-Id: 5fe0438a-3323-4877-8199-91318ed6457a
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5c155d3c41
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Session-Id: 5fe0438a-3323-4877-8199-91318ed6457a
|
@codex review |
|
Codex Review: Didn't find any major issues. You're on a roll. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Live GREEN proof: production after deploy (e88433bd3, contains 047db016)This run used the relay#1787
Note: the agent could still create a new file locally inside the read-only directory ( |
…ware-garden-139d1a46 Session-Id: 5fe0438a-3323-4877-8199-91318ed6457a
|
@codex review |
|
Codex Review: Didn't find any major issues. Chef's kiss. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 06c3237. Configure here.
startFleetNodeAttachProxy gains pinnedTransport: the given workspaceKey and baseUrl are used exactly instead of re-resolving the selection, where a matching persisted project route could replace the credential or reject the origin. handle.attach() always pins (Relaycast's canonical origin when the spawn transport had none). The CLI's selector semantics are unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Session-Id: 5fe0438a-3323-4877-8199-91318ed6457a
|
@codex review |
|
Codex Review: Didn't find any major issues. Nice work! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
…hangelog and SDK test entries) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
spawnFleetSandbox fails closed (placement_mismatch) unless the engine's dispatch receipt names the ensured sandbox node. The 1656, 1744 and 1746 probes mocked a spawn with no receipt, so 1656 stopped before reaching the output-sink failure it relies on. Their subject is sandbox identity and launcher authority, not placement, so the mocks now report the receipt a real dispatch to that node returns. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Targeted verification shard 23 failed on 🤖 Generated with Claude Code |

Summary
This PR implements the workforce#338 upstream contract (issue #1765), with D4 resolved as option 1:
spawnFleetSandboxstarts a running agent.@agent-relay/sdk/fleet→spawnFleetSandbox(input). It provisions a Cloud fleet sandbox and starts the agent harness through placement, waiting for confirmation by default. It then requires the engine's dispatch receipt (dispatchedNodeId/handlerNodeId) to prove the agent landed on the ensured sandbox node. If no receipt proves it, or a receipt names another node, the call releases the agent, deletes an owned sandbox, and throwsplacement_mismatch. Caller hooks (verifySandbox,resolveWorkerCwd,resolveTask) andpersistRelaycastTargetmay be async; they are awaited inside the cleanup boundary. The launcher client andattach()both use the transport pinned at spawn. It returns aFleetSandboxHandle:sandboxId,nodeId,nodeName,agentName,ownsSandbox, the redactedsandbox, andinvocation;attach({ mode }): a live terminal through a private local socket;destroy(): idempotent; releases the agent, then deletes the sandbox only when this call provisioned it.agent-relay fleet spawn --sandboxnow callsspawnFleetSandbox, passing its repo inference, cwd and task context as hooks and its dependencies for injection. The CLI and SDK cannot drift. All existing sandbox regression tests pass unchanged.@agent-relay/sdk/attach/@agent-relay/cloud/attach:startFleetNodeAttachProxywithsocketPath,finishedandclose(), plus single-agent discovery fromnodeId.readonlyPaths: forwarded in the sandbox ensure request (also via--sandbox-readonly-path). Cloud enforcement: AgentWorkforce/cloud#4303.sandboxIdis retained: failure cleanup anddestroy()never delete it. A non-emptyenvis rejected (unsupported_env) rather than silently dropped, because fleet spawn cannot deliver a per-agent environment yet.Merge of main
Main was merged in. Main's newer attach changes (relay#1829 decoded repaint, terminal-session replacement) and workspace-transport changes (
fallbackBaseUrl, DEV Relaycast route) were ported into the modules this PR moved to@agent-relay/cloud.persistWorkspaceRelaycastTargetmoved to@agent-relay/cloud/workspace-transport, and the CLI re-exports it.Consumer note (workforce#338)
@agent-relay/sdk/fleetand@agent-relay/sdk/attach, not the@agent-relay/cloud/*paths the draft probes.handle.attach(): it carries the verified Relaycast target.startFleetNodeAttachProxy({ node: handle.nodeName, agent: handle.agentName })also works.namefor the agent;label,permissionsandauthModeare not part of the contract.readonlyPathslist is ignored.Live proof (production)
These runs used this branch's
spawnFleetSandboxagainst production Cloud on agent37 (E2B) sandboxes:readonlyPathswas ignored. The mount token keptfs:write, the read-only file was mode 644, an append exited 0, and the server content changed.Local verification (CI does not run on trunk PRs)
Head
5ec40ec9a(trunkmerged in). InheritedRELAY_*/AGENT_RELAY*variables were removed for the test runs.npx npm@10.9.4 ci --ignore-scripts(CI's npm)npm run buildnpm run typechecknpm run lint(cd packages/sdk && npm test)(cd packages/cloud && npm test)npx vitest run packages/cli/ --maxWorkers=4Validation
packages/sdk/src/__tests__/fleet-spawn.test.ts(7 tests) failed beforespawnFleetSandboxexisted. The new CLI test "rejects an agent that lands on another node and tears the sandbox down" fails on the previous CLI and passes now.RELAY_*andAGENT_RELAY*variables removed.broker-lifecycle"keeps the claim when the spawn rejects…" (a file this PR doesn't touch);attach-fleet-node"uses the terminal-session request timeout…". Main's own original CLI attach module fails this one in 4 of 5 isolated runs here, so it is pre-existing.Both pass on re-run.
npm run buildandnpm run typecheckpass; lint reports 0 errors.Release: RELEASE NEEDED
v13.2.0 was cut before this PR merged and does not contain it.
@agent-relay/sdkgains the./fleetand./attachexports and an exact dependency on@agent-relay/cloud(13.2.0). The CHANGELOG is marked[Unreleased - Minor]. workforce#338 needs the next minor release of@agent-relay/sdkand@agent-relay/cloudafter this merges.RelayFlow Proof
featuresandbox-readonly-pathsThe generated base/head probe checks exact request forwarding and the compiled CLI help. Server-side enforcement is proven live in AgentWorkforce/cloud#4303.
🤖 Generated with Claude Code
Note
Medium Risk
Touches Cloud sandbox provisioning, placement verification, and terminal attach—critical fleet paths—but behavior is heavily tested and failures fail closed with cleanup.
Overview
Introduces
spawnFleetSandboxon@agent-relay/sdk/fleetas the single orchestration path for Cloud fleet sandboxes: ensure sandbox, pin Relaycast transport, spawn and confirm the harness, fail closed when the dispatch receipt does not prove the agent landed on the sandbox node, and return a handle withattach()(private stdio socket) and idempotentdestroy().agent-relay fleet spawn --sandboxnow delegates to that function so CLI and SDK stay aligned.Shared Cloud modules are published and re-exported:
@agent-relay/cloud/attach(fleet terminal attach; CLI’s large loopback adapter becomes a re-export),@agent-relay/cloud/fleet, and@agent-relay/cloud/workspace-transport. SDK adds matching./fleetand./attachentries and depends on@agent-relay/cloud.Read-only Relayfile mounts:
readonlyPathson ensure (validated/path/**subtrees) plus--sandbox-readonly-pathon fleet spawn; requests are forwarded to Cloud for server-side enforcement.CI/eval builds now compile session, config, and cloud before the SDK; changelog and docs describe the new APIs.
Reviewed by Cursor Bugbot for commit 8a7e568. Bugbot is set up for automated code reviews on this repo. Configure here.