Hermes Kanban: The Idempotent Nightly Review
A task that files itself onto the board every night and never double-books.
Run this workflow
CI-verified, 4/4 fixtures passing.
Intended Use
Anyone who wants a recurring Hermes task triggered from system cron or a webhook, where a dated idempotency key guarantees repeat triggers never create duplicate cards.
Not for
- One-off tasks (no need for an idempotency key)
- Schedules you'd rather manage inside another orchestrator
The Stack
Tested Against
hermes@0.15node@20.xSide effects & data flow
- Network
- your LLM provider, only in the non-CI worker step
- Writes
- ~/.hermes/kanban.db (the board)
- Credentials
- LLM provider key (hermes setup), for the review step only
Data privacy
- your LLM provider, only in the non-CI worker step ← the notes/state the review reads (retention: per that provider's API policy)
Prerequisites
- Hermes Agent (MIT): `curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash`
- `hermes setup` (LLM provider — only to run the review itself)
- cron (or any nightly trigger) calling the create command
- Node 20+ (used here to read the --json board state)
Steps
- 1
Create with a dated idempotency key, twice
The trick that makes a cron/webhook trigger safe: call create with `--idempotency-key "nightly-ops-$(date -u +%F)"`. CI calls it twice with the same key and asserts the second call returns the SAME task id (no duplicate) — an un-fakeable property of the board.
hermes kanban init >/dev/null mkid() { node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>process.stdout.write(JSON.parse(s).id))'; } KEY="nightly-ops-$(date -u +%F)" echo "idempotency key: $KEY" ID1=$(hermes kanban create "Nightly ops review" --assignee ops --idempotency-key "$KEY" --max-runtime 30m --json | mkid) ID2=$(hermes kanban create "Nightly ops review" --assignee ops --idempotency-key "$KEY" --max-runtime 30m --json | mkid) if [ -n "$ID1" ] && [ "$ID1" = "$ID2" ]; then echo "idempotent OK: repeat returned same id $ID1"; else echo "DUPLICATE: $ID1 vs $ID2"; exit 1; fi hermes kanban list --json | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{const o=JSON.parse(s);const t=Array.isArray(o)?o:(o.tasks||o.items||[]);console.log("cards titled Nightly ops review: "+t.filter(x=>x.title==="Nightly ops review").length)})' - 2
Schedule it (cron) and run the review (worker step, not CI)
Add a line like `0 3 * * * hermes kanban create "Nightly ops review" --assignee ops --idempotency-key "nightly-ops-$(date -u +%F)" --max-runtime 30m` to crontab. The dated key makes re-triggers safe; `--max-runtime` caps a stuck worker. The review itself runs a model, so CI doesn't run it.
Eval, 4 fixtures
Last passed: verified 11d agokey-formatregextimeout 60s · max $0Expected:
nightly-ops-[0-9]{4}-[0-9]{2}-[0-9]{2}idempotentcontainstimeout 60s · max $0Expected:
idempotent OK: repeat returned same idno-duplicatecontainstimeout 60s · max $0Expected:
cards titled Nightly ops review: 1clean-exitexit_codetimeout 60s · max $0Expected:
0
Results
The 'set it and forget it' pick from the WebAfterAI guide.
Liked this workflow?
Get new verified workflows in WebAfterAI, three issues a week (Tue, Thu, Sat).