Creating Custom Flows
Define your own workflows as YAML files, one per flow, in a directory your
recipe names with flows_dir::
# kapi.yaml
flows_dir: flows
The path is relative to the recipe. Keep the directory committed with the
recipe; kapi rejects a flows_dir under .kapi/, which is a cache for one
checkout. A flow can also be declared inline under flows: in kapi.yaml.
Flow definition format
name: my-flow
description: Brief description of what this flow does
steps:
- tool: tool-name
config:
optionA: value
- tool: another-tool
config:
optionB: value
Step config keys are the tool's own schema keys, in camelCase, exactly as the
tool reference lists them. kapi ignores an
unrecognized key without an error, so a misspelled key silently drops its
option. The locale comes from the run's --target-lang, or from the recipe
inside a project, so one flow serves every locale. kapi tools lists the
tools your installation provides, plugins included.
Example flows
Simple AI drafting
flows/translate-simple.yaml:
name: translate-simple
description: AI drafting with the project's default provider settings
steps:
- tool: translate
config:
provider: anthropic
model: claude-sonnet-5
The provider and model keys accept any provider the
translate tool
supports; omit them to use the project's defaults.
Reuse first, then draft, then check
flows/full-translation.yaml:
name: full-translation
description: Reuse from memory, draft the remainder, check terms and quality
steps:
# 1. Pre-fill from content memory before spending any credits
- tool: recycle
# 2. Draft what memory could not fill
- tool: translate
config:
provider: anthropic
model: claude-sonnet-5
# 3. Check the terms in force at each block's point
- tool: term-check
config:
caseSensitive: true
# 4. Run quality checks
- tool: qa
config:
checkDoubleSpaces: true
checkDoubledWord: true
checkPatterns: true
checkTargetInconsistency: true
The recycle and term-check steps read the project's content memory and terms
(or a profile's own termstore:), so they take no path of their own. See the
recycle and
term-check references
for their options.
Checks only
flows/checks-only.yaml:
name: checks-only
description: Quality and term checks without drafting
steps:
- tool: placeholder-check
config:
flagExtra: true
- tool: term-check
- tool: qa
config:
checkDoubleSpaces: true
checkPatterns: true
Run it, then let kapi check turn the findings into an exit code; see
Source language preparation.
Source cleanup
flows/cleanup.yaml:
name: cleanup
description: Normalize source case, then tidy the target's whitespace
steps:
- tool: case-transform
config:
mode: title
applySource: true
- tool: whitespace-correct
config:
normalizeSpaces: true
matchSourceWhitespace: true
removeZeroWidthChars: true
The wording constraint
term-check, translate and recycle take one key for the wording
constraint, term_rules:, a list of rules naming a term, what to use instead,
and whether a violation fails a check. Inside a project you rarely write it by hand: the
voice profile's vocabulary: and the bound terms store supply the rules in
force at each block's point. See Project model.
Variable substitution
Use environment variables in flow configs:
- tool: translate
config:
provider: anthropic
apiKey: ${ANTHROPIC_API_KEY} # From environment
Running custom flows
# List all flows (built-in + custom)
kapi flows
# Run your custom flow
kapi run my-flow
Best practices
- Name flows descriptively:
translate-review-exportrather thanmy-flow - Document in description: explain what the flow does and why
- Reuse before you draft: put
recycleahead oftranslate - Order matters: place expensive tools (AI) last
- Test incrementally: add one tool at a time
- Commit flows to git: the
flows_dirdirectory is versioned with the recipe - Gate in CI:
kapi check --shipis the enforcement point, not the flow