Language Reference

Complete syntax for .dip workflow files.

File Structure

Every .dip file contains exactly one workflow. The top-level structure has four sections that must appear in order:

workflow <name>
Header
goal, start, exit
Defaults (optional)
model, provider, ...
Node Definitions
agent, human, tool, ...
Edges (optional)
A -> B when ...

Dippin uses indentation-sensitive syntax (like Python). Use 2 spaces or tabs consistently. The canonical formatter always outputs 2-space indentation.

Workflow Header

The workflow declaration is the first line, followed by required and optional header fields:

workflow my_pipeline
  goal: "Ask user for a task, implement it, review, ship"
  start: AskUser
  exit: Done
FieldRequiredDescription
workflow <name>YesDeclares the workflow and its identifier
goal: <text>NoHuman-readable objective for this pipeline
start: <NodeID>YesEntry point node — execution begins here
exit: <NodeID>YesTerminal node — execution ends here

Defaults Block

The optional defaults block sets graph-level configuration that applies to all nodes unless overridden at the node level.

  defaults
    model: claude-opus-4-6
    provider: anthropic
    retry_policy: standard
    max_retries: 3
    fidelity: high
    max_restarts: 5
    cache_tools: true
    compaction: summary
FieldTypeDescription
modelStringDefault LLM model for all agent nodes
providerStringDefault LLM provider (e.g., "openai", "anthropic")
retry_policyStringDefault retry strategy name
max_retriesIntegerDefault max retry attempts per node
fidelityStringDefault checkpoint fidelity level
max_restartsIntegerMax loop restarts before pipeline failure (default: 5)
cache_toolsBooleanWhether to cache tool call results
compactionStringContext compaction mode for long pipelines

Node Kinds

There are 6 node kinds, each with its own syntax and configuration:

agent
LLM interaction
human
Decision gate
tool
Shell command
parallel
Fan-out
fan_in
Join
subgraph
Sub-pipeline

agent

Agent nodes invoke an LLM. They are the most configurable node kind. Key fields include model, provider, prompt, system_prompt, max_turns, auto_status, and goal_gate.

  agent Analyze
    label: "Analyze the request"
    model: claude-opus-4-6
    provider: anthropic
    goal_gate: true
    auto_status: true
    reads: human_response
    writes: analysis
    prompt:
      You are a senior software architect.
      Analyze the following request carefully.
FieldTypeDescription
modelStringLLM model to use (overrides defaults)
providerStringLLM provider (e.g., "anthropic", "openai")
promptBlockMultiline prompt text sent to the model
system_promptBlockSystem-level instructions prepended before the prompt
max_turnsIntegerMaximum conversation turns before the node exits
auto_statusBooleanAutomatically extract STATUS: success/fail from model output into ctx.outcome
goal_gateBooleanMarks this node as a goal gate — requires retry_target or fallback_target for recovery
readsStringContext key this node reads as input (advisory metadata)
writesStringContext key this node writes as output (advisory metadata)
response_formatStringStructured output mode: json_object or json_schema. Instructs the model to return valid JSON.
response_schemaBlockJSON Schema definition enforced when response_format: json_schema is set. Must be valid JSON.
paramsBlockArbitrary key-value pairs forwarded to the provider API. Keys must not duplicate first-class fields (see DIP133).
cmd_timeoutDurationMaximum wall-clock time for this agent call before the runtime cancels and errors (e.g., 30s, 2m).

human

Human nodes pause execution and wait for human input. Two modes: choice (predefined options from edge labels) and freeform (open text input).

  human Approve
    label: "Ship it?"
    mode: choice
    default: "yes"

tool

Tool nodes execute shell commands. The command's stdout is captured as ctx.tool_stdout and stderr as ctx.tool_stderr. Always include a timeout.

  tool RunTests
    label: "Run test suite"
    timeout: 60s
    command:
      #!/bin/sh
      set -eu
      pytest --tb=short 2>&1

parallel

Parallel nodes fan execution out to multiple branches that run concurrently. Every parallel must have a matching fan_in.

  parallel FanOut -> TaskA, TaskB, TaskC

fan_in

Fan-in nodes join concurrent branches back together. Sources must match the targets of a corresponding parallel node.

  fan_in Join <- TaskA, TaskB, TaskC

subgraph

Subgraph nodes embed another workflow as a single step. Parameters are passed via the params.* namespace.

  subgraph ReviewProcess
    ref: review_pipeline
    params:
      strict: true
      model: gpt-5.4

Edges

The edges block defines connections between nodes. Each edge is a single line:

<FromID> -> <ToID> [when <condition>] [label: <text>] [weight: <int>] [restart: true]

Basic and Conditional Edges

  edges
    AskUser -> Interpret
    Interpret -> Validate
    Validate -> Approve   when ctx.outcome = success
    Validate -> Retry     when ctx.outcome = fail

Edge Attributes

AttributeTypeDescription
when <expr>ConditionBoolean guard — edge only traversed if true
label: <text>StringHuman-readable label (used for human gate choices)
weight: <int>IntegerPriority hint — higher wins among competing edges
restart: trueBooleanMarks this as a back-edge (loop restart)

Restart Edges

Restart edges create controlled loops. When followed, the engine increments a restart counter (max controlled by max_restarts), clears downstream nodes, resets retry budgets, and resumes from the target.

    Task -> Start when ctx.outcome = fail label: "retry" restart: true

Conditions

Conditions appear on edges after the when keyword. All operators perform string comparison.

Comparison Operators

OperatorMeaningExample
=, ==String equalityctx.outcome = success
!=String inequalityctx.outcome != fail
containsSubstring matchctx.response contains "approved"
not containsNegated substringctx.tool_stdout not contains all-done
startswithPrefix matchctx.response startswith "yes"
endswithSuffix matchctx.response endswith "done"
inValue in listctx.status in "pass,fail,skip"

Logical Operators

OperatorMeaningPrecedence
notLogical negationHighest
andLogical ANDMedium
orLogical ORLowest

Parentheses control precedence:

    A -> B when ctx.outcome = success and ctx.score = high
    A -> C when ctx.outcome = fail or ctx.status = blocked
    A -> D when (ctx.x = 1 or ctx.y = 2) and ctx.z = 3

Multiline Blocks

Fields like prompt and command support multiline content. Write the key followed by :, then indent the content on subsequent lines:

  agent MyAgent
    prompt:
      You are a code reviewer.

      ## Rules
      - Check for bugs
      - Check for security issues

      ## Context
      ${ctx.last_response}

The first content line's indentation sets the baseline. All content is de-indented by that amount. Empty lines are preserved. The block ends when indentation returns to or above the field's level. No quoting or escaping needed.

  tool RunTests
    timeout: 60s
    command:
      #!/bin/sh
      set -eu
      if pytest --tb=short 2>&1; then
        printf 'pass'
      else
        printf 'fail'
        exit 1
      fi