Self-hosted agents
You write the agent with the AI SDK. chamberu queues its runs, checkpoints every step, pauses for approvals and resumes interrupted runs, in your own Node process and database.
export const triage = defineAgent({
name: 'triage',
model,
instructions: 'Label new issues and close duplicates.',
triggers: [
http({ path: '/issues' }),
cron('0 * * * *'),
],
tools: () => ({
// recorded per effect key: retries never relabel
label: defineEffectTool({
description: 'Adds a label to an issue.',
inputSchema: z.object({
issue: z.number(),
label: z.string(),
}),
execute: async (i) => addLabel(i.issue, i.label),
}),
close: tool({
description: 'Closes an issue as a duplicate.',
inputSchema: z.object({ issue: z.number() }),
execute: async ({ issue }) => closeIssue(issue),
}),
}),
// waits in `waiting` until the owner signs off
approvals: { close: 'user' },
notify: 'owner',
});What the AI SDK leaves out
A webhook, a cron tick or a manual call becomes the same envelope and the same queued run. Idempotency keys turn redeliveries into the existing run; concurrency keys keep two runs for one issue apart.
dispatch({ idempotencyKey })
A checkpoint after every step. drain() hands unfinished runs back, and recover() continues them from the latest checkpoint on any replica, without applying a recorded effect twice.
drain() → recover()
A tool call that needs a human pauses the run in waiting, with a signed resume token. Approve or deny it an hour or a day later, from any replica.
resume(token, { approved })
How a run flows
Every run lives in your store, from dispatch to its final status. Whatever stops it halfway, the next execution starts from the latest checkpoint.
Packages
The engine and its test helpers ship now. The scheduler, the HTTP API, the Postgres store and the rest are designed milestone by milestone.
@chamberu/coreshippedAgents, triggers, the run engine, checkpoints, budgets, effect tools, approvals, agent state and the in-memory store. Reference@chamberu/test-kitshippedControllableClock and the store contract suite every IStore implementation must pass. Reference@chamberu/store-typeormplanned M1Postgres store through TypeORM, passing the store contract suite.@chamberu/schedulerplanned M1Fires cron() triggers once per tick across replicas.@chamberu/httpplanned M1REST control API, server-sent events, webhook intake and an MCP endpoint.@chamberu/githubplanned M1GitHub App auth, webhook triggers and issue tools with reconciliation.@chamberu/sandbox-*planned M1Disposable workspaces, local for development and a pod per workspace in production.@chamberu/uiplanned M1A dashboard with live steps, an approvals inbox, agent state and schedules.Define an agent, dispatch a run and watch it settle. MemoryStore needs no database, so the quick start runs in a single file.
npm install @chamberu/core ai zod