AI Automation as Code  ·  v0.6.0

Tools for agents.
Or the agent harness itself.

Type-safe framework for AI automation. Build the tools an agent uses, or the harness itself, with the same fluent DSL.

morning-brief.tscron trigger
craft()
  .id('morning-brief')
  .from(cron('0 9 * * 1-5'))
  .transform(summarise)
  .to(agent('eywa'))
Same body. Different trigger. Change one line.
IBounded by design

Hands, not keys.

Agents have deleted production databases trying to do their job. Routecraft capabilities are bounded by design: typed inputs, authorize(), guard(), the same code in test and prod. The agent gets the hands you choose, not the keyring.

The keyring

Hand the agent raw tools and hope for the best.

// Typical agent SDK setup
const agent = new Agent({
  tools: [
    bashTool(),
    browserUse({ allowAll: true }),
    computerUse({ allowAll: true })
  ],
})

// The agent decides what to run.
// Including DROP TABLE, rm -rf,
// or leaking the connection string.

One bad prompt away from a production incident.

The hands you authored

Give the agent named capabilities and nothing else.

// A capability that drives the agent.
craft()
  .id('triage-inbox')
  .from(mail('INBOX'))
  .to(agent({
    model: 'anthropic:claude-sonnet-4-6',
    system: 'Triage and route inbound support mail.',
    tools: tools(['publishBrief', 'sendDigest']),
  }))

// One of the bounded hands the agent can reach for.
craft()
  .id('publishBrief')
  .input(BriefInput)
  .authorize({ roles: ['editor'] })
  .transform(redactPII)
  .to(http({ url: '/feed' }))

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.

IITwo ways to ship agents

Use Routecraft on either side of the agent.

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.

01

Tools for an agent

Expose capabilities, let agents call them.

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.

  • .from(mcp()) exposes a typed tool
  • .input(schema) validates before your code runs
  • .authorize({ roles }) gates per-agent
Expose a capability over MCP
02

The whole agent

Build the harness. Own the loop.

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.

  • .to(agent({ model, system })) picks the model
  • tools([...]) scopes what the agent can do
  • .to(direct('next')) composes into longer flows
Build an agent capability
IIIWhat you can wire up

The surface area.

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.

IVWhy Routecraft

Thesis

Every primitive an agent app needs.

Type-safety, validation, auth, MCP, composability, structured logging. Production-grade plumbing so you spend your time on the agent, not the boilerplate around it.

01

Type-safe end to end

Types flow through every operation. The body shape at .to() is inferred from .from() and every transform in between.

02

One DSL, every trigger

Cron, webhook, MCP, IMAP, channel, file. Swap one line to change how a capability is invoked. The business logic is unchanged.

03

Native MCP integration

Set the source to mcp() and the capability becomes an MCP tool that Claude Desktop, Cursor, and any MCP client can call.

04

Standard Schema validation

Bring Zod, Valibot, ArkType, or anything that speaks Standard Schema. Inputs validate before your code runs.

05

Auth as a primitive

jwks() verifies bearer tokens. .authorize({ roles }) gates capabilities. userinfo hydrates the principal from your IdP.

06

Compose capabilities

direct() lets one capability call another with full type safety. Build a graph, test each node in isolation.

07

Structured logging

Every step emits structured events. Pipe them to your log aggregator, or watch them live in the built-in TUI.

08

Plugin system

Telemetry, AI, mail, custom adapters. Plugins extend the runtime without forking it.

09

Runs on Bun or Node

The CLI runs TypeScript directly on Bun. Embed in any Node 22+ app via ContextBuilder.

VFrom the blog
VITry it

Open the playground. Have an MCP server in thirty seconds.

Run it in GitHub Codespaces without leaving your browser. Or scaffold locally and have it humming on your laptop in the same minute.

Routecraft is the framework. DevOptix is the team that ships with it.

AI automation built and operated for SMBs and consultancies, by the people who wrote the framework.

Talk to us