Repository navigation
Integrations microsandbox
Experimental: this works and is tested, but may change and gets less hardening than the stable core. Tested: SOCKS5 connections made as microsandbox's source sends them, into a real signer; not yet run against a released microsandbox (#312).
microsandbox runs each sandbox as a microVM (libkrun: KVM on Linux,
Hypervisor.framework on macOS). The sandbox's network stack runs in the msb process on the host, and its
outbound proxy sends
each TCP connection the guest opens through an HTTP CONNECT, SOCKS4 or SOCKS5 proxy, from the host. Code in the guest
can't see that proxy or go around it. Point it at the egress observer and the run gets a signed record
of every host its sandbox reached, made outside the guest.
| microsandbox | Tracekit's egress observer | |
|---|---|---|
| What it does | Runs the agent's code in a microVM; resolves names, applies its network policy, opens each TCP connection through the proxy | Attributes each connection to a run, checks the host, relays the bytes, and reports per-minute totals to the signer |
| Where | The msb process on the host |
tracekit egress serve on the same host, as its own user |
| What a third party can check later | Nothing: its logs aren't signed |
effect.observed records in the run's signed bundle |
The observer's plain loopback listener takes SOCKS5 as well as HTTP: the same port serves both. Use microsandbox's
socks5 protocol. Its http_connect sends no credentials, and it sends an address, which the observer refuses over
CONNECT (403); SOCKS4 isn't taken.
-
Run the observer on the microsandbox host, as its own user, with its own signer identity:
# egress.yaml listen: 127.0.0.1:3128 signer: https://signer.internal:8443 # the observer's identity: TRACEKIT_SIGNER_TOKEN_FILE or _CERT/_KEY
In
signer.yaml, grant that identityobserve_effectand nothing else, and never give it to the agent (egress). Linux system mode's observer (tracekit init --v2 --egress) already listens on127.0.0.1:3128. -
Give each sandbox its run's id and token as SOCKS5 credentials, from the code that creates the sandbox. microsandbox reads the password from a host environment variable when the sandbox starts, so set it just before
create:import asyncio import os from microsandbox import OutboundProxy, Sandbox, SecretSource from tracekit.sdk.client import Client async def main(): with Client().run(agent="my-agent") as run: os.environ["TRACEKIT_RUN_TOKEN"] = run.run_token proxy = OutboundProxy.socks5("127.0.0.1:3128").credentials(run.run_id, SecretSource.env("TRACEKIT_RUN_TOKEN")) async with await Sandbox.create("agent-1", image="python", proxy=proxy) as sb: await sb.shell("pip install --quiet requests") # the sandbox's work, while the run is open asyncio.run(main())
With the CLI:
msb run python --proxy socks5://127.0.0.1:3128 --socks5-username <run id> --socks5-password-env TRACEKIT_RUN_TOKEN. When several runs start at once in one process, give each its own variable name. -
To make every sandbox on the host use the observer whatever the code creating it says, enforce the proxy in microsandbox's managed configuration (
/etc/microsandbox/managed.jsonon Linux):{ "version": 1, "overrides": { "sandbox_defaults": { "outbound_proxy": {"protocol": "socks5", "address": "127.0.0.1:3128"} } } }A managed proxy replaces each sandbox's own, credentials included, so per-run credentials can't be combined with it. Without credentials the observer attributes by identity: on Linux, the uid that runs
msb; the signer gives each connection to that uid's latest open run. On macOS the observer can't read the uid, so it refuses every connection without credentials, and the sandboxes have no network.
On Linux the uid that runs msb goes with the run token too: register the run as that same user (through its signer
socket), or the signer attributes the connections by the uid instead of by the token
(egress).
Every connection msb makes is that one uid's, so all the sandboxes of one msb user share 64 open connections
through the observer, with or without run tokens: one more is closed at once, and the observer says so on stderr
(egress).
microsandbox sends the observer the address it resolved and checked against its own network policy, never a host name
(crates/network/lib/proxy/socks.rs). The observer names the host by the server name in the connection's TLS
ClientHello, and only when that name resolves to the same address on the observer's host (a public one, unless allow
lists it). It then relays the connection to that address. A connection without a TLS server name, or whose name
resolves elsewhere, is closed before anything reaches the host, and the observer says why on stderr.
Each minute, per run, host and port, the signer writes a signed record naming the observer's identity:
effect.observed {observer, kind: net, host, port, bytes_out, bytes_in, connections, first_ts, last_ts,
attribution: token}
A host none of the run's calls or the policy's explains covers is also a reconcile.unexplained_effect. While the
observer heartbeats, the run's coverage matrix says network: observed (enforced with posture: {network: enforced}
in signer.yaml); an observer that stops is a signed observer_lost gap (egress).
- Content: paths, headers and bodies. It doesn't intercept TLS.
-
Names microsandbox resolves: its DNS forwarder doesn't use the proxy, and connections to
host.microsandbox.internalskip it. -
Plain HTTP and other non-TLS TCP: they reach only addresses
allowlists. The observer has no name to record for them. - UDP: microsandbox sends non-DNS UDP as SOCKS5 UDP ASSOCIATE, which the observer refuses, so it fails.
- The guest: nothing about processes or files inside the microVM.
Limits lists each with what to do.
Generated from docs/ at v1.4.1. Edit the docs in the repository, not here.
Get started
- Quickstart: the v2 signer
- Quickstarts
- Quickstart: Claude Agent SDK
- Quickstart: a custom agent
- Quickstart: LangChain and LangGraph
- Quickstart: MCP client
- Quickstart: OpenAI Agents SDK
- Coding agents other than Claude Code
- tracekit doctor
- Walkthrough: Tracekit end to end
How it works
- How Tracekit works
- Overview
- The life of a tool call
- The evidence format
- Verification and assurance
- Witnesses and monitoring
- Policy
- Approvals
- Detection and containment
- Capture and completeness
- Custody
- Provenance and tracekit why
- Deployment and isolation
- Storage, durability and performance
- Integrations
- Security model
- Architecture
- tracekit why: architecture
Integrations
- Integrations
- Adapters
- OpenTelemetry
- Remote clients
- Kubernetes agent-sandbox
- agentgateway
- agentsh and Tracekit
- Browser Use
- Claude Agent SDK
- Claude Code's sandbox
- Codex's sandbox
- CrewAI
- Docker MCP Gateway
- E2B
- Falco
- Gemini CLI's sandbox
- Google ADK
- Haystack
- LangChain v1
- LiteLLM
- LlamaIndex
- MCP client
- microsandbox
- Microsoft Agent Framework
- OpenAI Agents SDK
- NVIDIA OpenShell
- Pydantic AI
- sandbox-runtime's proxy on its own
- Strands Agents
- Tetragon
- Vercel AI SDK
- Wassette
Policy and approvals
- Policy reference
- Approvals
- Findings
- Reading the model's reasoning
- Incidents and containment
- Webhooks
Deploy and operate
- Deploying the signer
- The signer as a container
- The signer on Kubernetes
- The compose stack
- Identity
- Tool executor
- MCP gateway
- LLM gateway
- Egress observation
- Witnesses
- Log monitor
- Record-key issuer
- Signer observability
- Viewer
- tracekit why: causal investigation and replay
- Migrating
- Platforms
Verify the evidence
- Reading a v2 verify report
- Evidence format v2
- Auditor guide
- Sample evidence bundle
- Signing
- What Tracekit guarantees
Security and privacy
- Threat model: the v2 signer
- Threat model: the v1 laptop signer
- HTTP security checklist
- Threat-model review packet
- Privacy
- Known limits and trade-offs
- What's stable
Compliance
- Compliance mapping
- EU AI Act
- ISO/IEC 42001
- NIST AI RMF and the Generative AI Profile
- OWASP Top 10 lists for LLM and agentic applications
Evaluation
Demos
- Demos
- Agent approvers within bounds
- Completeness and tamper evidence
- Detection and containment
- Network coverage: an egress observer
- Guardrails: allow, deny, or ask a person
- MCP tools, gated and recorded
- Prompt injection held by provenance
- Why: which input caused the action
Help