x-dog

Tools for building AI agents and managing LLM deployments.

GitHub →

x-dog / Packages / flow / Examples

Ten workflows ship with Flow (packages/flow/examples/*.json), from small focused patterns to the flagship Release Radar. Selected examples are runnable on the HaveFun page; every artifact is also available to the CLI, TUI, Coding Agent skill, codegen, and scheduler.

Agent Calculator (script → agent + bash)

Two nodes: make_problem (a script node) turns the typed integer inputs a and b into an arithmetic string like "347 + 895"; solve (an agent node with the bash tool) is told not to do the math in its head — it shells out to compute the expression and replies with the integer.

┌────────────────────────┐
 make_problem [script] *
└────────────┬───────────┘
              problem
        ┌────┘
┌───────▼──────┐
 solve [agent]
└──────────────┘

What running it produces: make_problem builds the expression from the inputs, then solve runs a bash command and returns the answer (e.g. a=12, b=30 → answer "42"). A dry-run only exercises the wiring; a real run has the agent actually compute via bash.

Two agents in a feedback loop: draft writes a concise answer to a topic; critic fact-checks it with the web_search tool and replies APPROVE or REVISE + notes. A bounded loop edge (critic→draft, when the feedback contains REVISE, loop≤2) sends the notes back so draft can improve the answer.

┌────────────────┐
 draft [agent] *│◄───┬───criticdraft [feedback contains:{{feedback}} loop2]
└────────┬───────┘    
          answer     
        ┌┘            
┌───────▼───────┐     
 critic [agent]│─────┘
└───────────────┘

What running it produces: draft produces an answer, critic web-searches to verify it; if it says REVISE the answer is rewritten and re-checked, up to twice, before the loop settles on an APPROVEd answer. This is the canonical generate-and-critique multi-agent pattern.

Essay Writer (a sub-workflow as one node)

Three nodes, but the middle one is a whole workflow. brief (an agent) turns a question into a thesis and three supporting points; compose is a subflow node that references ./essay_compose.json — a reusable draft → critique → revise triad authored as its own standalone, runnable workflow; wrap (a script) counts the words and gates on the critic's score. The compose node declares no ports: its {thesis, points} inputs and {final_essay, score} outputs are derived from the child's signature.

┌──────────────┐
 brief [agent]
└───────┬──────┘
         thesis, key_poin
        └─┐
┌─────────▼────────┐
 compose [subflow]
└─────────┬────────┘
           final_essay, s
        ┌─┘
┌───────▼──────┐
 wrap [script]
└──────────────┘

What running it produces: brief sets the argument; the compose child runs its own draft → critique → revise internally as one opaque step, returning the polished essay plus the critic's score; wrap reports the word count and whether the score cleared the bar. The child is a complete workflow — you can run it on its own. Both engines run compose by calling the same execute() on the child, so interpret == compile holds by construction. See the A Workflow as a Node post for the design.

Flow Release Radar (local repository audit)

release_readiness.json is the flagship demonstration of Flow's product vision: an Agent-authored, human-reviewable workflow that audits this local x-dog repository and can run every Monday.

collect_repo [deterministic script]
        │ snapshot
        ▼
plan_checks [SDK Agent + filesystem/bash]
        │ checks[]
        ▼ fan_out
 audit#0 … audit#N [parallel SDK Agents]
        │ findings[]
        ▼
score_risk [deterministic policy]
        │
        ▼
report [subflow]
  compose → critique → revise ↺
        │
        ▼
     $output

It combines:

  • local Git inspection with a deterministic script;
  • in-process SDK Agents using filesystem and bash tools;
  • dynamic fan-out over Agent-planned review dimensions;
  • deterministic release scoring (ready / review / blocked);
  • a path-referenced report subflow with compose/critique/revise and a bounded loop;
  • typed schemas, structured Agent output, frontier-batch checkpoints, and a weekly systemd timer declaration.
uv run xdog-flow validate packages/flow/examples/release_readiness.json
uv run xdog-flow graph packages/flow/examples/release_readiness.json --mermaid
uv run xdog-flow generate packages/flow/examples/release_readiness.json -o release_readiness.py
uv run xdog-flow scheduling install packages/flow/examples/release_readiness.json --dry-run

The workflow defaults to /data/workspaces/pyspace/x-dog, but repo and base_ref are ordinary $in values and can be overridden per run.

Its test suite

release_readiness.test.json sits beside it and covers the graph without calling a model. Agent turns are stubbed by output port, the report subflow is stubbed whole — it has its own release_report.test.json — and score_risk runs for real, because the risk policy is exactly what the case is asserting.

{
  "cases": [
    {
      "name": "critical finding blocks the release",
      "agents": {
        "audit": [
          {"when": {"check": {"name": "security"}}, "then": {"finding": {"severity": "critical"}}},
          {"then": {"finding": {"severity": "low"}}}
        ]
      },
      "expect": {
        "output": {"risk": {"status": "blocked", "release_allowed": false}},
        "calls": {"audit": 3, "revise": 0}
      }
    }
  ]
}
uv run xdog-flow test packages/flow/examples/ --allow-script-stub

release_report.test.json pins the review loop from the other side: one case scores below the gate then above it, another passes on the first read so revise never runs, and a third never satisfies the reviewer so the loop stops at its loop.max bound. Writing that third case is what surfaced a real bug in the example — an unconditional compose → revise edge that let the quality gate be bypassed.

Depins Enrichment (an Agent with commit access)

depins_enrich/ is the one example that is not a teaching device. It runs on a small server every four hours, points a coding Agent at a live Flask site, and lets it commit and push its own work — but only if a chain of deterministic checks admits it.

precheck ─(refused)──────────────────────────► skipped ──► $output
    │
    └─(proceed)─► build ─► scope ─► guards ─► gate ─► validate ─► decide
                                               ▲                    │
                                               │                    ├─(approved)──► commit
                                               │                    │
                                               │                    ├─(unfixable)─► revert
                                               │                    │
                                               └───── fix ◄─────────┘
                                             while note != "", max 3

Three Agents (build, validate, fix) and eight script nodes. Everything between build and commit is deterministic code whose job is to not believe the Agent: guards imports the live registries out of the repository the Agent just edited and diffs them against a ledger, so a no-op cycle, a runaway cycle and a duplicate are all set-differences rather than heuristics; gate runs ruff against a pre-captured baseline, then pybabel, then a sweep of every route the app exposes.

Four things it is worth reading the JSON for:

  • precheck is both the gate and the input hydrator. Every downstream node's inputs flow out of it, so a refusal leaves nothing with an enabled incoming edge and the chain is skipped structurally — no if proceed: anywhere.
  • A node never raises to mean "stop the cycle." It returns a verdict and the edges decide. A raise means something is actually broken.
  • decide is a node, not conditions scattered on the write edges. That gives commit and revert exactly one gated predecessor each. The version without it had commit reachable while approved was false.
  • The repair back-edge is a while, not a loop. A fixer that has not converged in three attempts has left a broken tree; the run fails rather than stopping quietly on it.

It is also the only example whose script nodes are run: references to sibling modules — which is why it is a directory, and why it found three bundling and codegen defects that every inline-code example had hidden. See Letting an Agent Commit for that story.

Its six-case suite covers every terminal state and needs no repository, virtualenv or network:

uv run xdog-flow test packages/flow/examples/depins_enrich/ --allow-script-stub

Other shipped patterns

  • trip_planner.json — structured Agent outputs and JSONPath sub-field mappings.
  • cli_triage.json — Claude Code CLI backend plus deterministic routing.
  • digest_timer.json — cron-based timer scheduling.
  • triage_hook.json — HTTP hook delivery into a human signal.

Run them

# Offline dry-run — no LLM calls, exercises the wiring
uv run xdog-flow run packages/flow/examples/agent_calculator.json --dry-run --input a=12 --input b=30

# Render the diagram
uv run xdog-flow graph packages/flow/examples/refine_loop.json

Or open HaveFun to run a supported example in the browser.