Eight components or eighty lines: two ways to keep an agent's secrets
A reader asked how our agent sandbox and secrets scheme compare to OneCLI, an open-source platform for running AI agents as a team. Fair question, and the answer is more interesting than “ours is better”, because on one axis theirs is, and checking the comparison turned up a sentence on our own product page that was not true.
What OneCLI is
A team control plane. One sandboxed agent per employee, provisioned from your identity provider, under a team policy, with shared connections, memory, scheduling, and a Slack identity each. It runs on your infrastructure. The runner is outbound-only with no inbound ports, which is the same idea our tunnel client uses to live behind NAT.
The part worth studying is how it handles credentials. The agent never holds one. A Rust gateway sits between the agent and the internet, intercepts outbound HTTPS by acting as a man in the middle, and injects the right credential into each request, matched by host and path. The agent authenticates to the gateway with a token of its own. Secrets sit encrypted at rest, or are fetched on demand from Bitwarden or 1Password.
What we do
Claudette runs the agent in a bubblewrap sandbox that drops every capability, unshares the process, hostname and IPC namespaces, clears the environment, mounts the system read-only, gives the agent a project-scoped fake home, and generates a per-project SSH key inside the sandbox so your own keys never enter it. The whole sandbox definition is about eighty lines of arguments to one program, and you can read them.
Secrets live in git, encrypted with sops to explicit age recipients: an operator key kept offline, and one identity per host, sealed in that host’s TPM where it has one. At use, a secret is decrypted into an allowlisted environment that the sandbox receives. The agent process holds that token for its session.
The honest verdict on credentials
Ask one narrow question: if a prompt injection fully compromises the agent, can it exfiltrate its own credential?
Under OneCLI, no. The agent cannot leak what it never had. Under Claudette, yes. The token is in the environment, and a compromised process can read its environment. On that question their design is stronger, and we would rather say so than have you find it.
Now ask the next question: what is the blast radius of compromising the component that holds the secrets?
Under OneCLI, that component is the gateway, and it decrypts every credential for every agent on the team. Compromise it and you own all of them. It also requires installing a certificate authority in every sandbox so the gateway can read HTTPS, which is a trust decision the README does not discuss. There is no threat model section.
Under our scheme there is no system-wide root by design. Each host protects its own key with its own TPM or passphrase. The operator key is a recipient on everything, kept off any machine, so a dead TPM is not a lost secret. A compromised sandbox leaks the handful of variables allowlisted for that one project and nothing else.
Two legitimate designs that bet opposite ways on centralisation. Theirs accepts one chokepoint with total blast radius to get per-request injection. Ours accepts per-session exposure to avoid any single point that holds everything. Which is right depends on whether you fear the compromised agent or the compromised platform more, and a team should decide that on purpose.
Where the comparison was not close
OneCLI’s sandbox is described as a “sandbox supervisor”. The README does not say what the isolation technology is. Containers, gVisor, a microVM, bare namespaces: not stated. Ours is listed line by line, and “not stated” is not a control. Nothing in their feature list screens what the agent reads for injection before it reaches the model; our sandbox runs a defender over every web fetch, file read and command output. Their approvals are called “deterministic” and the word is never defined; our pairing is explicit, allowlisted, fail-closed, and cannot be changed from inside the channel. And their platform is eight components including a web control plane and a proxy that reads all your TLS, against one launcher and one encryption tool. More parts is more to audit, and more to get wrong.
Where it was not close the other way: multi-tenancy. If you want fifty agents for fifty people under one policy with a dashboard, they have one. Our managed pods are one per customer, and a fleet is a proposal.
The sentence that did not survive
Our Cone of Silence page said the pods had “default-deny egress”. While writing this I checked the mechanism, as the page invites you to. Claudette does not give the sandbox its own network namespace. The sandbox shares the host’s network, and outbound traffic is governed by the host’s firewall and the agent’s own network prompts, not by the sandbox. I had verified that weeks earlier without noticing what it meant for the product page: while building mosh support I watched UDP leave the sandbox freely and was glad it did.
That is not default-deny egress. The page now says what the mechanism does, and the build that would make the stronger claim true is on our list: a network namespace per sandbox with a per-project allowlist enforced inside it, paired with credential injection at the sandbox boundary so the agent process never sees a token at all. That second part is OneCLI’s good idea, and we intend to take it, at the edge of one sandbox rather than in a proxy that holds everyone’s.
What this is really about
A control you can read beats a control you are told about. We lead with that, which means it cuts both ways: it is why eighty lines of bubblewrap are easier to trust than an undescribed supervisor, and it is why a wrong sentence on our own page had to be fixed in public rather than quietly. If you are choosing between the two, read both sources before either sales page, including ours.