Fenzi

Start

How it works

The agent runs in a sandbox on your machine. A policy decides what it can read, write, and reach. Fenzi writes that policy, starts the sandbox, and keeps the record.

Applies to Free and TeamSandbox: OpenShell 0.1.2

The pieces

The sandbox is OpenShell, an open source runtime licensed under Apache 2.0. Fenzi does not replace any part of it. We pin a version and drive it through its own commands. The sandbox holds the agent process.

PieceWhere it runsWhat it does
Fenzi CLIYour machineCompiles the policy, checks it, starts the sandbox, copies the project in and out, files approvals, reads the log.
GatewayYour machineOpenShell's control process. Holds sandboxes, policies, and credentials for this machine.
SupervisorInside each sandboxApplies the filesystem and process rules at start, and runs the proxy every network call goes through.
AgentInside the sandboxClaude Code, Codex, or another agent, running as an unprivileged user.
Control planeOur cloud, Team onlyHolds the org policy, the approval queue, and the decision log. Never connects to your machine.
Your machine holds the Fenzi CLI, the gateway, and the sandbox. Inside the sandbox, every call from the agent passes the supervisor's proxy. Only allowed hosts are reached. The CLI talks to our cloud outbound only, on Team. YOUR MACHINE fenzi CLI gateway openshell commands SANDBOX agent, unprivileged supervisor and proxy every call supervisor dials the gateway allowed hosts everything else Fenzi cloud Team only outbound only: policy down, decision records up
Nothing connects in to your machine. Your code, keys, and terminal output never reach our cloud. The model vendor still receives what the agent sends it.

What is inside the sandbox

  • The agent's image. Built on your machine from a Dockerfile we publish, with the agent, git, and common tools. We do not redistribute agent binaries.
  • A copy of your project. Uploaded at start, respecting .gitignore. The agent edits the copy. You apply the changes when it exits.
  • Nothing else from your machine. Your home directory is not there, so ~/.aws, ~/.ssh, and your shell history are not there either. Only what is uploaded or built into the image exists.
  • Placeholders instead of keys. The agent's environment holds a placeholder. The real key is added by the proxy, only on requests that the policy allows and only to the endpoints that key belongs to.

Inside, the project folder and /tmp are writable. System folders such as /usr and /etc are read-only. Anything not listed is not reachable at all.

Walls and doors

Some parts of the policy are fixed when the sandbox starts. Others change while it runs. Fenzi always tells you which kind of change you are making.

ChangeKindWhat happens
A host added or removedDoorChecked with the prover, then applied to the running sandbox as a new revision: on Free with fenzi policy apply after you edit fenzi.yaml, on Team when fenzi sync or the forwarder picks up a published revision. A change the prover refuses is not loaded. The sandbox loads it on its next poll, about ten seconds later.
An approved requestDoorSame as above. The agent retries and the call goes through. On Team, the forwarder applies a console approval on its next pass first, so it takes about fifteen seconds.
A path made readable or writableWallThe running sandbox keeps the paths it started with, and Fenzi says so. The next run creates a new one with the new paths.
The user the agent runs asWallSame as above.
Wall: fixed when the sandbox starts

No running sandbox picks up a filesystem change. When a wall moves, Fenzi says the sandbox will be recreated before it does it. It never hides a restart behind a saved message.

When network rules change, open WebSocket connections in the sandbox are closed and clients must reconnect. Plain HTTP requests are not affected.

Keys

Model keys are stored by the gateway on your machine, as OpenShell providers. fenzi key set stores one, or fenzi run creates it from your environment the first time you run an agent. They are never sent to our cloud, on any plan.

Each key is bound to the endpoints it belongs to. A network rule that lets the agent reach a host does not let the key go there. If the agent sends the placeholder to a different host, the request is denied.

What reaches the model

The agent's calls to its model are allowed, because the agent cannot work without them. Whatever the agent puts in a prompt leaves the machine that way: the files it read, command output, and your instructions. The sandbox limits what the agent can read and where else it can connect. It does not read or filter prompts.

Claude Code's web search goes the same way. Anthropic runs the search, so the query travels inside a model call, and the sandbox cannot block it without blocking the model. Fetching a result page from the sandbox is still refused. See Web search.

The log

The sandbox records every network decision it makes, and the gateway on your machine keeps a stream of them in a limited buffer. Fenzi keeps what that stream still holds when it reads it. fenzi log reads the stream while a sandbox runs. When the agent exits, Fenzi saves a copy before it asks whether to delete the sandbox. The save has to come first: deleting the sandbox deletes the gateway's copy.

Each line in the stream is one decision, as text: the time, allow or deny, the program, the destination, and the rule. A deny includes the sandbox's reason. Query strings are left out. The stream does not carry the full audit file the sandbox writes for itself, and that file cannot be read from outside the sandbox. fenzi log and a Team record are both built from these lines. A blocked file write is in neither. The agent sees Permission denied.

On Team, the forwarder follows the same stream for every sandbox Fenzi started and uploads each decision once. If the gateway restarted, or its buffer dropped decisions before they were read, those decisions are gone: the machine reports a gap, and the console shows it for that sandbox and that span of time. So the guarantee is every network decision the gateway still held, with every hole reported. See What our cloud receives.

When our cloud is unreachable

The sandbox keeps enforcing the last policy it loaded. That does not depend on us. On Team, the CLI uses the last signed policy it verified, decision records wait on the machine, and requests stay pending, so the blocked call stays blocked. An enrolled machine that has never received a policy refuses to start a sandbox. Every case is in When something is down.

What a laptop cannot enforce

You own your laptop and the gateway on it. You can change the runtime directly, approve your own requests, or delete a sandbox. On a laptop the developer administers, nothing stops them running an agent outside Fenzi, and Team does not see that run.

On laptops, Team makes the org policy the default path, forwards the decisions and approvals the gateway records for sandboxes Fenzi started, and reports drift: a sandbox running something other than the published policy, or an approval that did not come from the console. Enforcing against the machine's owner needs a gateway they do not administer: the License plan, on a cluster. License is planned and not built yet.

If the sandbox has a bug

Then we have a software bug, and we say so, whichever side of the line it is on. The fix may be upstream: we pin the OpenShell version, read its release notes before every bump, and move the pin when a fix ships. We do not add a second enforcement layer of our own on top of it.