Skip to content

DSL Reference

The HBIA DSL (Domain Specific Language) is a YAML format for defining DAG-based workflows. This is the semantic layer that AI agents read to understand your entire application architecture.

File Format

flow:
  flow_name:
    vertex_name:
      handler: module.path.function
      effect: pure | side_effect
      version: "1"
      inputs:
        param_name: type | vertex_name.output_name
      outputs:
        output_name: type
      next:
        - other_vertex

atomic_groups:
  group_name:
    vertices: [vertex_a, vertex_b]
    on_failure: rollback | compensate | abort
    no_cache: true
    no_parallel: true

Top-Level Keys

Key Required Description
flow Yes Contains one or more named flow definitions
atomic_groups No Declares transactional vertex groups

Flow Definition

A flow is a named collection of vertices connected by edges:

flow:
  create_user:            # Flow name
    normalize:            # Vertex name (must be unique within the file)
      handler: ...
      next: [validate]
    validate:
      handler: ...
      next: [save]
    save:
      handler: ...

Entry Point Detection

HBIA automatically identifies the entry point of each flow. The entry vertex is the one that no other vertex lists in its next field — it has zero incoming edges.

In the example above, normalize is the entry point because neither validate nor save list it in next.

Vertex Fields

handler (required)

Dotted Python import path to the handler function:

handler: vertices.users.normalize
# Resolves to: from vertices.users import normalize

Declares whether the vertex has side effects:

effect: pure           # No side effects — cacheable, retriable
effect: side_effect    # Has side effects — database, API, file I/O

Version string for change tracking:

version: "1"
version: "2.0"

inputs

Input declarations. Two formats:

Type declaration — plain type name:

inputs:
  username: str
  age: int

Data binding — dotted reference to another vertex's output:

inputs:
  username: normalize.username     # Reads from normalize's output
  email: normalize.email

Rule: if the value contains a ., it's a data binding. Otherwise, it's a type declaration.

Supported types: str, int, float, bool, dict, list, tuple, set, bytes, none.

outputs

Output type declarations:

outputs:
  user_id: str
  saved: bool
  errors: list

next

List of vertices that execute after this one. Creates edges in the DAG:

next:
  - validate
  - log_event       # Fan-out: two edges from this vertex

A vertex with no next is a sink (terminal node).

Atomic Groups

atomic_groups:
  payment_txn:
    vertices: [reserve, charge, confirm]
    on_failure: rollback
    no_cache: true
    no_parallel: true

Fields

Field Required Default Description
vertices Yes List of vertex names
on_failure Yes rollback, compensate, or abort
no_cache No true Bypass cache inside the group
no_parallel No true Force serial execution in the group

Failure Policies

  • rollback — Snapshot the data store, state store, and lineage before execution. On failure, restore the snapshots.
  • compensate — Use SAGA-style compensating handlers to undo completed steps. Required when rollback isn't possible (external APIs).
  • abort — Stop execution immediately with no cleanup.

Complete Example

flow:
  process_order:
    validate_order:
      handler: vertices.orders.validate
      effect: pure
      version: "1"
      inputs:
        order_data: dict
      outputs:
        is_valid: bool
        items: list
        total: float
      next:
        - check_inventory

    check_inventory:
      handler: vertices.orders.check_inventory
      effect: side_effect
      version: "1"
      inputs:
        items: validate_order.items
      outputs:
        available: bool
        reserved_items: list
      next:
        - process_payment

    process_payment:
      handler: vertices.orders.charge
      effect: side_effect
      version: "1"
      inputs:
        total: validate_order.total
        available: check_inventory.available
      outputs:
        transaction_id: str
        charged: bool
      next:
        - send_confirmation

    send_confirmation:
      handler: vertices.orders.send_email
      effect: side_effect
      version: "1"
      inputs:
        transaction_id: process_payment.transaction_id
        items: check_inventory.reserved_items
      outputs:
        email_sent: bool

atomic_groups:
  payment_group:
    vertices: [check_inventory, process_payment]
    on_failure: rollback
    no_cache: true
    no_parallel: true

Schema Version

The graph model supports a schema_version field for future format evolution. The current version is "1".

Naming Conventions

  • Vertex names: snake_case (e.g., fetch_user, validate_input). The linter warns on non-snake_case names (W006).
  • Flow names: snake_case (e.g., create_user, process_payment).
  • Handler paths: Standard Python dotted paths (e.g., vertices.users.fetch).
  • Atomic group names: snake_case (e.g., payment_txn).