Skip to main content

Flows

A flow is a named, ordered composition of tools: a plan that says "read the document, run these steps in this order, write the result." A tool does one thing. A flow assembles several into an end-to-end workflow (leverage from memory, look up terminology, translate the remainder, check quality) and gives it a name, so you can run it again and share it.

A flow describes the chain, and the pipeline executor runs it concurrently. kapi flows and the Command Reference list the flows that ship in a given build.

In the CLI, a flow is the abstraction behind kapi run <flow>: one named flow, one pass. kapi up loops the project's default flow (defaults.flow, or the built-in default when none is set) until the project's gates are met. Understanding the CLI layers explains how the two verbs relate and where the raw tool layer sits.

A flow is a sequence of tools​

At its simplest, a flow is a list of tools that Parts stream through in order. The framework models this directly:

type Flow struct {
Name string
Tools []tool.Tool // for single-document / sequential execution
ToolFactories []ToolFactory // for parallel: a fresh tool chain per document
}

The Builder provides a fluent API for assembling one in Go:

f, err := flow.NewFlow("translate").
AddTool(tools.NewMemoryLeverageTool(memoryCfg)).
AddTool(terms.NewTermLookupTool(tb, termCfg)).
AddTool(aitools.NewAITranslateTool(provider, translateCfg)).
AddTool(tools.NewRuleCheckTool(checkCfg)).
Build()

A flow built this way holds concrete tool instances. For running the same flow over many documents at once, a flow can instead hold tool factories: each document then gets its own fresh tool chain, so per-document state never leaks between concurrent runs.

The two authored representations​

A flow can be authored in two equivalent forms, and both compile to the same executable graph.

Steps: the human-authored form​

The steps format is a YAML list of tools. It is the form people write by hand:

steps:
- tool: recycle
label: Apply memory matches
config:
fuzzyThreshold: 70
- tool: translate
label: Translate the rest
config:
provider: anthropic
- tool: qa
label: Quality checks

Each step names a tool and optionally configures it. Steps run sequentially: each tool's output channel feeds the next tool's input channel. At run time the flow above becomes this chain, with the ends bound when you run it:

sourcebindingchanrecyclememory matcheschantranslatethe restchanqafindingschansinkbinding

A flow carries only its steps. Where content comes from and goes to is a binding you choose when you run it (see Source and sink).

A project declares its flows in kapi.yaml, inline under flows:, or as one steps file per flow in the directory the recipe names with flows_dir: (see Flow files). kapi flows lists both kinds beside the built-in flows, and kapi run <name> runs either over the project's collections.

A check such as qa is a read-only step. It attaches findings to each block as annotations and leaves the content as it is, so it usually sits last, where a CI gate reads its result.

To run several checks, list them in order:

steps:
- tool: create-target
config: { copySource: true }
- tool: qa
- tool: term-check
- tool: xml-validation

Transformers​

Some tools rewrite the source itself: redaction replacing sensitive spans with placeholders, a simplifier rephrasing for clarity, a normalizer. These transformers are ordinary steps in the same ordered list as everything else:

steps:
- tool: redact # rewrites the source in place
- tool: translate # translates the redacted source
- tool: qa

A transformer is a read-only edit producer. It returns an edit plan, and a single framework-owned applier performs the rewrite atomically: it applies the edits, rebases surviving run-anchored overlays (segments, term and entity spans) onto the new runs, vaults any secrets fail-closed, and bounds-checks the result. Because the applier mutates inline and in order, each transformer settles the source before later steps observe it.

A placement pass checks the step order of every flow at build and load time. It rejects a transformer placed after a step that produces a committed target (rewriting source would orphan the targets; unredact is exempt because it rewrites both sides), rejects a recoverable transformer such as redact placed after a step that sends source to a remote service (except a step producing an input the transformer's configuration requires), and warns when a transformer sits later than its earliest valid slot, since every overlay present at apply time must be rebased. See the tool system AD for the model.

A flow that declares the removed source_transforms: field is rejected at load with a migration error: list the transformers as ordered steps instead.

Graph: the canonical form​

Internally a flow is a directed graph of tool nodes connected by edges:

type FlowDefinition struct {
ID string
Name string
Nodes []FlowNode // tool nodes
Edges []FlowEdge // directed connections
}

The graph is what the visual flow editor reads and writes. Compilation from steps to graph is mechanical: StepsToGraph creates a tool node for each step, chained by edges. Cycles are rejected, and kapi runs the tool nodes as one ordered chain, each tool's output feeding the next. The flow's ends (where content enters and leaves) are bindings, covered next.

Because both forms compile to the same graph, the steps you write by hand and the graph you build in the editor are interchangeable: a hand-written flow opens in the editor, and an editor-built flow runs from the CLI.

Build a flow, then run it

Assemble a flow in the same node editor the desktop app uses (add, remove, and reorder tool nodes), then press Run flow to execute it on a file and step through the result. The graph is serialized to a kapi.yaml recipe and run with the real kapi engine in your browser via WebAssembly.

Loading the interactive lab…

Source and sink: the flow's ends​

A flow processes a stream of blocks; where that stream comes from and where the result goes are its source and sink bindings. The same flow runs over a loose file, the blocks already in a project, a .kpz workspace, or content imported from an interchange file; only the binding changes:

BindingAs sourceAs sink
file (default)read + parse a filewrite a file (round-trip via skeleton)
store / kpzexisting blocks + overlayscommit overlays; no file
interchangeimport from XLIFF / PO / a bilingual .kpzemit interchange for a translator
none(none)discard (analysis / checks only)

Bindings are resolved when you run the flow, by precedence: an explicit -i / -o flag, then the project or .kpz you're in, then the flow's own intent, then auto-detection from the path. A plain path is detected (.kpz → workspace, .xliff → interchange, a document → file); a scheme: is explicit (-o store:, -o xliff:hand.xliff). kapi run <flow> --explain prints the resolved source → sink without running anything.

A flow declares only intrinsic intent (a check flow that produces no document sets sink: none), never a path. Inside a project, a run with no -o lands its work in the store (process-only); kapi merge materializes files when you're ready. See E-04 for the full model.

Running a flow​

A flow is run against a source. The runner resolves the source and sink bindings, instantiates the tool chain, and hands it to the executor. Composed (multi-tool) flows run with kapi run; single-tool flows are exposed directly as their tool's command:

# Run a composed flow (two or more tools) on a file
kapi run translate-qa -i app.xliff --target-lang fr

# List the composed flows available in this build
kapi flows

The demo below runs the pseudo-translate flow: source → pseudo-translate → sink. Because it is a single-tool flow, it is invoked directly as kapi pseudo-translate. The left pane is the CLI invocation; the right pane is the framework's result, the same file with its source strings replaced by accented look-alikes:

Built-in flows​

The framework ships a set of built-in flows covering common workflows: AI translation, AI translation with a quality pass, pseudo-translation for layout testing, memory leverage, rule-based checks, a redact-translate-restore flow for sensitive content, and media-to-subtitles flows that turn audio and video into translated subtitle tracks (see Translate audio & video). For the full list, run kapi flows or see the Command Reference; both are generated from the live flow set.

  • Tools: the units a flow composes.
  • Pipeline: how the executor runs a flow's graph concurrently.
  • Flow Authoring: the full steps-format reference and more examples.