Cori
Concepts

Architecture

Locked architectural decisions in Cori — a summary for curious readers and contributors.

This is a summary. The authoritative source is AGENTS.md in the Cori repository, which contains the full rationale for each decision. When this page and AGENTS.md disagree, AGENTS.md wins.

Locked decisions

One workflow type. There is a single CoriWorkflow on Temporal. All step dispatching goes through it. No per-step workflow types, no custom workflow registration.

Closed set of activity kinds. There are exactly five activity kinds (cli, mcp_tool, code, llm, builtin). New kinds require a code change; there is no plugin API for custom kinds in v1.

Single execution path on Temporal. Cori does not support running workflows on anything other than Temporal. There is no "local runner," no "dry-run executor," no Wasm sandbox. --dry-run validates without executing activities.

Broker as the trust boundary. The broker is the only component that executes external side effects. Step files run inside the Temporal activity executor on the worker, with no direct access to the workflow orchestration layer.

Disk is truth, no database. Cori stores no state in SQLite or any other database. Run history is JSON files in ~/.cori/runs/. Configuration is ~/.cori/config.toml. There are no migrations, no database to set up, no schema to manage.

TypeScript-only step files. User-authored step files are TypeScript. No Python, no other languages in v1.

Zod for all schemas. Every step's input and output is typed with a Zod schema. This enables compile-time validation and typed parameter passing between steps.

The largest known gap

The builtin activity kind (map, for_each, branch, parallel, wait) is accepted by the compiler but not executed by the v1 runtime. This is the biggest missing piece for complex workflow patterns. See the Contributing section.

Further reading

  • AGENTS.md in the Cori repository — full decision log with rationale
  • Execution model — what cori run does
  • Determinism — why the workflow body must be a pure function

On this page