Skip to content

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.