kortecxdocs

Chain steps into a workflow

Turn work that takes more than one step into a workflow: steps that run one after another or side by side, and several agents working on one task.

Most useful work is more than one step. You research, then you draft. You ask three agents the same question, then you pick the best answer. A chain is how you say that out loud: a short expression that names the steps and how they connect.

A chain is written with task handles — short names like plan or review — joined by four operators. Each handle points at one step: a model step (an agent that reasons), a pure step (a deterministic transform, no model call), or a tool step. Today the service runs model steps only — a pure or tool step is refused before the run starts — and a chain needs at least one model step that is granted a tool, and at most eight of them. A chain runs once it is saved as a workflow in your workspace. The expression describes the shape only. Kortecx still checks and authorises every step it runs; a chain changes what is proposed, never what is allowed.

The result is a DAG — a directed acyclic graph. "Directed" means edges point one way, parent to child. "Acyclic" means nothing loops back on itself. If you write a loop, authoring fails before anything runs.

The operators

a > b        sequential — b reads a's output
a & b        parallel — both run, no edge between them
a | b        parallel — the same thing, looser binding
[ a > b ]    grouping — overrides precedence
plan@tool    tool grants on a model handle

Whitespace does not matter. a>b and a > b are the same expression.

Precedence

Tightest first. This is the part that decides what your expression actually means.

OperatorMeaningBinding
@tag a tool onto a model handletightest (a handle suffix)
[ ]groupingtightest
>sequential — adds a data edgetighter
&parallel mergelooser
|parallel mergeloosest

& and | are the same operation — a parallel merge that adds no edges. They sit at two precedence levels so you can express tight and loose grouping without brackets. Use [ ] when you want to be explicit.

A handle used twice is the same node

This is the rule that turns a line of text into a graph. The first time a handle appears it registers a node. Every later appearance refers to that same node — it is not a copy.

a > b | a > c

Three nodes (a, b, c) and two edges, both out of a. Reuse is how you build a DAG without drawing one.

Worked examples

Nodes are listed in first-appearance order; the position in that list is the node index. Edges are written parent → child after the canonical sort.

ExpressionNodesEdgesShape
a > ba, b0→1sequential
a > b > ca, b, c0→1, 1→2pipeline
a > [b & c]a, b, c0→1, 0→2fan-out
[a & b] > ca, b, c0→2, 1→2fan-in
[a & b] > [c & d]a, b, c, d0→2, 0→3, 1→2, 1→3full join
a > b | ca, b, c0→1> binds tighter than |
a & b > ca, b, c1→2> binds tighter than &
a > b | a > ca, b, c0→1, 0→2reuse builds a fan-out

Read a > [b & c] as fan-out: a runs, then b and c both run on its output. Read [a & b] > c as fan-in: a and b both run, and c waits for both.

The trap is precedence. a > b & c is not a fan-out — it parses as (a > b) & c, so only a → b gets an edge and c is a second, unconnected root. Bracket the parallel side when you mean to fan out.

When authoring fails

Every one of these fails before a run starts, with a named error class:

What you wroteError
An empty expression, or an empty group []parse
A dangling @ — p@, p@@x, @toolparse
A handle that is not in your task mapunknown handle
A cycle or self-loop — a > a, a > b | b > acycle
@ grants on a non-model step — pure@toolgrants on a non-model step

Tasks you define but never use in the expression are ignored.

Running a chain

Ask for a workflow in plain language and the console shows you what it would run — the steps in order, the edges between them, and anything it could not resolve — before you run it.

You can see these in the console.

Model steps need a served model

A model step in a chain only runs against a model this runtime is serving. Leave model_id empty and the runtime binds the served model for you. Name a model the runtime is not serving and authoring is refused before anything runs — the runtime never routes a step to a model it does not offer.

Tool grants on a model step

A model handle can carry tool tags with @:

plan@web-search@fs-list > review

plan is one node granted two tools, and review is a downstream step. The tags are order-preserving and de-duplicated, so p@x@x is the same as p@x. The runtime resolves each tagged tool and builds that step's grants — you never hand it a grant. The tool set is part of the step's identity, so resuming or re-running gives you the same step, granted exactly the same tools.

The turn budget for the reason-tool-observe loop comes from the run's tier — 16 turns and 20 tool calls at the standard tier. A max_turns or max_tool_calls on a single step is not read today, so it does not narrow that budget. The two are independent, because a single turn can fire several tool calls at once. See Tools for what a tool is and how it gets registered.

Reusable shapes

Five shapes cover most of what people build. Each is an ordinary chain — no new step kind, no new wire format — so recovery and delivery behave identically whichever you pick.

ShapeTopology
Map-reduce[m0 & m1 & …] > reduce
Fan-out / gather[w0 & w1 & …] > gather
Supervisorplanner > [w0 & w1 & …] > gather
Consensus[v0 & v1 & …] > reduce
Review loopworker > review > review > …

Map-reduce and fan-out/gather are the same fan-in family. The difference is intent: map-reduce folds a uniform list of mapper outputs with a deterministic reduce (a pure step, which the service does not run yet); fan-out/gather collects outputs that differ from each other and merges them.

The review loop is iterative refinement. A worker drafts, then a reviewer reads the previous version — its data-edge parent — and emits a better one, for however many rounds you ask for. The last step's output is the result. This is an author-static loop: you fix the number of rounds up front.

Multi-agent patterns

Each of the three multi-agent patterns below composes down to an ordinary chain.

Swarm — many angles, one answer

N agents run at the same time, each an independent step that finishes on its own. A gather step fires once they have all finished and merges their outputs into one answer.

Supervisor — plan, delegate, integrate

A lead planner breaks the goal into subtasks. Every worker runs on that plan — the planner's output is a data-edge parent of each worker. Then the lead integrates the results.

This is a static hierarchy: a fixed team, decided up front.

Agents chain inside one workflow

A supervisor delegates to agents in the same graph. One app has no way to hand work to a second app — when you want more moving parts, add more agents to the workflow rather than reaching for another app. See Apps.

Consensus — a judge picks one

N voters answer independently, then the graph reduces to one answer:

  • A judge (the default) — a model judge reads the candidates and selects the single best one, verbatim. It does not merge them. That is what separates it from a swarm's gather.

Run history and re-running

Every run is recorded, so you can list what happened, and fork a run an app started.

A run an app started can be forked, which starts a new run: a retry re-runs only the steps that did not finish, and a restart re-runs one step and everything after it, reusing the rest.

ExampleAn App's run stops at a failed step and keeps its reason; a retry from that step does not run the finished steps again, and the message is sent once.

For what a run emits while it is going, and where a failure ends up, see Observability.

What holds

  • No new primitives. Swarm, supervisor, consensus and the review loop are compositions of the same fan-out, fan-in and sequential edges as every other chain. No new step kind, no new wire format.
  • Interrupted work resumes. Press run again with the same idempotency key and the run re-derives the same chain, so work it already committed is returned rather than done again, and a step that already reached the outside world is not done a second time. See what you can rely on.
  • The client proposes, the runtime decides. The runtime compiles and authorises every step. Chains, swarms and workflow files change what is proposed — never what is allowed.
  • Know the edges. What a chain does not promise about capacity, latency and concurrency is stated plainly in production notes and limitations.