A tool call ends when it returns. A script stays.
Why Glove gives agents a persistent, sandboxed working environment instead of a menu of tools, and what ninety runs taught us about where it actually fails.

Watch a developer work and you will not see them pick actions from a menu. You will see them make a directory, drop the inputs in it, write a script, run it, look at the output, fix the script, run it again, and leave the script there because they will need it tomorrow. The environment accumulates. That is where most of the leverage in software comes from.
Now watch an agent work with tools. Every call is stateless. It returns, and whatever it learned is gone unless it made it back into the context window, where it costs tokens on every subsequent turn until it gets compacted away. There is no directory. There is no tomorrow.
Glove's working environment exists to give the agent the first thing instead of the second.
What it is
A small, fast, in-memory, sandboxed, persistent virtual filesystem with a script runtime. The agent can create files, write and persist scripts, run them, capture outputs, generate intermediates, inspect them, and iterate, the way a developer works in a normal environment, without networking, host filesystem access, or process spawning.
Getting one is three lines:
const env = await createWorkingEnvironment({ stdlib: [documents(), spreadsheets()] });
await env.mount("./q3.xlsx", "/inbox/q3.xlsx");
mountWorkingEnvironment(agent, { env });
The tree the agent sees is opinionated. /inbox is where the host puts inputs. /scripts is the agent's own library, each script with an auto-generated type definition next to it. /skills holds worked recipes with exact import lines, read-only. /std is the materialized documentation for whatever adapters are mounted, also read-only. /tmp is for intermediates and run output. /out is where deliverables go so the host can export them. The agent cannot write where it should not, not because a prompt asked nicely, but because those paths are read-only by configuration.
Where it sits
We have three primitives in Glove that let a model execute code, and it is worth being precise about which one this is.
The scratchpad and the sandboxed REPLs solve one powerful executable over a resource catalog. They are stateless per call. You write a program against your tools, it runs, the result comes back. That is the right shape for a question.
The working environment solves a different problem: a place where state accumulates. Multi-file, multi-script, persistent, inspectable. That is the right shape for a task.
And when a task needs a real coding environment, a real shell, real packages, a real network, that is not this either. That is a full-fidelity sandbox, and it is a different tool with different costs. The working environment's non-goals are as load-bearing as its goals: no networking, not configurable; no shell emulation; no bare exec; no background execution.
Security by construction
The phrase we keep using is that scripts run in a scope containing only injected capabilities. There is no fetch to block. It simply does not exist. There is no process, no require, no filesystem module. Whatever the host mounted is there. Nothing else is.
Scripts run in isolated worker threads, and the timeout is enforced by terminating the worker, which is the only mechanism that stops a compute-bound script regardless of what it is doing. Every script must default-export a function, and that is validated at write time, not at first run, so a broken script fails when it is written rather than after the agent has built three more on top of it.
What the agent gets
The model-facing verbs are a closed set. Read, write, edit, move, copy, remove. ls, grep, describe. run_script, run_tests. checkpoint, undo, redo, diff, history. A handful are conditional: view_image appears only when a vision-capable model is wired, present only when the host wired a presenter. The rule is that an agent is never shown a capability that would fail on use.
Then the stdlib. Documents, spreadsheets, images, slides, archives, media, rendering, motion, OCR, email. Each is an adapter, paths in and paths out, and each mounts unchanged into the same tree. The render adapter exists so the agent can look at what it produced. The motion adapter replaces time rather than measuring it, so two renders of the same scene are byte-identical, which is what makes a test of an animation possible at all.
One thing surprised us. We expected simplified wrappers to help models. The scenario using the real pptxgenjs API, warts and all, scored highest of the set. Models have already read that library's docs a thousand times. A wrapper asks them to learn something new. The real API asks them to remember.
Context discipline
The other job the environment does is keep big data out of the window.
A tool that returns a 40-page document puts 40 pages into context. A script that reads the same document into /tmp, greps it, and prints the three lines that matter puts three lines into context. Outputs truncate with spillover to a file, so the agent can always go back and read more, but never pays for it by default. Extract to a file and grep it. Searching is not an optimization here. It is the only thing that works.
An agent producing a thirty-slide deck from a hundred commits writes one script that loops, groups, generates, and validates, entirely server-side, in one run, in one session's memory. The commits never enter the context. The slides never enter the context. Only the summary does.
Measured, not guessed
We do not want to sell this on architecture diagrams, so here is what ninety runs across three inexpensive models produced on an analyst-desk task with a real spreadsheet and a real deliverable.
Eighty-three of ninety runs produced the artifact. Forty-nine of ninety were fully correct.
The environment was not the bottleneck. What failed was content, and it was strongly model-dependent. One model delivered eighty percent of the time at ninety-three percent fact accuracy. Another produced a file eighty-three percent of the time and got it right twenty-three percent of the time. That last profile is the one to watch in production, because it hands you something that looks like finished work.
The single most frequent error was a guessed import. That is why /skills ships worked recipes with the exact line to type, and why every mounted adapter materializes its documentation into /std. The fix for hallucinated tool names is not a stricter prompt. It is a file the agent can read.
Idle cost is about sixteen megabytes and one OS thread per environment. Five of them is about eighty. That is not a leak. It is residency, and it is the price of a workspace that is still there when the agent comes back.
The compounding library
The part we care about most is the quiet one. Scripts persist. An agent that solved a problem yesterday has the script today, with its type definition, in a directory it can list. Over time an agent accumulates a discoverable, documented toolkit of its own.
That is what a working environment is for. Not to make one call cheaper. To make the thousandth call build on the first.

