Extending the agent
The agent writes its own tools
When a capability is missing, the agent can author a tool at runtime — generate Rust, compile it to WASM, and register it without a restart.
If the agent needs something no tool provides, it can write the tool, register it, and use it in the same session. No restart, no redeployment.
> write a tool that converts our CSV exports into the summary format
The agent generates a Rust scaffold, compiles it to wasm32-wasip2, validates
the resulting component, and registers it into the running tool registry.
What it needs on your machine
A Rust toolchain and the wasm32-wasip2 target. If they are missing, the first
create_tool call installs them — roughly 200 MB for rustup and 50 MB for the
target, once.
That is a real cost on a machine you did not intend to put a compiler on, and a tool takes tens of seconds to build the first time. If that is the wrong trade for you, there is now a second path.
JavaScript — nothing needs to be installed
> write a tool that converts our CSV exports into the summary format
create_js_tool needs no toolchain at all. The interpreter is compiled to WASM
when Snaga itself is built and travels inside the binary, so creating a tool is
three file writes and a smoke run rather than a compile.
That cheapness buys back a check the compiled path never had: the tool is executed before it is registered, because doing so costs about a millisecond.
One interpreter is shared by every script tool — each differs only in the script it runs and the policy it runs under — so the runtime compiles the interpreter once for all of them, and an ahead-of-time cache keeps even that across restarts.
| JavaScript | Rust | |
|---|---|---|
| Toolchain needed | none | rustup + wasm32-wasip2 |
| First tool | about a second | tens of seconds |
| Run before registering | yes | no |
| Capabilities | declared | inferred from source at compile time |
Prefer JavaScript unless you need something Rust gives you. The one real difference in the security model is that last row: the Rust path can scan generated source to infer what a tool needs, and a substring scan cannot be sound over a dynamic language — so a script tool's capabilities are declared and enforced by the runtime gate. That gate is what the sandbox treats as authoritative in both cases anyway.
The sandbox is otherwise identical: a script tool is an ordinary WASM component under the same memory and CPU budgets, the same wall-clock timeout, and the same per-tool capability bits.
Building many tools
Dependencies are built once into a shared tree rather than per tool. Two tools created in a row, measured end to end through the agent:
before 35.41s 33.24s
after 30.33s 1.19s
The cost is a shared build tree of about 164 MB, and one consequence worth knowing: two tools building at the same time now serialise, because the build tool locks the directory.
What compiling does and does not verify
The build succeeding means the code type-checks. It does not mean the tool works — nothing runs it before it is registered. Ask the agent to exercise a new tool before you rely on it.
Where tools live
.snaga/tools/
├── my_tool.wasm # the compiled component
├── my_tool.rs # the Rust source, kept
└── my_tool.policy.toml # capabilities and limits
The policy file is readable and is the authority on what a tool may do. If you want to know what something the agent wrote is allowed to touch, that file answers it — see Capabilities and the sandbox.
Manage them with list_wasm_tools, find_tool, activate_tool,
deactivate_tool and remove_tool. Deactivating hides a tool from the agent
while leaving it on disk; removing deletes the files and unregisters it.
The sandbox applies to tools the agent wrote
A generated tool is an ordinary WASM component under the same runtime as anything you install: the same memory and CPU budgets, the same wall-clock timeout, the same per-tool capability bits. The agent writing the code does not grant the code any additional trust.
Capabilities for a generated tool are inferred at compile time by scanning the generated source, and enforced at runtime by the capability gate — the gate is what actually holds.
When not to write one
If somebody has already written it, install theirs — see Installing tools from the registry. Writing a tool is for the case where the capability does not exist yet, and publishing it afterwards is how it stops being that case for the next person.