feat(agent-sdk): per-session sandbox workspaces (Pattern C)#6
Merged
Conversation
Each interactive session and headless run can get its own isolated microVM sandbox as a disposable workspace, behind the agent-sdk-harness `sandbox` feature. The .claude/ projection is staged into the sandbox, the agent's exec/file is routed there via an in-process `run_in_sandbox` tool (host Bash/Write/Edit disabled = true containment), and the workspace is discarded - or snapshotted to the warm pool - on close. One SandboxClient is shared between the Rust harness and the Python tool so both resolve the workspace from a single registry (no Arc serialized across the boundary). - agent-sdk-core: add AgentSdkConfig.sandbox_workspace_id (plain data) - agent-sdk-harness: `sandbox` feature; workspace module (config/disposition/ registry); render_projection refactor + stage_into_sandbox sink; acquire/release/apply_containment wired into run/start_session/stop_session - py-bindings: SandboxClient.attach() + harness_arc(); from_python_backend sandbox=; enable harness `sandbox` feature - python: _make_run_in_sandbox factory + sandbox= plumbing through ClaudeAgentSDKBackend/_build_options/agent_sdk_backend/harness - umbrella: agent-sdk-sandbox forwarder feature; docs + CHANGELOG + README Tests: 19 harness tests pass with the feature (11 new, MockBackend, network-free), 9 without (base parity); py-bindings + full workspace + umbrella forwarder build; Python smoke verifies the shared-registry attach+exec path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pattern C — per-session sandbox workspaces for the Agent SDK harness
Contains the harness's
bypassPermissionsdefault for untrusted work: eachinteractive session (and each headless run) can get its own isolated microVM
sandbox as a disposable workspace. Feature-gated (
agent-sdk-harness/sandbox)and off unless
spec.workspace.enabled.What it does
.claude/projection into the sandbox (write_file) insteadof the host filesystem — necessary because a
SandboxHandlehas nohost-visible mount, so the host
claudeCLI can'tcdinto it.run_in_sandboxtool bound to the session's sandbox and disables hostBash/Write/Edit(true containment).close; warm starts fork from the
SnapshotPool.The shared-registry seam (no Arc serialized across PyO3)
One
SandboxClientis passed to the harness; the Rust side holds the sameArc<SandboxHarness>, and the Pythonrun_in_sandboxtool closes over the sameclient — so the per-session sandbox the harness creates is the exact one the
tool execs into. The session's
SandboxIdrides the normal config round-trip(
config.sandbox_workspace_id);SandboxClient.attach(id)binds the tool.Changes
AgentSdkConfig.sandbox_workspace_id(plain, optional data).sandboxfeature;workspacemodule(
SandboxWorkspaceConfig/WorkspaceDisposition/SessionWorkspace/WorkspaceRegistry);render_projectionrefactor (pure renderer reused bythe host-fs
materializeand the newstage_into_sandboxsink);acquire_workspace/release_workspace/apply_containmentwired intorun/start_session/stop_session.SandboxClient.attach()+harness_arc();from_python_backend(sandbox=…); harness built withfeatures=["sandbox"]._make_run_in_sandboxfactory;sandbox=plumbed throughClaudeAgentSDKBackend/_build_options/agent_sdk_backend/harness.agent-sdk-sandboxforwarder feature.Tests
cargo test -p atomr-agents-agent-sdk-harness --features sandbox— 19 pass(11 new, MockBackend, network-free): acquire+stage, exec routing, containment
flags, discard, snapshot, warm reuse, disabled path, enabled-no-client, two
quotas, headless discard, projection parity.
cargo test -p atomr-agents-agent-sdk-harness— 9 pass (base parity, nofeature compiled).
cargo build --workspace,cargo check -p atomr-agents-py-bindings,cargo build -p atomr-agents --features agent-sdk-sandbox— all build.attach+ exec pathand harness construction with a workspace-enabled spec.
Pattern B (whole
claudeCLI inside the VM via aSandboxAgentSdkBackend) anda host-side credential proxy are noted as future roadmap.
🤖 Generated with Claude Code