Agents that survive
production.
A self-hosted TypeScript runtime for AI agents: tools that wait for a human, workflows that outlive the process, swarms, memory and RAG — on any model, in your own infrastructure.
Agent-friendly docs at /llms.txtconst refund = tool({
name: 'refund_order',
description: 'Refund part or all of an order.',
parameters: z.object({ order: z.string(), amount: z.number() }),
requiresApproval: ({ amount }) => amount > 100,
execute: ({ order, amount }) => payments.refund(order, amount),
});
const support = new Agent({
name: 'support',
model: 'anthropic/claude-sonnet-5-5',
instructions: 'Refund orders when the customer asks.',
tools: [refund],
});
const run = await cog.run(support, { input, threadId });
if (run.status === 'paused') {
await cog.resume(support, threadId, {
defaultDecision: { approved: true },
});
}A run pauses before a sensitive tool and resumes when a human approves — even after a restart, with a durable checkpoint store · examples/core/14-approvals.ts
+++ Any model · any runtime · your infrastructure +++
- Anthropic
- OpenAI
- Gemini
- Ollama
- Mistral
- DeepSeek
- vLLM
- Groq
- Together
- AWS Bedrock
- Azure OpenAI
- Anthropic
- OpenAI
- Gemini
- Ollama
- Mistral
- DeepSeek
- vLLM
- Groq
- Together
- AWS Bedrock
- Azure OpenAI
- TypeScript
- Node.js
- Bun
- Deno
- Cloudflare Workers
- Next.js
- Express
- Fastify
- Hono
- Koa
- Redis
- PostgreSQL
- SQLite
- MongoDB
- Qdrant
- Docker
- MCP
- OpenTelemetry
- Telegram
- Discord
- Fly.io
- TypeScript
- Node.js
- Bun
- Deno
- Cloudflare Workers
- Next.js
- Express
- Fastify
- Hono
- Koa
- Redis
- PostgreSQL
- SQLite
- MongoDB
- Qdrant
- Docker
- MCP
- OpenTelemetry
- Telegram
- Discord
- Fly.io
- LLM providers
- 11
- npm packages
- 33
- built-in tools
- 26
- runnable examples
- 74
+++ Durable workflows +++
Workflows that outlive the process.
Wire agents, tools and human sign-offs into a DAG. Each finished node is checkpointed to Postgres or Redis, so a crash, a deploy or an approval that takes all afternoon picks up where it stopped — not from the top.
const checkpoints = new PostgresCheckpointStore({ client: pool });
const executor = new WorkflowExecutor(cog, checkpoints);
const draft = agentNode<Post>(writer, {
stateMapper: (run) => ({ draft: run.output }),
});
const review = humanWorkflowNode<Post>(
approvalNode('review', { title: 'Publish this post?' }),
{ stateMapper: (answer) => ({ approved: answer.approved }) }
);
const publish = functionNode<Post>('publish', async (post) =>
post.approved ? cms.publish(post.draft) : null
);
const pipeline = new WorkflowBuilder<Post>('publish-post')
.addNode('research', agentNode(researcher))
.addNode('draft', draft, { after: ['research'] })
.addNode('fact-check', agentNode(checker), { after: ['research'] })
.addNode('review', review, { after: ['draft', 'fact-check'] })
.addNode('publish', publish, { after: ['review'] })
.build();
const durable = {
checkpoint: true,
checkpointStrategy: 'per-node',
approvalStore: new PostgresApprovalStore({ client: pool }),
} as const;
await executor.execute(pipeline, { topic }, durable);
const [last] = await checkpoints.list('publish-post');
await executor.resume(pipeline, last.id, durable);- 14:02:07execute · publish-post
checkpointStrategy: 'per-node' — on resume, finished nodes are skipped and only the nodes that were in flight run again · @cogitator-ai/workflows
- config.compensationA failed step undoes the finished ones in reverse order — with retries, circuit breakers and a dead-letter queue.Sagas
- cronTrigger · webhookTriggerStart runs on a cron schedule in any time zone, from a rate-limited webhook, or on an internal event.Scheduling
- mapReduceWorkflowNodeFan a list out across agents, reduce the results, and nest whole workflows as subworkflow steps.Patterns
+++ Swarms +++
Seven ways to make agents work together. One config key.
A supervisor over workers, a jury that votes, an auction for the task, stages behind a quality gate, two agents arguing it out — and every agent on the model that suits its role.
A supervisor splits the task and hands pieces to workers with the delegate_task tool. Results flow back up to it.
const team = new Swarm(cog, {
name: 'feature-team',
strategy: 'hierarchical',
supervisor: lead,
workers: [frontend, backend, devops],
hierarchical: {
maxDelegationDepth: 2,
visibility: 'summary',
},
});
const { output, agentResults } = await team.run({
input: 'Add SSO to the admin panel',
});Replays of what each strategy runs · the event names are the ones swarm.on() receives · examples/swarms
+++ Everything in the box +++
Every package, ready when you need it.
Memory, RAG, protocols, channels, voice, browsers, evals and more ship as focused packages on the same runtime. Add the ones you need; each comes with docs and runnable examples.
@cogitator-ai/memory
Memory & context
Every run gets a context built to a token budget: recent history, long-term facts and semantic hits, on Postgres, Redis, SQLite, MongoDB or Qdrant.
- System promptYou are Alice's travel concierge…210
const cog = new Cogitator({
memory: {
adapter: 'postgres',
postgres: { connectionString: process.env.DATABASE_URL! },
embedding: { provider: 'openai', apiKey: process.env.OPENAI_API_KEY! },
contextBuilder: {
maxTokens: 8000,
strategy: 'hybrid',
includeFacts: true,
includeSemanticContext: true,
},
},
});
await cog.run(concierge, { input: 'Book my usual hotel', threadId: 'trip-42', userId: 'alice' });+++ Runs anywhere +++
Drop it into the stack you already run.
One adapter call turns your agents into an HTTP API with SSE streaming, memory threads, approvals and a WebSocket — on Express, Fastify, Hono, Koa, Next.js, Tetsu on Bun, Deno or Cloudflare Workers. Or keep your client: speak OpenAI's Assistants API, or hand an agent to the Vercel AI SDK as a model.
import express from 'express';
import { createServer } from 'node:http';
import { CogitatorServer } from '@cogitator-ai/express';
import { assistant, cogitator } from './agent';
const app = express();
const server = new CogitatorServer({
app,
cogitator,
agents: { assistant },
config: { basePath: '/cogitator', enableWebSocket: true },
});
await server.init();
const http = createServer(app);
await server.attachWebSocket(http);
http.listen(3000);assistant ›
- POST/cogitator/agents/:name/runRun an agent, JSON reply
- POST/cogitator/agents/:name/streamSame run as an SSE stream
- POST/cogitator/agents/:name/resumeResume a run paused for approval
- GET/cogitator/threads/:idMemory threads · POST messages, DELETE
- POST/cogitator/workflows/:name/streamWorkflows and swarms, run or streamed
- WS/cogitator/wsAgent runs over a socket, via attachWebSocket
- GET/cogitator/docsSwagger UI and /openapi.json, on by default
Starting from scratch? The scaffolder writes a ready-to-run project, installs it and sets up Docker Compose if you want it.
+++ Agent friendly +++
Docs your coding agent can read.
Point Claude Code, Cursor or any agent with a shell at cogitator.app and it gets Markdown, not a rendered page: a llms.txt index, the whole docs in one file, and every page at its own URL.
- /llms.txt
The index: all 114 docs pages, grouped like the sidebar, each linked to its Markdown with a one-line summary.
- /llms-full.txt
Every page in one Markdown file, in sidebar order — for long-context models and offline reading.
- /docs/<page>.mdx
Any page as Markdown: append .mdx to its URL, or request it with Accept: text/markdown.
+++ Hand the docs to your agent +++
Every docs page has the same actions for that page: Copy Markdown, and Open in ChatGPT, Claude or Cursor.
Ship the agent.
Keep the control.
Scaffold a project with your provider, memory and Docker set up, then grow it into workflows, swarms and channels package by package.