Skip to content

Workflow YAML Format

Complete schema reference for Binex workflow files.

Root — WorkflowSpec

Field Type Required Description
version int no Schema version (default: 1, must be >= 1). See Versioning below.
name str yes Workflow name
description str no Workflow description (default: "")
nodes dict[str, NodeSpec] yes Map of node_id to node definition
defaults DefaultsSpec no Default settings applied to all nodes
budget BudgetConfig no Budget constraints for the run (see below)
webhook WebhookConfig no Webhook notification target (see below)

Node — NodeSpec

Field Type Required Description
id str no Auto-set from the dict key
agent str yes Agent URI — local://, llm://, a2a://, human://, langchain://, crewai://, autogen://, or custom plugin prefix
system_prompt str no System prompt sent to the agent (supports file:// prefix)
inputs dict[str, Any] no Input key-value pairs; supports variable interpolation
outputs list[str] yes Artifact names this node produces
depends_on list[str] no Node IDs that must complete before this node runs
config dict[str, Any] no Per-node config forwarded to the adapter (see below)
retry_policy RetryPolicy no Override the default retry settings
deadline_ms int no Override the default deadline for this node
when str no Conditional execution expression (see below)
cost NodeCostHint no Optional cost estimate for planning (see below)
budget float or NodeBudget no Per-node budget limit (shorthand: budget: 0.50, full: budget: { max_cost: 0.50 })
output_schema dict no JSON Schema for validating node output. Failed validation triggers auto-retry
routing dict no Per-node Gateway routing overrides (see below)

config keys (LLM adapter)

Key Example Effect
api_base "http://localhost:11434" LiteLLM API base URL
api_key "sk-..." Provider API key
temperature 0.7 Sampling temperature
max_tokens 4096 Max tokens in completion

All config values are forwarded to litellm.acompletion() when not None.

External System Prompt — file://

The system_prompt field supports loading content from an external file using the file:// prefix. Relative paths are resolved relative to the workflow YAML file's directory. Absolute paths are used as-is.

nodes:
  researcher:
    agent: "llm://openai/gpt-4"
    system_prompt: "file://prompts/researcher.md"
    outputs: [findings]

If the referenced file does not exist, workflow loading fails with a clear error message.

Conditional Execution — when

The when field enables conditional node execution based on upstream artifact values. A node with a when condition is skipped (not failed) if the condition evaluates to false. Skipped nodes count as resolved for downstream dependency purposes.

Operators:

Operator Example Meaning
== ${review.decision} == approved Run only if artifact content equals "approved"
!= ${review.decision} != rejected Run only if artifact content does not equal "rejected"

Example — approval gate with branching:

publish:
  agent: "local://echo"
  inputs:
    final: "${revise.content}"
  outputs: [result]
  depends_on: [human_review]
  when: "${human_review.decision} == approved"

discard:
  agent: "local://echo"
  inputs: {}
  outputs: [notice]
  depends_on: [human_review]
  when: "${human_review.decision} == rejected"

The when field is commonly used with human://approve nodes but works with any artifact value.

Defaults — DefaultsSpec

Field Type Default Description
deadline_ms int 120000 Default deadline in milliseconds
retry_policy RetryPolicy see below Default retry policy for all nodes

Retry — RetryPolicy

Field Type Default Description
max_retries int 1 Maximum retry attempts
backoff "fixed" or "exponential" "exponential" Backoff strategy between retries

Budget — BudgetConfig

Budget constraints limit the total cost of a workflow run. The orchestrator checks accumulated cost after each batch of nodes.

Field Type Default Description
max_cost float Maximum allowed cost in the specified currency (must be > 0)
currency str "USD" Currency code
policy "stop" or "warn" "warn" What to do when budget is exceeded

Budget Policies

Policy Behavior
stop Skip all remaining nodes, set run status to "over_budget"
warn Log a warning to stderr, continue execution

Example:

name: budgeted-pipeline
budget:
  max_cost: 5.0
  policy: stop

nodes:
  planner:
    agent: "llm://gpt-4o"
    outputs: [plan]
  researcher:
    agent: "llm://claude-sonnet-4-20250514"
    outputs: [findings]
    depends_on: [planner]
  summarizer:
    agent: "llm://gpt-4o"
    outputs: [summary]
    depends_on: [researcher]

If the accumulated cost exceeds $5.00 after the researcher node, the summarizer is skipped and the run status is "over_budget".

See the Budget & Cost Tracking Guide for more examples and patterns.

With --json, the run output includes budget information:

{
  "status": "over_budget",
  "total_cost": 5.23,
  "budget": 5.0,
  "remaining_budget": -0.23
}

Node Cost Hint — NodeCostHint

Optional cost estimate for planning purposes. Does not affect execution — purely informational.

Field Type Default Description
estimate float 0.0 Estimated cost for this node (must be >= 0)
nodes:
  expensive_node:
    agent: "llm://gpt-4o"
    outputs: [result]
    cost:
      estimate: 2.50

Per-Node Budget — NodeBudget

Individual nodes can have their own budget limits. The policy is inherited from the workflow-level budget.policy (default: stop).

Field Type Default Description
max_cost float Maximum allowed cost for this node (must be > 0)

Shorthand: budget: 0.50 is equivalent to budget: { max_cost: 0.50 }.

When both workflow and node budgets are defined, the effective limit is min(node_budget, remaining_workflow_budget).

Pre-check before retry: If a node has a budget and fails, the orchestrator checks remaining budget before each retry attempt. With policy: stop, the retry is skipped if budget is exhausted. With policy: warn, the user is prompted via click.confirm().

Post-check after execution: After each execution, if the node's accumulated cost exceeds its budget, the policy determines behavior: stop discards the result and marks the node failed; warn keeps the result and logs a warning.

Example:

name: per-node-budget
budget:
  max_cost: 10.00
  policy: stop

nodes:
  planner:
    agent: "llm://gpt-4o-mini"
    outputs: [plan]
    budget: 0.50           # shorthand

  researcher:
    agent: "llm://gpt-4o"
    outputs: [findings]
    depends_on: [planner]
    budget:
      max_cost: 3.00       # full form

  summarizer:
    agent: "llm://gpt-4o"
    outputs: [summary]
    depends_on: [researcher]
    budget: 2.00

If the planner costs $0.60 (exceeding its $0.50 limit), it is marked as failed and dependent nodes do not run.

Output Schema Validation

Nodes can define a JSON Schema to validate their output. If the output fails validation and the node has retries remaining, Binex automatically retries the node.

Field Type Default Description
output_schema dict None Standard JSON Schema object

Example:

nodes:
  extractor:
    agent: "llm://openai/gpt-4o"
    system_prompt: "Extract structured data. Return valid JSON."
    outputs: [result]
    output_schema:
      type: object
      properties:
        title:
          type: string
        score:
          type: number
          minimum: 0
          maximum: 100
      required:
        - title
        - score
    retry_policy:
      max_retries: 2

If the LLM returns output that doesn't match the schema (e.g., missing title field or score out of range), the node is retried automatically. After all retries are exhausted, the node fails with a validation error.

The validator handles both JSON string output (parsed first) and dict output (validated directly).

Routing Overrides

When a Gateway is configured (either embedded via gateway.yaml or standalone via --gateway), individual nodes can override the default routing behavior using the routing field:

nodes:
  critical_search:
    agent: "a2a://research"
    routing:
      prefer: lowest_latency
      timeout_ms: 10000
      retry_count: 5
      failover: true
Key Type Default Description
prefer str "highest_priority" Selection strategy (highest_priority, lowest_latency, round_robin)
timeout_ms int null Override request timeout for this node
retry_count int null Override retry count for this node
failover bool null Override failover setting for this node

Routing overrides only apply when a Gateway is configured. Without a Gateway, the routing field is ignored.

Variable Interpolation

Two variable scopes are available inside inputs values:

Syntax Resolved Description
${user.*} Load time Substituted from --var CLI arguments
${node.*} Runtime References an artifact produced by another node

Example:

inputs:
  query: "${user.query}"          # --var query="LLM agents"
  plan: "${planner.execution_plan}" # artifact from the planner node

Minimal Valid Workflow

name: minimal
nodes:
  only_node:
    agent: "local://echo"
    system_prompt: ping
    inputs:
      msg: "hello"
    outputs: [response]

No defaults, description, depends_on, or config required.

Versioning

Workflow files support schema versioning via the version field. This enables future schema changes with automatic migration.

version: 1
name: my-workflow
nodes:
  step1:
    agent: "local://echo"
    outputs: [result]

Behavior

  • Missing version field: Defaults to version 1 (backward compatible with all existing workflows). A warning is logged.
  • version: 1: Current version — no migration needed.
  • version > CURRENT_VERSION: Raises UnsupportedVersionError at load time. Upgrade Binex to use newer workflows.

Migration framework

When Binex upgrades its schema version, a migration chain transforms older workflow dicts step by step (v1 → v2 → ... → current). Migrations run in-memory at load time — the original YAML file is never modified.

Workflow snapshots

Every binex run stores a normalized, SHA256-deduplicated snapshot of the workflow definition in SQLite. This lets you:

  • Inspect the exact workflow used in any past run via binex debug <run-id>
  • Compare workflows between runs via binex workflow diff <run1> <run2>
  • Reproduce runs even if the original YAML file has changed

Check the workflow version of any file:

binex workflow version examples/simple.yaml

## Webhook — `WebhookConfig`

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `url` | `str` | yes | Webhook endpoint URL |

Webhook notifications are sent on run completion, failure, or budget exceeded. Can also be set via `BINEX_WEBHOOK_URL` environment variable.

```yaml
name: notified-pipeline
webhook:
  url: "https://hooks.example.com/binex"
nodes:
  step1:
    agent: "local://echo"
    outputs: [result]