Defining Flows¶
This section covers the YAML flow format in detail — vertices, edges, data bindings, effects, and atomic groups.
Flow Structure¶
Every flow file has this top-level structure:
flow:
flow_name:
vertex_a:
# vertex definition
vertex_b:
# vertex definition
atomic_groups: # optional
group_name:
vertices: [vertex_a, vertex_b]
on_failure: rollback
The flow key contains one or more named flows. Each flow contains vertices as nested keys. The atomic_groups key is optional and declares transactional boundaries.
Vertex Fields¶
Each vertex supports these fields:
| Field | Required | Description |
|---|---|---|
handler |
Yes | Dotted path to the Python function |
effect |
Recommended | pure or side_effect |
version |
Recommended | Version string (e.g., "1", "2.0") |
inputs |
No | Input declarations and data bindings |
outputs |
No | Output type declarations |
next |
No | List of vertices that execute after this one |
Handler¶
The handler field is a dotted Python import path:
At runtime, HBIA imports the module and resolves the function. You can also provide handler functions directly when using the Python API.
Effect¶
The effect field declares whether a vertex has side effects:
pure— No side effects. The function always returns the same output for the same input. Pure vertices can be cached, retried, and run in parallel safely.side_effect— Has side effects (database writes, API calls, file I/O). Side-effect vertices skip caching and are treated with care during atomic execution.
normalize:
handler: vertices.users.normalize
effect: pure # safe to cache and retry
save:
handler: vertices.users.save
effect: side_effect # writes to database
Warning
If you omit effect, the linter will warn you (W001). Always declare effects — it's critical information for both the execution engine and AI agents.
Version¶
Version tracking for the rewrite-over-patch philosophy:
When an AI agent modifies a vertex, it creates a new handler function and bumps the version number rather than patching the existing code. This makes changes atomic and auditable.
Inputs¶
Inputs serve two purposes:
-
Type declarations — a plain type name means "this vertex expects this type":
-
Data bindings — a dotted reference resolves to another vertex's output at runtime:
The rule is simple: if the value contains a ., it's a data binding. Otherwise, it's a type declaration.
At runtime, data bindings are resolved from the DataStore, which holds all outputs from previously executed vertices. If a binding cannot be resolved, HBIA raises a DataResolutionError.
Outputs¶
Output declarations define what the vertex produces:
Supported type names: str, int, float, bool, dict, list, tuple, set, bytes, none.
Next¶
The next field creates edges in the DAG:
A vertex with no next field is a sink — a terminal node in the graph. A vertex that no other vertex lists in next is a source — an entry point.
Common Patterns¶
Linear Pipeline¶
flow:
process:
extract:
handler: vertices.extract
effect: pure
version: "1"
outputs:
raw_data: dict
next:
- transform
transform:
handler: vertices.transform
effect: pure
version: "1"
inputs:
raw_data: extract.raw_data
outputs:
clean_data: dict
next:
- load
load:
handler: vertices.load
effect: side_effect
version: "1"
inputs:
clean_data: transform.clean_data
outputs:
success: bool
Diamond (Fan-Out / Fan-In)¶
flow:
analyze:
fetch:
handler: vertices.fetch
effect: side_effect
version: "1"
outputs:
data: dict
next:
- analyze_text
- analyze_images
analyze_text:
handler: vertices.analyze_text
effect: pure
version: "1"
inputs:
data: fetch.data
outputs:
text_score: float
next:
- combine
analyze_images:
handler: vertices.analyze_images
effect: pure
version: "1"
inputs:
data: fetch.data
outputs:
image_score: float
next:
- combine
combine:
handler: vertices.combine
effect: pure
version: "1"
inputs:
text_score: analyze_text.text_score
image_score: analyze_images.image_score
outputs:
final_score: float
In this diamond pattern, analyze_text and analyze_images share no dependencies on each other, so they are placed in the same execution stage and can run in parallel automatically when PARALLEL_ENABLED=True.
Multiple Flows in One File¶
flow:
create_user:
validate:
# ...
next: [save]
save:
# ...
delete_user:
check_permissions:
# ...
next: [delete]
delete:
# ...
Atomic Groups¶
Atomic groups wrap sets of vertices in all-or-nothing semantics. If any vertex in the group fails, the entire group is rolled back.
flow:
payment:
validate_card:
handler: vertices.payment.validate_card
effect: pure
version: "1"
outputs:
card_valid: bool
next:
- reserve_funds
reserve_funds:
handler: vertices.payment.reserve
effect: side_effect
version: "1"
inputs:
card_valid: validate_card.card_valid
outputs:
reservation_id: str
next:
- charge
charge:
handler: vertices.payment.charge
effect: side_effect
version: "1"
inputs:
reservation_id: reserve_funds.reservation_id
outputs:
transaction_id: str
next:
- confirm
confirm:
handler: vertices.payment.confirm
effect: side_effect
version: "1"
inputs:
transaction_id: charge.transaction_id
outputs:
confirmed: bool
atomic_groups:
payment_processing:
vertices: [reserve_funds, charge, confirm]
on_failure: rollback
no_cache: true
no_parallel: true
Atomic Group Fields¶
| Field | Required | Description |
|---|---|---|
vertices |
Yes | List of vertex names in the group |
on_failure |
Yes | rollback, compensate, or abort |
no_cache |
No | true to bypass cache inside the group (default: true) |
no_parallel |
No | true to force serial execution (default: true) |
Failure Policies¶
rollback— Restore data store, state store, and lineage to pre-group snapshots. The most common choice for database transactions.compensate— Use SAGA-style compensation handlers to undo completed steps. Necessary when rollback is impossible (e.g., external API calls).abort— Stop execution immediately with no cleanup. Use when failure is unrecoverable.
For detailed information on atomicity and SAGAs, see the Atomicity and SAGA Pattern sections.
Validation¶
Always validate your flows before running them:
# DSL validation (YAML structure, field types, references)
hbia validate flows/payment.yaml
# Graph validation (cycles, connectivity, atomic group integrity)
hbia graph-validate flows/payment.yaml
# Linting (best practices, naming conventions, missing fields)
hbia lint flows/