# Homerail Dag Patterns

> Select, inspect, instantiate, adapt, and validate HomeRail's built-in DAG design patterns. Use when an agent needs to design a reusable workflow for periodic triage, read-only issue diagnosis, planner/worker fan-out, on-demand executor/advisor consultation, budget admission, graduated trust, standing-goal verification, quorum decisions, adversarial builder/breaker review, monotonic improvement, or evidence-driven process evolution. Also use when deciding whether a workflow needs condition, loop, join, or while gateway semantics. Patterns describe control-flow invariants; for stable live Actor panels, Surface updates, or follow-up commands, use homerail-dag-ops and a concrete presentation-aware Workflow.

- Skill: `xiaotianfotos/homerail-dag-patterns` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add xiaotianfotos/homerail-dag-patterns`
- Raw SKILL.md: https://api.skillmd.com/api/skills/xiaotianfotos/homerail-dag-patterns/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: xiaotianfotos (https://skillmd.com/u/xiaotianfotos)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/xiaotianfotos/homerail-dag-patterns

---


# HomeRail DAG Patterns

Treat a pattern as an abstract control-flow invariant, not a finished task
template. Read the live Manager catalog before choosing one; it is the source of
truth for parameters and generated topology.

## Manager Agent Native Path

When running as the HomeRail Manager Agent, dedicated Manager Tools are the
shortest path for the operations below. The harness-native shell and `hr --json`
remain valid when they expose a needed command that has no dedicated Tool:

1. Call `list_dag_patterns` and compare `typical_uses`, `avoid_when`, required
   primitives, and parameters.
2. Call `get_dag_pattern` for the best candidate before changing Manager state.
3. Call `instantiate_dag_pattern` with a stable `workflow_id`, task-specific
   name, and typed parameters. Keep its default `sync=true` only after the
   selection is justified.
4. Call `create_and_run` with the returned `workflow_id`, an available runtime
   profile when needed, and a prompt containing task inputs and boundaries.
5. Use `get_run_status` for progress. Never claim the DAG started without the
   real run id returned by `create_and_run`.
6. Use `list_dag_approvals` to find durable human-decision nodes. Never call
   the approval decision API yourself; present the proposal hash to the human.
7. Use `list_dag_triggers` and `fire_dag_event` for Manager-owned schedules and
   idempotent event delivery. Always supply a stable idempotency key.
8. Use `get_dag_state` and `set_dag_state` for versioned trust, budget, and goal
   ledgers. Preserve compare-and-set versions instead of overwriting blindly.

When adapting a pattern or authoring a custom workflow instead of using the
generated instance unchanged:

1. Call `get_dag_schema`; do not rely on a remembered WorkflowSpec shape.
2. Emit `api_version: homerail.ai/v1` with explicit top-level edges and terminal
   nodes.
3. Call `validate_dag_workflow` and repair every structured diagnostic.
4. Call `sync_dag_workflow` only after validation returns `valid: true`.
5. Use the returned workflow revision and canonical hash as provenance.

For a simple one-step or linear task, do not force a pattern. Use an existing
concrete orchestration or ask for the missing execution boundary.

## Patterns do not imply presentation

A pattern instance defines topology and evidence flow. It does not gain a
Canvas Surface merely because its roles are called Actors or Workers.
`orchestrator-workers` in particular creates data-driven fan-out children with
no declared Skill, `allowed_surface_views`, `report_surface_state`, or
`await_command`. Use it for bounded parallel work whose results are aggregated.

When the request includes multiple live cards, parallel panels, continuous UI,
per-panel correction, or later follow-up, load `homerail-dag-ops` and select a
concrete Workflow that declares those presentation and lifecycle contracts.
Never promise that a generic pattern will update visible panels.

Inspecting results is the opposite case: it needs no declared presentation
contract at all. Every non-worker node (command, join, condition, and other
gateways) already has a structured, human-readable result at
`GET /api/dag-status/<run_id>/node/<node_id>/result`, and the node drawer plus
the Voice Cockpit `dag_explorer` widget render it by default. Do not author a
custom Workflow or generative UI just to make pattern results visible.

## Select a Pattern

```bash
hr doctor
hr --json patterns list
hr --json patterns show <pattern-id>
```

Choose from constraints, not keyword similarity:

- `heartbeat`: periodic work needs a cheap quiet exit, one selected action, and
  an independent verdict.
- `issue-diagnosis`: an untrusted issue snapshot must be checked against one
  explicit repository revision by independent reproduction, data-flow, and
  history reviewers, then arbitrated and unanimously verified without platform
  write-back.
- `orchestrator-workers`: one planner can split independent work that must
  aggregate before verification.
- `executor-advisor`: an executor should retain context and call a separately
  bound stronger model only at concrete ambiguity boundaries.
- `budget-gate`: measured usage must admit or stop work before execution.
- `trust-ledger`: autonomy varies per recurring skill based on measured history.
- `standing-goal-sentinel`: previously satisfied goals must be re-verified as
  standing invariants.
- `quorum`: expensive or risky action requires independent n-of-m agreement.
- `sparring`: a breaker, builder, and fresh verifier must remain separate.
- `ratchet`: one metric should improve through bounded attempts until a target.
- `compost`: repeated failures should produce a bounded set of proposals that
  remain behind human review.

Do not choose a pattern when the catalog's `avoid_when` conditions apply. A
small linear DAG is better than a pattern whose invariant is unnecessary.

## Instantiate and Adapt

Generate YAML without syncing it first:

```bash
hr patterns instantiate quorum \
  --set workflow_id=release-decision \
  --set threshold=2 \
  --output /tmp/release-decision.yaml
```

Adapt role names, prompts, evidence fields, and terminal actions to the task.
Preserve the invariant that made the pattern useful:

- Keep voters independent in `quorum`.
- Keep planner, workers, and verifier distinct in `orchestrator-workers`.
- Keep advisor calls bounded and executor-owned in `executor-advisor`.
- Keep breaker, builder, and verifier distinct in `sparring`.
- Keep `ratchet` bounded and metric-driven.
- Keep policy changes behind review in `compost`.
- Keep the quiet path cheaper than the action path in `heartbeat`.
- Keep `issue-diagnosis` revision-pinned, credential-free, remote-read-only, and
  independent from issue-tracker triggers or comment permissions. Preserve its
  three investigation roles, explicit arbiter, and scenario/evidence/adversarial
  3-of-3 verification policy. Only the reproduction role may modify a private
  `scratch/reproduction/source` copy for focused tests; the shared prepared
  source stays read-only. Treat issue comments that clarify state, ordering,
  provider, and credential reuse as part of the immutable snapshot. Consume the
  fixed `diagnosis.json` and `verification.json` outputs through generic `hr dag
  artifacts <run-id>` / `hr dag artifact <run-id> <name>` commands.

Do not put provider, model, API key, or base URL fields in generated workflow
YAML. Bind models through HomeRail database settings and runtime profiles.

Pattern instances are strict WorkflowSpec v1 documents. Keep the
`api_version`/`kind`/`metadata`/`spec` envelope, named port contracts, top-level
`spec.edges`, and explicit terminal outcomes when adapting them.

## Compose Patterns

Compose only at explicit boundaries. Common combinations:

- Put `budget-gate` or `quorum` before an expensive `orchestrator-workers`
  subgraph.
- Put `trust-ledger` after independent verification, not before execution alone.
- Run `standing-goal-sentinel` as a heartbeat action, but keep detection and
  repair as separate runs.
- Feed failed runs and violated goals into `compost`; never let Compost apply
  its own policy proposals.

When combining patterns, retain one structured handoff contract at each
boundary. Avoid nested planners, duplicated verifiers, and loops without one
clear stop predicate.

## Use Gateway Semantics Correctly

- `condition`: route one structured value by field and exact case.
- `foreach`: iterate a finite item list and emit `done` after the last item;
  set `result_port` to include every ordered iteration result in the final payload.
- `join`: aggregate all arrived inputs using `all`, `any`, or `n_of_m`;
  configure `field`, `success_values`, and threshold explicitly.
- `while`: compare the latest feedback value, emit `continue` while
  unmatched, and emit `exhausted` after `max_iterations`.
- A `kind: feedback` edge must declare `max_traversals` independently of the
  run-wide edge limit.
- `terminal` declares `outcome: success | failure | cancelled` and never calls
  a model.
- `command` runs an allowlisted argument vector with explicit timeout and typed
  evidence; the default allowlist is empty, and dynamic commands additionally
  require `HOMERAIL_DAG_ALLOW_DYNAMIC_COMMANDS=true`.
- `approval` persists a proposal hash and waits for an authorized human actor.
  Declare a proposer actor distinct from every authorized approver. You may
  list pending approvals, but never decide one; direct the human to `hr dag
  decide` with the displayed proposal hash.
- `state` updates a namespaced versioned ledger transactionally.
- `budget_admit` atomically reserves the positive amount selected by
  `value_field`; treat that amount as a conservative upper bound.
- `fanout` creates bounded run-local workers with explicit parallelism and
  completion policy. Set `item_field` for per-worker work and `context_field`
  for immutable context shared by every worker and the aggregate verifier.
- Agent `advisors` and `workspace_access` are runtime-enforced capabilities,
  not prompt suggestions. Workspace access validates final changes inside the
  workspace; external filesystem containment depends on the backend sandbox.

Data edges imply completion dependencies. Use `depends_on` only for a
control-only barrier that carries no payload. Join nodes wait for all declared
inputs before aggregating. Feedback edges must return to a `foreach` or `while`
node, remain statically bounded, and have an explicit dependency on that loop
gateway.

## Validate Before Running

Inspect generated YAML, then sync and run it only when its task-specific prompts
and runtime profile are complete:

```bash
hr dag schema
hr --json dag validate /tmp/release-decision.yaml
hr dag sync /tmp/release-decision.yaml
hr profile sync <profile.yaml> --workflow release-decision
hr run --workflow release-decision --profile <profile-id> --prompt "<task>"
hr dag watch <run-id> --timeout 600
hr dag handoffs <run-id> --content-limit 0

# Durable governance and state operations
hr dag approvals
hr dag decide <run-id> <node-id> --decision approved --actor <actor> --proposal-hash <hash>
hr dag triggers
hr dag trigger-event <event> --idempotency-key <stable-key>
hr dag state-get <namespace> <key>
hr dag state-set <namespace> <key> '<json>' --expected-version <version>
```

For a non-loopback Manager, set `HOMERAIL_DAG_MUTATION_TOKEN` in both the
Manager and the authorized CLI or Manager Agent environment before syncing
workflows/profiles or invoking any DAG write operation, including run lifecycle,
events, state, injection, and dynamic graph changes. This token does not
authorize approval decisions.

Require all of the following before calling the adaptation useful:

- `hr patterns instantiate` reports a valid graph.
- The YAML contains pattern id, version, source, and resolved parameters.
- Every branch reaches an explicit terminal node, possibly through a bounded
  feedback edge.
- Sync returns the expected immutable revision and canonical hash.
- A deterministic or fake-dispatch test exercises the topology.
- A real model-backed run exercises task semantics before production use.
- Terminal status and non-empty handoffs support the claimed result.

