Agent SDK
The alineo package runs Pi coding agents inside sandbox containers — start an agent from a spec, prompt it, steer it mid-turn, spawn children from it, and pick it back up after your process dies or its container is gone.
alineo runs an AI coding agent inside a sandbox container. An agent is a spec and a prompt:
import { Alineo, textOnly } from "alineo";
import { SQLiteAdapter } from "@alineo-labs/sqlite";
const agent = await Alineo.start(
{
name: "hello",
harness: "pi",
provider: "nvidia",
model: "nvidia/nemotron-3-super-120b-a12b",
env: { NVIDIA_API_KEY: "${NVIDIA_API_KEY}" },
},
{ adapter: new SQLiteAdapter("./.alineo/ledger.db") },
);
for await (const chunk of textOnly(agent.prompt("Write and run a Python hello world."))) {
process.stdout.write(chunk);
}The agent installs packages, clones repositories and runs what it writes — inside the container, never on your machine. Quickstart →
It starts in seconds
The first start() installs the Pi CLI into a node:22 sandbox and snapshots it. Every start
after that restores the snapshot instead: ~3 seconds rather than ~90. The cache key is the spec's harness
version, packages and setup steps, so it invalidates itself when it should —
setup snapshots.
Your process is not the agent
The agent lives in the container, not in your Node process. Kill the process, come back tomorrow, pick the same agent back up:
const agent = await Alineo.reattach(sandboxId, { adapter });The bridge inside the container is never restarted, so a turn that was running when your process died is still
running. If the container itself is gone — deleted, or left Exited by a reboot — reattach() restores the agent
onto a fresh one from its last turn checkpoint instead of
failing — reconnecting and restoring.
Steer it mid-turn
await agent.steer("Focus only on the auth path — drop the unrelated findings.");The message lands after the current tool call finishes and before the next model call. The agent does not restart
and does not lose its context. followUp() queues the next turn instead, and abort() stops this one now —
steering.
Gate what it can do
Every tool call the agent wants to make can be held for a decision — yours, or a policy's:
agent.prompt(task, {
onPermission: (req) =>
req.tool === "bash" && req.target.startsWith("rm ")
? { kind: "reject", feedback: "Deleting files is out of scope." }
: { kind: "once" },
});reject hands the feedback back to the model as the reason. Leave onPermission off and the requests surface on
the stream instead, for a human to resolve with agent.resolvePermission() —
the permission gate.
Spawn a child from a live agent
const reviewer = await agent.spawn("./agents/reviewer.json");spawn() forks the parent's live sandbox, so the checkout, the installed packages and the files the parent
wrote are already on the child's disk. Clone a repository once and review it three ways at the same time.
For more than a couple of children — budgets, waitFor gathering, one event stream for the whole tree, recovery
when the host dies — that's alineod, which drives this SDK in-process and exposes it over HTTP.
Everything is on the record
The adapter on start() isn't bookkeeping you can skip. Every exec, tool call and state transition is appended
to a SQLite or Postgres ledger before anything derived from it is updated, and that is what makes the rest work:
reattach() finds the agent again, a restore finds its latest checkpoint, and an auditor gets the whole session
rather than a summary of it.
Where this sits
The Agent SDK runs one agent on top of the Core SDK's sandboxes — agent.sandbox is a live
SandboxHandle for anything Pi doesn't cover. alineod runs trees of these agents, and the
alineo CLI drives them from a shell.