Multi-agent pipelines for Claude Code. Define agents, wire them into workflows, run them. No API key needed.
For a "one-agent, one-workflow starter", run:
pnpm dlx @generata/core init @generata/starter ~/Projects/hello-generata
# or: npx @generata/core init @generata/starter ~/Projects/hello-generata
cd ~/Projects/hello-generata
pnpm generata hello --message "world"The init command above scaffolds the project, asks for any env values, and writes Claude Code slash commands for every workflow it finds.
If you want the full plan-driven coding pipeline, initialize @generata/coding (or add it to an existing project with pnpm generata add @generata/coding).
defineAgent takes a factory function: declare the agent's typed inputs, get them back inside the closure, interpolate them into the prompt.
// agents/greeter.ts
import { defineAgent } from "@generata/core";
export default defineAgent<{ message: string }>(({ message }) => ({
type: "worker",
description: "Greets a message in one creative line.",
modelTier: "light",
prompt: `Greet "${message}" in one creative line.`,
}));And a workflow that uses it. Workflows live under agents/ (flat) or agents/workflows/ (nested) - the filename is the workflow name. The starter uses flat; most templates use the nested convention.
// agents/hello.ts (or agents/workflows/hello.ts)
import { defineWorkflow } from "@generata/core";
import greeter from "./greeter.js";
export default defineWorkflow({
description: "Greets the supplied message.",
required: ["message"],
})
.step("greet", ({ message }) => greeter({ message }))
.build();And the project config - init writes one for you, but here's what it looks like:
// generata.config.ts
import { defineConfig } from "@generata/core";
export default defineConfig({
modelTiers: {
heavy: "claude-opus-4-7",
standard: "claude-sonnet-4-6",
light: "claude-haiku-4-5",
},
});That's the whole API surface for most use cases - defineAgent, defineWorkflow, defineConfig. No decorators, no plugin system, no DI container.
Agents declare typed outputs. Downstream steps destructure them by name in their stepFn - the chain builder threads each agent's output keys into the next step's params with full type-safety. No parsing, no sentinels.
// agents/coiner.ts - mints a slug from a topic
import { defineAgent } from "@generata/core";
export default defineAgent<{ topic: string }>(({ topic }) => ({
type: "worker",
description: "Turns a topic into a kebab-case slug.",
modelTier: "light",
outputs: { slug: "Kebab-case slug, lowercase, dash-separated" },
prompt: `Turn "${topic}" into a slug.`,
}));// agents/expander.ts - takes a slug, writes a one-liner
import { defineAgent } from "@generata/core";
export default defineAgent<{ slug: string }>(({ slug }) => ({
type: "worker",
description: "Expands a slug into a one-line description.",
modelTier: "light",
prompt: `Write one sentence describing "${slug}".`,
}));// agents/workflows/blurb.ts
import { defineWorkflow } from "@generata/core";
import coiner from "../coiner.js";
import expander from "../expander.js";
export default defineWorkflow({
description: "Coin a slug, then expand it.",
required: ["topic"],
})
.step("coin", ({ topic }) => coiner({ topic }))
.step("expand", ({ slug }) => expander({ slug }))
// ^ `slug` arrived from coiner's `outputs`, typed via the chain.
.build();Typo slug, reference it before coin runs, or pass the wrong shape to expander - all type errors at the call site. Halt at any agent with halt with reason "X" and the engine stops the workflow cleanly; downstream steps don't run.
For workflows that mutate the repo and ship a PR, opt in to git-worktree isolation via worktree. The workflow runs in a fresh worktree branched from origin/main (override with baseRef - any <remote>/<branch> triggers a fetch first, a bare branch like "main" is used as-is), while logs, metrics, and any declared sharedPaths symlink back to the main checkout. Pruned at run end.
import { defineWorkflow, worktree } from "@generata/core";
export default defineWorkflow({
description: "Self-improve loop",
isolation: worktree({
sharedPaths: ["IMPROVEMENTS.md", "last-run.md"],
}),
})
.step(/* ... */)
.build();Run-time overrides: generata workflow <name> --worktree forces isolation on, --local forces it off. generata worktree prune recovers orphan worktrees from crashed runs.
- Composable agents - planners, workers, critics. Mix and match.
- Heavy/standard/light tiers - each agent declares the tier it needs; you map tiers to actual models once in
generata.config.ts. Swap a whole pipeline from Opus to Haiku by editing three lines. - Typed workflow chains - each agent's
outputsflow into the next step's params with full type-safety. Steps run in parallel where deps allow; critics retry an upstream step on rejection; agents halt the workflow cleanly with a structured reason. - Runs on the Claude Code CLI you already have - no separate API key, no provider config.
- Zod-validated end to end. Bad configs and bad step args fail loud at the edges.
- Metrics included - cost, tokens, and duration captured per agent and per workflow, written as JSONL. Run
generata metrics today,metrics week,metrics expensive(top 10 calls today), ormetrics <agent>(7-day rollup for one agent) for summaries. The 7-day total auto-prints at the start of each run. - Prompt logs on demand - flip
logPrompts: true(or pass--log-prompts) and every prompt sent to Claude Code lands inlogs/so you can replay, diff, or debug what an agent actually saw. - Work/personal env profiles - pass
--profile workand required env keys are pulled fromWORK_-prefixed vars, so the same pipeline can run against a work GitHub token one minute and your personal one the next without.envshuffling.
Most agent frameworks expect you to manage Anthropic/OpenAI API keys, juggle Python environments, or wire up a runtime that knows how to spawn subagents. generata shells every step out to the Claude Code CLI you already have signed in - so the only runtime is the one you've been using all along. The engine is small, TypeScript-first, and treats critic-retry loops and parallel DAG execution as first-class.
| Package | What it is |
|---|---|
packages/core |
@generata/core - the engine and CLI, published to npm |
packages/templates/coding |
The default coding pipeline template, cloned by init |
packages/templates/starter |
Minimal starter for building your own pipeline |
packages/templates/standup |
Daily standup summariser template |
Built by Ben Rogerson.