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.

  1. 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.

  2. 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.

  3. 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.

Example workflow. The agent chooses this decomposition; spore does not impose it on every task.
  1. Contracts and rules the batch and the customer's rules
  2. Reusable checks a program: dates, amounts, required sections
  3. Sections needing judgment what the checks cannot settle
  4. Focused cells one section and the rules each
  5. 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.

  1. npm install -g @rhizogrip/spore-cli
  2. spore setup
  3. spore here

Then carry one task from your application to a finished, paid-for result.