Skip to content

Embedder mode: run the harness outside the sandbox (hard no-local-tools gate, MCP-sourced coding tools, resumable serve/--json stream) #330

Description

@justrach

Context

The README's Coming soon → Sandboxes bullet already points at this: run the agent's bash/file tools inside an isolated sandbox so untrusted or destructive steps can't touch the host. This issue is the embedder's version of that ask — the pieces that matter when graff is the reasoning loop inside a hosted product rather than a CLI on a laptop.

The industry converged on this split over the last few months (OpenAI's Agents SDK sandbox clients, Anthropic's Managed Agents, Vercel, Cloudflare, Amp; Rivet's writeup "Run Your Harness Outside of the Sandbox" is the clearest articulation): the agent loop runs in a trusted backend; everything the agent executes happens through tool calls into the sandbox. Graff currently only supports the inverse shape for headless embedding.

How embedders have to run graff today

The only deployment shape that works headless right now:

  1. boot a disposable microVM, curl the static graff release into it
  2. inject the tenant CODEGRAFF_API_KEY as process env
  3. printf '%s' "$PROMPT_JSON" | graff --json --yolo --model … --system-prompt … > /tmp/out.jsonl
  4. tail the JSONL from outside (file reads on an interval), parse events, relay to clients

Four problems fall straight out of that shape:

  • Trust boundary. The tenant provider key sits inside the same VM where --yolo bash researches untrusted web content. A prompt-injected env | curl exfiltrates it; everything the harness can reach, a hijacked agent can reach. This also means the embedder can never hand the in-sandbox agent any other credential (internal APIs, user sessions), which walls off entire tool categories.
  • Durability. All run state lives in the VM. If it OOMs, or the embedder's supervisor is redeployed mid-run, the run is unrecoverable — restart from zero is the only option.
  • Streaming/observability. File tailing with no sequence numbers: a supervisor crash loses stream position, and a graff crash can only be diagnosed by scraping /tmp/*.err from outside after the fact.
  • Cost/latency. The VM must boot and download graff before the first token — even for runs that never execute a single command.

Proposal: let the harness run outside the sandbox

Graff runs on a trusted host (the embedder's backend); the sandbox is reached exclusively through tools.

1. Hard no-local-tools gate + remote coding tools

--tools=remote (or --no-local-tools): built-in bash/read/write/edit are hard-disabled for the session — a gate in the binary, not a permissions/prompt-level rule the model could talk its way around — and the coding tools come from a configured MCP server instead. Graff already speaks remote Streamable HTTP MCP, so an embedder can stand up a thin sandbox-proxy MCP (exec/read/write against their microVM provider) and point graff at it. A first-class sandbox backend interface (create/exec/readFile/writeFile/destroy + provider adapters) could come later; MCP-only tool sourcing is the minimal unlock.

2. Resumable event stream + programmatic resume

For serve / --json mode: monotonic sequence ids on emitted events, replay from ?from=N (or a {"resume_from": N} handshake) on reconnect, and API-addressable session resume — so a replacement graff process on a fresh host can pick a run up from the last persisted turn. Sessions already persist for the CLI (/resume); the ask is exposing that through the serve/SDK transport.

3. Lazy sandbox

With tools remote, sandbox creation can defer to the first tool call that needs one. A large share of runs answer from provider knowledge + HTTP tools and never need a VM — those get web-request economics instead of VM economics, and time-to-first-token stops paying the boot+provision tax.

What already exists (why this is close)

  • graff serve (host/port/token) and --json structured stdio (the SDK transport)
  • remote Streamable HTTP MCP client support
  • persisted sessions + /resume in the CLI
  • the permission gate / yolo model for tool approval

The gap is only: (a) a hard switch that removes local execution entirely, (b) event-stream resumability + programmatic session resume, (c) optionally, a first-class sandbox backend API.

A companion gateway-side issue (mintable per-run scoped keys) covers the credential half for anything that still must enter a lower-trust environment.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions