Giving an AI agent shell access: seven forks we had to decide
Seven decisions that decide whether agent autonomy is safe to ship: approvals, the account, secret files, release source, verified completion, coordination and release scope.
The short answer
Giving an agent a shell is not one decision. It is seven, and five of them are about the machine rather than the model: what may run without a question, which operating-system account runs it, who can read a credential file, whether production is built from a commit, and what the word "done" is allowed to mean. We tested all seven on our own product and kept the narrower access mode until the isolation work lands.
Three independent reviews of the same packet produced two factual errors. A single check on the server settled both. That is the part worth publishing: reviewers should receive the results of checks, not a retelling of the problem.
Vendor-authored engineering record, observed 28 October 2026. It is not a benchmark, not an independent audit and not a claim that Tvijo is better than another tool. Scores are deliberately absent: the only numbers here are ours, with a date and a way to reproduce them.
The seven forks at a glance
| Fork | The question in plain words | Cheap default | What we chose | What it costs | What would change it |
|---|---|---|---|---|---|
| Approvals | Remove the questions, or keep a floor under them? | Remove every confirmation | No questions inside an isolated task; the floor of hard denials stays | Every task needs its own working copy | A sandbox that provably cannot reach production makes the floor redundant |
| Privilege | Run as the administrator account, or as a dedicated one? | Run as root because it already works | A dedicated account with an empty home | Provisioning, ownership of outputs, a login shell to disable | Evidence that the sandbox already denies the same paths |
| Secrets | Promise that keys are not passed, or make them unreadable? | "We do not put keys in the environment" | File modes plus an explicit mount list | An audit of every reader before tightening anything | A machine with no other local accounts |
| Release source | Edit the copy that runs, or build from a commit? | Edit the running copy, it is faster | Commit, rebuild, restart; the edit does not exist until then | A restart window and a rebuild step | A deployment that reads committed artefacts by construction |
| Completion | Trust the model's "done", or check it? | Trust the agent's own report | Engine predicates per task class | The engine must record every tool call | A task class where no check exists yet |
| Coordination | Read other agents' session logs, or read a board? | Feed raw logs to a model | A small deterministic board: owner, pid, task, working copy | Heartbeats and a script that has no model in it | A queue that already reports its own state |
| Release scope | Ship autonomy, or ship verified autonomy? | Ship the feature now | Ship the narrow mode until the first five forks are closed | A slower public release | Isolation landing earlier than expected |
None of the seven is exotic. Each one is cheap to decide badly and expensive to discover later.
Two access modes on five commands
We evaluated the released command policy without executing anything, then recorded the decision for each command in both modes.
| Command | Narrower mode (parsed, bounded to the folder) | Wider mode (direct host shell) |
|---|---|---|
git push origin main |
asks first, because it leaves the machine | runs, no question |
git push --force origin HEAD:main |
refused | runs, no question |
git -C . reset --hard |
refused | runs, no question |
rm -rf of the whole workspace folder |
blocked by the folder bound | runs, no question |
crontab -r |
runs, no question | runs, no question |
Read this as behaviour, not as a security score. Three of five commands go from "refused or questioned" to "no question". The fifth row is the honest one: the narrower mode never had a rule for the scheduler either. A short list of patterns is protection against an accident, not a boundary β and a list that is short enough to read is short enough to walk around with a different spelling of the same command.
Where three reviewers disagreed, and what the check showed
The same packet went to three reviewers from different model families. They agreed on the order of work and disagreed on isolation. Both disagreements were resolved by looking at the machine, not by arguing.
| Reviewer claim | What the check showed | What it changes |
|---|---|---|
| "A dedicated account cannot reach the working tree, so you must choose between open and unreachable" | The tree is world-readable and not world-writable | The real choice is "read, cannot write", which is enough for code and not enough for credentials |
| "A dedicated account is sufficient" | A file's own mode decides who reads it, and older copies of a key file keep their own mode | The account is the first step; the mount list and the file modes are the boundary |
| "Real isolation needs a container platform" | A sandbox runtime was already installed and the project already had a written sandbox contract | Reuse it. Building a platform was never required |
The reviewers also missed something a status check finds in one line: a worker supervisor on this machine had been failing for six days. No review mentioned it, because no review was asked to look at running state. A board that lists processes would have shown it immediately.
What "done" is allowed to mean
The engine returns done when the model's own message says done. Nothing on that path counts how many tools actually ran. That is acceptable for a chat answer and unacceptable for a task that claims to change code.
| Task class | Predicate the engine can check | What is not enough |
|---|---|---|
| Change code | An engine-recorded edit, then an engine-run check after the last edit | The model quoting a passing test it never ran |
| Answer a research question | The tree hash is unchanged, and the tool log contains the reads the answer relies on | A confident answer with no tool calls |
| Diagnose | The probe exists in the log, and the returned code matches the log entry | A plausible cause invented from the prompt |
The same principle already applies to review: a reviewer is credited when its structured event completes, not when its exit code is zero.
The receipt we want for every task
- What changed, by path.
- Which checks the engine itself ran, and when, relative to the last edit.
- Metered money, read from the ledger rather than from the agent's report.
- Subscription usage in calls and tokens, separately β not converted into dollars.
- Whom we asked and what they answered.
Point five is why the receipt matters commercially. The same question cost $0.0038 on the cheapest lane we used and $0.0693 on the most expensive one: eighteen times the price for the same eight-part answer. Without a receipt, choosing a reviewer is taste; with one, it is a routing decision that can be audited later.
What we deliberately do not do
- Build our own container platform when a sandbox runtime is already present.
- Send another agent's raw session log to a paid model to find out what it is doing.
- Publish a wider access mode before isolation exists.
- Sell "keys are not inherited by the environment" as a security boundary. It is a statement about a process, not about a file.
β οΈ When this does not work
- One person, one machine, no other local accounts. Most of the seven forks collapse into "it does not matter"; isolation then buys reproducibility, not safety.
- A dirty baseline. If the working copy is already modified, "the tree changed" proves nothing. You need a start hash or a snapshot before the task, otherwise the check is theatre.
- Slow or flaky checks. If the test suite takes an hour, "the engine ran a check after the edit" becomes a formality. Keep a short list of fast checks and say which ones were required.
- An agent that never calls a tool. Our starting problem was exactly this: the agent reported a refusal without trying. Completion checks do not fix a capability claim; check the capability first.
- A tight budget. A second opinion costs money. An eighteen-fold spread between lanes is a reason to route by task class, not a reason to always buy the expensive reviewer.
Ask for a scoped review
If you are choosing where to start on your own machine, the form below asks which of the seven forks you want reviewed first. We answer with what we would change, in what order, and what we would need to see on your side. No payment is taken here, no system access is granted, and no credentials should be sent.
Method and sources
Observed on 28 October 2026. Inspected: the released extension package, the reviewed source snapshot, the running service configuration and the command policy as shipped. Measured: the policy decision for five commands in two modes, the metered cost of three reviews from the transport ledger, and the process state of a worker supervisor.
Not done, and not claimed: no penetration test, no independent audit, no load benchmark, no paid activation of any client, no real customer pilot. The page describes decisions and their costs, not a security certification.
Restated for clarity: the four numbers in this page are ours, and each one can be recomputed from the artefacts kept with the task. Where we could not check a statement, it is written as a claim of a reviewer, not as a fact.
Related reading
- Permissions and data: what the workspace may read, and what stays out of reach.
- Costs and budgets: why a per-call ceiling is not a per-task ceiling.
- Product comparison: three entry points into one product and what each of them can do.
π Article connections
Open the full knowledge graph βNext steps
Related reading
DSHREM robustness audit, October 2026
Six defects found in cancellation, retry, fallback and cost accounting. One money bug is fixed and covered by tests; five remain open with exact locations.
Costs, access and recoveryRecovery after a failed, stuck or uncertain run
No automatic paid retries, an uncertain task blocks further spend, and reconcile never resends inference. The exact commands to get unstuck.
Costs, access and recoveryPermissions and data flow
What leaves your machine, what stays local, and which actions need an explicit human decision β including the licence question people skip.
Costs, access and recoveryRunning a Tvijo pilot and measuring the benefit
A pilot that can be judged: one workflow, one acceptance check, four numbers per week, and exit criteria agreed before the first task.
π¬ Comments