Callbacks from a sandbox
A sandboxed worker reaches Kraft through a channel of its own. This page covers the shim it calls, how each harness's permission check travels, and what changes without network:.
The kraft shim
Under a network policy a sandboxed worker reaches Kraft through its session's own channel, the one its proxy runs on. Every such container has Kraft's kraft shim, a sh and curl script, mounted read-only at /opt/kraft/bin and first on its PATH (the image's own PATH after it).
The shim has only the verbs a worker needs, each for the worker's own item only:
kraft item progress Kkraft item reply THREAD --body ...kraft item retry: an escalation turn may retry its item, and a worker's own retry is answered403kraft view show|threadskraft view events [--after N] [--type T]kraft admin permission-hook HARNESS
view events answers the item's history as JSON (all of it, or the part --after and --type keep). The history holds what a person wrote in a steer or a gate note, and every permission decision. There is no -f inside.
There is no kraft view diff or compare inside: Kraft reads no git in a worktree while a sandboxed session runs in it, and the worker has git itself.
The shim sends each call to http://kraft through the proxy, which answers it in the Kraft server itself, never forwarded anywhere.
A call acts as the session whose channel it came in on, whatever headers or token the worker sends. It acts only on that session's own work item: its progress, replies on its own item's threads, its own permission asks, and reads of its own item. An escalation turn may also retry that item.
A call to anything else is answered 403 and recorded as a sandbox_egress_refused event, like a refused host. A worker's own retry of its item passes the channel, and the API refuses it with 403 ("a worker session cannot act on its own work item"); no event is recorded for that one. No allow list entry is needed for any of this.
Permission checks under network:
- Codex. Its hook is the shim's
admin permission-hook codex.- The hash Codex needs to trust the hook is asked of the image's own
codex, in a short container with no network, since Codex silently skips a hook it does not trust and runs the call. - When that cannot be done (the image's Codex does not start, or does not trust the hook), the task is refused.
- When the shim gets no answer from Kraft, it prints Codex's own deny.
- The hash Codex needs to trust the hook is asked of the image's own
- Claude. Launched with Kraft's MCP server at
http://kraft/mcpand no other (--strict-mcp-config), which answers its permission tool for that session alone. - Cursor ignores a proxy, so it is refused under a network policy.
Without network:
Kraft sets up no channel to itself: the container has no kraft command and no Kraft MCP server. Kraft does not restrict the container's network either, so do not rely on this configuration to keep a worker away from the host: see Security.
For that reason every launch into a sandbox without network: is refused, whatever the harness, unless the sandbox sets unrestricted_network: true. That key says you accept an unrestricted network and gates that are not enforced; it cannot be set together with network:.
With it, a sandboxed Claude task is still refused before it starts (its permission tool would be missing and the CLI would exit), as is a Codex or Cursor task with a tool policy (allowed_tools, deny_tools or a grant other than git-commit). For a task that does start:
- Prompts do not tell the worker to run
kraft: it tags its commits with the task number instead of reporting progress, and says what it did about each review thread in its result. - No reply agent is launched for review threads: a
commentreview answersreply_agent: false, and the item records areply_agent_skippedevent saying why. - An escalation turn cannot resume the chain itself: you retry it.
Related
- Network policy: the channel the callbacks travel on.
- Sandboxed workers: what else reaches the container.
- Resource limits: the CPU, memory and process limits of a sandbox's container.