Concepts¶
The tutorial shows you how. This page explains the why behind the handful of design choices that shape everything else. Each links to the architecture decision record (ADR) with the full reasoning.
Canvas and YAML are one thing¶
The central idea. The visual canvas and the AgentSpec YAML are not two representations kept in
sync. They are the same artifact seen two ways. Every canvas edit rewrites the YAML through the
validator, and every YAML edit re-renders the canvas.
flowchart LR
canvas["Canvas"] <-->|"parse ⇄ serialize"| spec["agent.yaml"]
editor["Your editor"] <-->|"read ⇄ write"| spec
This is why there's no import step and no "export to YAML". The YAML is the project. It's plain
text you commit, diff, and review like code. The round trip is built to be lossless: parse,
render, serialize, and you get the same file back, comments and formatting included: long
quoted expressions are not refolded, and flow maps and lists keep their spacing. One exception: a hand-wrapped
>- block is saved with each paragraph on one line (the value is the same); use | to keep line breaks
(ADR-0052).
ADR-0002
Layout lives in a sidecar, not the spec¶
Node positions on the canvas would clutter the spec and create noisy diffs if they lived in the
YAML, so they don't. Canvas coordinates go in a separate .kampong/layout.json sidecar, keyed by
step and tool ID. A spec with no sidecar still renders, because the canvas auto-lays-out anything
it hasn't seen before. A card you drag onto empty canvas stays where you put it (the sidecar marks it
pinned); cards you have not dragged keep their automatic place. Dropping a step on another step of
its list reorders it instead. The spec stays clean and hand-authorable.
ADR-0006,
ADR-0061
Export is one-way¶
You can eject a spec to a standalone TypeScript project, but the door only opens outward. The canvas and CLI never read generated code, only the spec round-trips. Hand-edits to an exported project stay in that project. This keeps the model simple: there is exactly one definition of a workflow, and it's the spec. YAML is its text form: the file you edit in local mode, and the format you import and export in the hosted product, where the spec is stored for you. ADR-0054 ADR-0002, ADR-0010
Local-first, and it fails loudly¶
Everything runs on your machine. The canvas is a local web app the CLI serves, not a desktop app and not a hosted service, which is what lets the same UI power a hosted mode later. ADR-0005
Two rules follow from taking "local-first" seriously:
- No silent fallbacks. A missing API key, an unreachable Ollama server, a missing replay fixture: each fails with a specific, visible error. The tool never quietly substitutes a paid cloud call or a stale value to keep a run alive.
- No telemetry by default, and no secrets in specs. Nothing phones home unless you opt in.
Specs reference
${ENV_VAR}placeholders only, and real keys live in your environment.
How many agents¶
A spec holds one agent today. That is a scope limit for this stage, not a design position, and
there is no multi-agent orchestration yet. The schema leaves room for a sub_agents field, and
multi-agent is open for later.
ADR-0001,
ADR-0053
The stack, briefly¶
TypeScript end to end, on Mastra. The canvas is React + Vite + @xyflow/react, the local server
is Fastify with server-sent events for live run and file-change updates, and YAML is parsed with
the comment-preserving yaml package, which is what makes the lossless round trip possible. The
local tool needs no database for specs; the one exception is a small SQLite file
(.kampong/state.db) that holds dedupe keys, run state and pending approvals for workflows that
run unattended. The hosted server uses Postgres.
ADR-0003,
ADR-0007,
ADR-0028
For the whole set of decisions, see Design decisions.