Skip to main content
Silo has two separate error vocabularies, and they are used in different places. SiloError — raised by the CLI and SDK when you are authoring an environment. These are your mistakes, not an agent’s. ToolError — returned to an agent when a tool call fails at runtime. These are values, not exceptions, and are written to be read by a model.

SiloError

The CLI prints the same codes alongside its messages and exits non-zero:

Environments

runtime_contract_invalid is often a module-system problem rather than a missing export. An environment in a project without "type": "module" loads as CommonJS, and its exports end up nested under .default.

Data

Tasks

Code resources

Names

Names are validated because they are interpolated into file paths and generated TypeScript.

ToolError

Returned to the agent as a value with isError: true — never thrown into it. A rejected call is an observation the agent can act on, not the end of the rollout.
Any string is accepted, so a domain can add its own vocabulary. Prefer these when they fit.
Inside a tool you throw; Silo catches it and returns it to the agent as a value.

Two are generated by Silo

invalid_input for a schema violation and tool_not_found for an unknown name are produced before your run executes. The schema message names the real parameters, which is what gives a model a chance to self-correct.

Writing messages an agent can act on

Tool error messages are read by a model mid-run, so they are part of your environment’s interface:
Name what was wrong and what is true instead. If an agent repeatedly makes the same mistake, the message is usually the thing to fix.