The keyring
Hand the agent raw tools and hope for the best.
One bad prompt away from a production incident.
AI Automation as Code · v0.6.0
Type-safe framework for AI automation. Build the tools an agent uses, or the harness itself, with the same fluent DSL.
craft().id('morning-brief').from(cron('0 9 * * 1-5')).transform(summarise).to(mail())
Agents have deleted production databases trying to do their job. Routecraft capabilities are bounded by design: typed inputs, authorize(), per-tool guards, the same code in test and prod. The agent gets the hands you choose, not the keyring.
The keyring
One bad prompt away from a production incident.
The hands you authored
The capability is the boundary. The agent has no other surface.
The DSL is simple enough that an LLM can write the capability for you. You review the capability, not the prompt.
The same fluent DSL builds the tools an agent calls, and the harness that runs an agent. You pick which side you are on. Sometimes both, in the same project.
Tools for an agent
Set the source to mcp() and your capability becomes an MCP tool. Claude Desktop, Cursor, ChatGPT, OpenClaw, Hermes, or any MCP-speaking client can pick it up. Auth, validation, and structured output are part of the primitive.
The whole agent
Set the destination to agent() and the capability becomes the brain. You choose the model, the system prompt, the tools the agent can reach for, and what happens to the result. The DSL is the harness.
Every adapter in Routecraft, grouped by what they do. Click any name for the full signature, options, and examples. New adapters are built the same way as built-ins.
Need something that isn't here? Adapters are a documented, stable contract, write your own.
Thesis
Type-safety, validation, auth, MCP, composability, structured logging. Production-grade plumbing so you spend your time on the agent, not the boilerplate around it.
Types flow through every operation. The body shape at .to() is inferred from .from() and every transform in between.
Cron, webhook, MCP, IMAP, channel, file. Swap one line to change how a capability is invoked. The business logic is unchanged.
Set the source to mcp() and the capability becomes an MCP tool that Claude Desktop, Cursor, and any MCP client can call.
Bring Zod, Valibot, ArkType, or anything that speaks Standard Schema. Inputs validate before your code runs.
jwks() verifies bearer tokens. .authorize({ roles }) gates capabilities. userinfo hydrates the principal from your IdP.
direct() lets one capability call another with full type safety. Build a graph, test each node in isolation.
Every step emits structured events. Pipe them to your log aggregator, or watch them live in the built-in TUI.
Telemetry, AI, mail, custom adapters. Plugins extend the runtime without forking it.
The CLI runs TypeScript directly on Bun. Embed in any Node 22+ app via ContextBuilder.
Tutorials, postmortems, and small notes from building Routecraft in production.
The full archiveThe personal-assistant wave gave every employee an agent with their own access, their own memory, and their own chat window. That model cannot serve a team. The unit of organisational AI leverage is the governed capability, not the personal agent.
Run it in GitHub Codespaces without leaving your browser. Or scaffold locally and have it humming on your laptop in the same minute.
AI automation built and operated for SMBs and consultancies, by the people who wrote the framework.