spore
Build agents into your product.
Persistent AI agents on your own machines, built into your application. Agents can reuse programs, work with files and delegate focused tasks; you set their access and budgets.
how agents do the work
The design aims at two things: not paying a model to redo work already done, and controlling what each model call has to read.
Reuse useful work.
An agent can write and test a program, then run it on later tasks without asking the model to reconstruct the procedure.
Choose what enters context.
Large outputs stay in files. The agent can search, filter and read relevant material instead of carrying the full output into every model call.
Give specialists focused jobs.
The main agent can delegate narrow questions to cells, each with selected inputs, capabilities and limits, then collect their results. A cell is a specialist made on the spot: it runs once and reports back.
These are what the design makes possible, not steps it forces: the agent chooses its approach and still has to check its own work. The reasoning is set out in principles.
an example: contract review
A document-review application sends each customer's contracts, with that customer's rules, to the customer's agent. This is one way the agent can split the work.
- Contracts and rules the batch and the customer's rules
- Reusable checks a program: dates, amounts, required sections
- Sections needing judgment what the checks cannot settle
- Focused cells one section and the rules each
- Report the check results, straight from the program, and the cells' readings
Example report excerpt
batch-2207 · 3 contracts
Checks (data/checks.mjs)
msa-0412 payment: 60 days, limit 45
msa-0419 no findings
sow-0415 missing section: Liability
Judgment (one cell per section)
msa-0412 §9 Indemnity
Uncapped; rule 4 requires a cap
at 12 months' fees.
sow-0415 §5 Acceptance
Deemed accepted after 10 business
days; within rule 6. Example helper for the mechanical checks, data/checks.mjs
import { readFileSync } from 'node:fs'
import { basename } from 'node:path'
const SECTIONS = ['Term', 'Payment', 'Liability', 'Governing law']
const MAX_DAYS = 45
for (const file of process.argv.slice(2)) {
const text = readFileSync(file, 'utf8')
const lines = text.split('\n')
const findings = SECTIONS
.filter((name) => !lines.some((l) => l.endsWith('. ' + name)))
.map((name) => 'missing section: ' + name)
const term = text.match(/payable within ([0-9]+) days/i)
if (!term) findings.push('payment: not stated')
else if (Number(term[1]) > MAX_DAYS)
findings.push('payment: ' + term[1] + ' days, limit ' + MAX_DAYS)
const contract = basename(file, '.txt')
console.log(JSON.stringify({ contract, findings }))
} Synthetic contracts and rules: an illustration, not a recorded run.
The next batch reaches the same workspace, where the helper is still there to run. The same example, end to end, on the build page.
how it fits your application
Each agent has a workspace that keeps its conversation, programs and files between turns. Your product decides which agent serves each customer, ticket or conversation. Idle agents need no process of their own; enabled services still run.
your product
- its interface
- its users' identities and how they sign in
- its business rules: what gets reviewed, who may see a report
- when work is sent, and which agent serves whom
spore
- running the agent, its cells and its model calls
- the workspace: messages, events and files
- confinement, credentials and budgets
- the record of what the agent did and spent
Your application sends work with a request ID of its own. After a timeout, a crash or a deploy, it can retry the submission safely under the same ID. It follows progress from the last event it handled, shows the answer as soon as the agent gives it, and records the cost once spore has settled it. A product with its own scheduler can decide when work starts.
Your code reaches all of this through the Node library, @rhizogrip/spore; an HTTP
API on a unix socket or a loopback address; or the spore command. All three call
the same functions. How each step works, on the build page.
what bounds execution
The agent is untrusted. By design. Anything it reads — a web page, a document, a tool's output — can steer it. The operator is trusted: that is you, the Unix user who runs spore and writes the definitions. spore confines the first and follows what the second wrote.
- access
- An agent writes only in its own workspace and the folders its definition grants, and cannot read spore's configuration and keys or another agent's folder. The Linux kernel enforces this with Landlock, namespaces and a syscall filter.
- credentials
- Provider and configured source credentials stay outside the agent: no provider key, bot token or source secret reaches its environment. Its model calls go through a broker, a go-between that holds them.
- budgets
- Time, money and model calls each have a soft and a hard limit; past the soft one, the agent is asked to answer with what it has. Once settled spend reaches the hard cost, no new model call starts; a call already running finishes and is paid, so a turn's spend can pass its limit by what that call adds.
- records
- An agent cannot rewrite what it spent or what it did: spend is settled and events are appended out of its reach.
The network is open by design: fetching a page or installing a package is ordinary work for an agent's programs. It can send anything it may read, confidential documents included, but not the credentials its brokers hold. Additional egress policy belongs to the host.
where the boundary stops, in full · source: SECURITY.md
try it
spore runs on Linux x64 or arm64, kernel 5.13+, with Node 24+ and unprivileged user namespaces;
on macOS in a Linux VM that spore setup makes, on Windows in WSL. Every prerequisite, and how to check it. Models are
reached through mohdel, which calls fifteen providers, from
Anthropic to OpenRouter, directly with your own keys.
npm install -g @rhizogrip/spore-clispore setupspore here
Then carry one task from your application to a finished, paid-for result.