Declarative multi-stage workflow primitive over the Hermes Kanban board.
Project description
hermes-workflow
A declarative, versioned, multi-stage workflow primitive over the Hermes Kanban board.
A *.workflow.yaml template — params, abstract roles bound to lanes, stages with
needs, a single-level expand fan-out plus an expand_out shape gate, a human
gate, and workspaces — is instantiated into a Kanban card-graph that Hermes'
existing dispatcher and worker lanes execute. It turns "hand-wire an orchestrator
from scratch every run" into a repeatable, durable, inspectable run on the board
you already use.
What it is
A template compiles to a linked card-graph. Materialization is lazy and single-level:
workflow_startvalidates the template + bindings, runs a per-profile pre-flight, and creates the dynamic-free prefix (the static stages up to the first fan-out) plus a write-once compiled-snapshot blackboard root.- The
post_tool_callfan-out hook fires as stages complete: when a source stage finishes, it creates that fan-out's children and its join in one atomic create, wiring the join as a child of every instance.
Completion-gating is deterministic and injection-free, enforced by a
pre_tool_call veto: it checks the expand_out shape + max, and commit-clean
for worktree stages, before a stage may complete. There is no LLM in the gate.
All state lives on the board — body sentinels, links, and statuses — and the run
root is a write-once compiled-snapshot blackboard. Nothing touches raw SQLite —
every mutation goes through Hermes' board APIs (kanban_* from workers, kb.*
from the host).
Requirements
- Hermes Agent v0.15.x
- Python ≥ 3.11
- For any role with
lane: codex: thecodexbinary onPATH, and Hermes' bundledkanban-codex-laneskill present in that role's bound profile. This plugin reuses that skill — it does not re-ship it.
Quick Install
The intended primary path is PyPI:
pip install hermes-workflow
From source:
git clone https://github.com/carlosraphael/hermes-workflow
cd hermes-workflow
pip install -e .
Then enable it in EVERY bound profile — not just the orchestrator's. This is
a pip / entry-point plugin, so hermes plugins enable does not apply to it
(that command only sees user-dir and bundled plugins). Instead add
hermes-workflow to the plugins.enabled list in each bound profile's
config.yaml — open it with hermes -p <profile> config edit (or edit
<that profile's HERMES_HOME>/config.yaml directly) and add:
plugins:
enabled:
- hermes-workflow
The change takes effect on the next session. (Do not use
hermes config set plugins.enabled … — it writes a scalar string, which breaks
the loader's list check.)
Per-profile enablement is the #1 failure mode. Workers read the plugin's
load status from the assignee profile's home, so the plugin must be enabled
and loadable in every profile a role binds to. workflow_start runs a
per-profile loadability pre-flight and fails fast — creating zero cards —
with a per-profile remediation map if any bound profile cannot load it (or a
codex role is missing its codex binary / kanban-codex-lane skill).
Quickstart
Using examples/build-hermes-plugin.workflow.yaml — a workflow that dogfoods
this repo, extending hermes-workflow with new workflow_* surfaces. Both
invocation surfaces — the slash command and the CLI — take the same arguments.
(examples/feature-delivery.workflow.yaml is a second, generic feature-delivery
SDLC you can run against any repo.)
In-session slash command:
/workflow start --template examples/build-hermes-plugin.workflow.yaml \
--params '{"repo":"/abs/path/to/hermes-workflow","capability":"a workflow_pause/workflow_resume tool pair"}' \
--bindings '{"architect":"designer","builder":"coder","tester":"designer","reporter":"writer"}'
CLI:
hermes workflow start --template examples/build-hermes-plugin.workflow.yaml \
--params '{"repo":"/abs/path/to/hermes-workflow","capability":"a workflow_pause/workflow_resume tool pair"}' \
--bindings '{"architect":"designer","builder":"coder","tester":"designer","reporter":"writer"}'
Run lifecycle
- The
specworker (rolearchitect) decomposes thecapabilityand returnsmetadata.surfaces = [{name, kind, summary}, …]. - The fan-out hook creates one
implementcard per surface — each on its own pre-provisioned worktree, gated by commit-clean — and wires theintegratejoin as a child of all of them. integrate(rolearchitect) merges the per-surface branches;test(roletester) then runs the suite.- The
reviewhuman gate promotes toready. The operator runshermes workflow approve <gate_card>— find it underawaiting_approvalviahermes workflow status <root_id>. report(rolereporter) then runs, summarizing the added surfaces and the branches from the handoffs.
Commands
Both surfaces — the CLI (hermes workflow <cmd>) and the slash command
(/workflow <cmd>) — dispatch the same tools (workflow_start … workflow_abandon).
| Command | Form | What it does |
|---|---|---|
start |
--template <path> --params <json> --bindings <json> [--board] |
Validate, pre-flight every bound profile, then seed the run (root blackboard + dynamic-free prefix). Fails closed with zero cards if any profile can't load. |
status |
<root_id> [--board] |
Read-only run summary: per-stage rollup plus blocked_stages, awaiting_approval (the gate signal), and review_required. |
validate |
--template <path> |
Deterministic, read-only template check. Rejects verify/retry and nested-expand. |
reconcile |
<root_id> [--board] |
Re-drive a partial fan-out: create missing children, re-link to the join, progress-aware dedup, and surface review-required stalls. |
approve |
<gate_card> [--board] |
Complete a human gate card so its downstream stages promote natively. |
abandon |
<root_id> [--board] |
Hazard-free teardown: reclaim running workers, then archive the run reverse-topologically (leaves-first). Worktrees are preserved. |
The four mutating commands (start, reconcile, approve, abandon) refuse to
run inside a dispatcher-spawned worker — they are orchestrator-context only.
Bundled skills
Two skills are auto-registered on plugin load:
workflow-author— how to write a*.workflow.yamltemplate within the 0.1.0 constraints; validate it withworkflow_validate.workflow-orchestrator— start / status / approve / abandon / reconcile, plus the review-required backstop for recovering a stalled stage.
0.1.0 scope
Lanes are {profile, codex} only — claude-code is deferred to 0.2.x.
verify.command / retry and granular reject / modify are deferred to
0.2.x. Nested fan-out (an expand stage that is itself an expand source) is
forbidden in 0.1.0.
Documentation
| Document | What it covers |
|---|---|
AGENTS.md |
Development guide for AI coding assistants and contributors. |
CONTRIBUTING.md |
Development setup, PR process, and code style. |
docs/operations.md |
Upgrade / version-gate procedure and operational caveats. |
CONTEXT.md |
The naming taxonomy (distribution / import / plugin / runtime layers). |
docs/adr/ |
Architecture decision records. |
Contributing
Contributions are welcome — see CONTRIBUTING.md for the
development setup, PR process, and code style.
License
MIT — Copyright (c) 2026 Carlos Raphael. See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hermes_workflow-0.1.4.tar.gz.
File metadata
- Download URL: hermes_workflow-0.1.4.tar.gz
- Upload date:
- Size: 41.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c3955bcf5ca7f907eb5fdce9b91e974846c10cdad7cd9f1f708737808a27a14a
|
|
| MD5 |
83b3503035873f59c5f369f90b974ec9
|
|
| BLAKE2b-256 |
f25443814e8ed7ea5aea83ff8694a6dd55fe77b3af1f2b4e0ea37bb55f2303e1
|
Provenance
The following attestation bundles were made for hermes_workflow-0.1.4.tar.gz:
Publisher:
release.yml on carlosraphael/hermes-workflow
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hermes_workflow-0.1.4.tar.gz -
Subject digest:
c3955bcf5ca7f907eb5fdce9b91e974846c10cdad7cd9f1f708737808a27a14a - Sigstore transparency entry: 1732275557
- Sigstore integration time:
-
Permalink:
carlosraphael/hermes-workflow@5c5914bee2bd515c72517e3ef4454e88430086b3 -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/carlosraphael
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5c5914bee2bd515c72517e3ef4454e88430086b3 -
Trigger Event:
push
-
Statement type:
File details
Details for the file hermes_workflow-0.1.4-py3-none-any.whl.
File metadata
- Download URL: hermes_workflow-0.1.4-py3-none-any.whl
- Upload date:
- Size: 45.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
99ed225ae7c356410933a730f59d6042e5c79b39ed9f4c08642af5e47ce66ccb
|
|
| MD5 |
0ebb1d8b780bcc2e16fefa240bf869d9
|
|
| BLAKE2b-256 |
a4e54982fa43e1b52a44a03b3a704ef77dedaa3c09d3f13207f3c382abb01b16
|
Provenance
The following attestation bundles were made for hermes_workflow-0.1.4-py3-none-any.whl:
Publisher:
release.yml on carlosraphael/hermes-workflow
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hermes_workflow-0.1.4-py3-none-any.whl -
Subject digest:
99ed225ae7c356410933a730f59d6042e5c79b39ed9f4c08642af5e47ce66ccb - Sigstore transparency entry: 1732275645
- Sigstore integration time:
-
Permalink:
carlosraphael/hermes-workflow@5c5914bee2bd515c72517e3ef4454e88430086b3 -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/carlosraphael
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5c5914bee2bd515c72517e3ef4454e88430086b3 -
Trigger Event:
push
-
Statement type: