Introduction
ayjnt is a thin, Bun-first framework for building Cloudflare Durable Object agents. It eliminates the config work around Agents so you can spend your time on the agent itself.
The problem
Cloudflare Agents are great. Setting them up is not. Every new agent
means another entry in wrangler.jsonc, another Durable
Object binding, another migration tag, another line in your worker's
fetch handler to route requests to the right class. For a
single agent this is fine. For a dozen agents with middleware, UI, and
cross-calls, it becomes the majority of your work.
ayjnt collapses that glue into a file-tree convention. Folders under
agents/ become agents, nested folders become nested URLs,
and the framework writes the worker entrypoint, the wrangler config,
and the DO migrations for you on every build.
What you get
Six capabilities that usually each take their own setup, built in:
- File-based routing. The folder tree is the API.
One
agent.tsper folder becomes one DO binding and one URL prefix. Route groups (parens) share middleware without leaking into the URL. - Git-safe migrations.
.ayjnt/migrations.jsonis committed to your repo andayjnt deployrefuses to run from an out-of-sync tree. Two developers can't race a deploy and produce divergent DO schemas in production. - Typed inter-agent RPC.
getAgent<T>(env.BINDING, id)returns a typed Durable Object stub with method autocomplete from the target class. Errors propagate as exceptions. - Co-located React UIs. Drop an
app.tsxnext toagent.ts. A generated typeduseAgent()hook is available at@ayjnt/<route>. State syncs across every connected tab automatically. - MCP agents. Classes extending
McpAgentroute through the SDK'sMcpAgent.serve()handler automatically — streamable HTTP + SSE transports are handled for you. - HMR-backed dev loop.
ayjnt devwatchesagents/, re-runs codegen when the file tree changes, and letswrangler devreload. Full rebuilds take single-digit milliseconds via bunup.
Who it's for
TypeScript engineers shipping one or more agents on Cloudflare Workers — from a single chat agent to a fleet of coordinating services. ayjnt is intentionally Bun-first: the CLI is a Bun script, the framework is written in TypeScript we ship as source, and the bundler is Bun. If your team is on Node without Bun, ayjnt still works (the compiled JS is shipped to npm), but the dev experience is smoother on Bun.
Relationship to the Cloudflare Agents SDK
ayjnt is a layer on top of
Cloudflare's Agents SDK
.
You still extend Agent from the agents package,
and every runtime feature — state, this.setState, scheduling,
WebSockets, identity messages — comes from the SDK, not from ayjnt. What
ayjnt adds is build-time:
- Scanning the
agents/folder for DO classes - Emitting the worker entrypoint + dispatch logic
- Emitting the
wrangler.jsoncincluding DO bindings and migrations - Generating per-agent typed React hooks
- Enforcing the git-safe migration contract at deploy time
When something goes wrong at runtime — a request handler throws, a WebSocket disconnects, the Agent SDK misbehaves — the Cloudflare docs are the authoritative reference. When something goes wrong at build time — the wrong migration was staged, the URL shape is unexpected, the generated entry.ts does something odd — that's on ayjnt.
Where to go next
If you're ready to install:
bunx ayjnt new my-app
cd my-app && bun install
bun run devThen read Installation for the full setup and Your first agent for a walkthrough with code. If you want the feature tour first, the home page has click-to-expand cards for each of the six pillars.