← Back to Blog

Give the agent a computer you can throw away

Kal does not get our production box. Here is how I decide when an agent should call a tool, and when it should get a machine we can delete.

I build the agent that talks to our customers. That means I also decide what it is allowed to touch.

Kal can already do more than reply. It searches knowledge, it calls connectors, it writes an internal note. Every one of those is a tool we shipped on purpose. The model picks an action. Our server runs it. Secrets stay on our side of the line.

The next request I keep getting, from the team and from myself, is: let it write the code for the step we did not build. Parse this export. Clean this CSV. Draw the chart. Run the script and show me if it worked.

That is a real teammate. It is also how you hand a non-deterministic program your production box. I will not do that. I will give it a computer we can delete.

The catalog is a ceiling#

A tool catalog is a product decision. It is also a fence.

If Kal only has the tools we shipped last quarter, a messy spreadsheet with defect rates on a factory line is a shrug. There is no draw_chart tool. There should not be one, either. That job is a script, not a product surface.

A sandbox is the missing middle. The agent writes the script, runs it in a box with no keys, and brings back the image. We did not grow the catalog. We gave the model a place where code is allowed to exist.

I keep the split boring on purpose:

  • Tools for anything stable, privileged, or tied to money, identity, or customer data. Fetch an invoice. Update a ticket. Charge a card. Those stay typed, logged, and filled on the server.
  • Sandbox when the missing piece is computation on untrusted or one-off inputs, and building a tool for it would be theatre.

That is the same line Rashim drew for connectors. secret.* and context.* never enter the model. param.* is the only blank Kal gets to fill. A sandbox is that idea applied to a whole filesystem.

When I reach for a box#

Most of Kal does not need one. Looking up an order or drafting a reply is a closed set of calls. A container would make that slower and more expensive for no gain. Chat has a latency budget. I will not blow it on a cold VM so the architecture slide looks modern.

I reach for a sandbox when all of this is true:

  • The user intent is clear and the work is required to finish the job.
  • We do not have a tool for that exact step, and we should not build one for a one-off.
  • The step can be a short script: parse, transform, render, convert, run a test.
  • Failure is cheap. Crash, hang, or fill the disk, and the box dies with it.

Inside the box the agent can be loud. Outside it should see almost nothing: no process.env, no production credentials, no path back into the app runtime. Network only if the task needs it, and then by policy, not by default.

The split I want on every agent we run, Kal included: trusted runtime on one side (model calls, our tools, secrets, durable state), sandbox on the other (filesystem, processes, generated code). Tools in the runtime may proxy into the sandbox. The model never gets the keys.

What I will not trade#

Isolation is not free, and I will not pretend it is.

Heavy work needs a larger box. Spin that up per conversation and the bill shows up in the same month we are trying to keep resolutions at $0.49. Cap CPU, memory, disk, and wall time. Do not give it more because the first demo felt slow.

Startup latency is the other tax. A cold container can miss a chat-shaped SLA. If the user expects an answer in a second, a fresh Docker VM is the wrong default. Warm pools, snapshots, or a lighter backend for short scripts. Or just ship the tool.

The failure mode I watch for is stuffing the sandbox with the things we were trying to hide. Mount the repo, inject the deploy token, open egress to the internal API, and the boundary is theatre. Secrets stay in the trusted runtime. Inputs and outputs live in the workspace. Delete the box when the turn ends unless we have a reason to keep the filesystem.

A sandbox also does not fix a bad tool. If Kal can call a privileged connector with no approval, prompt injection does not need a shell. The catalog and the box are two different controls. I treat them that way.

What I would actually run#

I do not want four backends. I want one boundary, enforced the same way every turn.

  • Docker when we already run containers and need to see inside the box. Mature, local, inspectable. We own the hardening: drop caps, read-only root, no Docker socket, tight seccomp, network off unless required.
  • Cloudflare Sandbox if the rest of the work already lives on Workers. Fast start. Less "bring your own VM".
  • E2B when we want a workspace that already thinks in "the model wrote this, run it," with snapshots.
  • Vercel Sandbox / eve when the agent loop itself is on eve. That is the shape we are moving our agent toward: loop stays trusted, only shell and files cross the line.

Pick from where the agent already runs, then pick on cold start, isolation, and price. Not from a blog roundup.

How I decide#

If the model only needs to choose among actions I already trust, I give it a tool.

If the model needs to invent the action, I give it a computer I can throw away.

Frequently asked questions

A disposable machine with a tight boundary. The model can write and run code inside it. Secrets, production systems, and the trusted app runtime stay outside.

Use typed tools for stable, privileged actions: charge a card, update a user, look up an order. Use a sandbox when the missing step is computation on one-off or untrusted inputs and you should not ship a tool for it.

Most of what Kal does is tools. Connectors, knowledge search, notes. Those stay in the trusted runtime so secrets never enter the model. A sandbox is for the rare step where the model has to invent the code.

Trusted runtime holds model calls, your tools, secrets, and durable state. The sandbox holds filesystem, processes, and generated code. Tools in the runtime may proxy into the sandbox. The model never gets the keys.

Updated August 2026

Explore SupportWire

Next Up