The shape of a world
Five parts, each with one job:Data defines the world. State gives that world behaviour. Tools expose controlled access. Tasks define objectives. Verifiers decide whether the objective was achieved.That separation is the whole design. Data holds facts and nothing else. State turns those facts into a typed world with domain helpers. Tools are the only surface the agent can touch. Tasks state what to accomplish without saying how. Verifiers grade the world the rollout left behind.
Where it lives
The contract
Silo loads an environment through three exports and nothing else:index.ts
The
environment const is not required at runtime. It exists so TypeScript fails the build if the module drifts from the contract, rather than failing at run time.
Tasks are not exported. They are discovered from tasks/*.json, so adding a task is adding a file.
Magic for data, never for code
Tasks and datasets are discovered from disk. Tools and verifiers are explicitly registered in their barrel files. That asymmetry is deliberate: a JSON file appearing indata/ is inert until something reads it, but a TypeScript file appearing in tools/ would otherwise become a new capability the agent can invoke. A file landing on disk must never silently widen what an agent can do.
The manifest
silo.environment.json
Type checking
silo init writes .silo/tsconfig.json covering environments/**/*.ts, and never overwrites one you already have.
Next
Data
Facts only — never a value you can derive.
State
The typed world and its domain helpers.
Tools
The only surface the agent can touch.
Tasks
Objectives, without a solution path.
Verifiers
Deterministic grading of the final world.
Validation
Catching a broken environment before a run.
Silo