| name | dynamic-workflows |
| description | Use the hermes-dynamic-workflows plugin: workflow runs, script harnesses, controls, child agents, and Kanban waits. |
| version | 0.1.1 |
| author | Donovan Yohan + Hermes Agent |
| license | MIT |
| metadata | {"hermes":{"tags":["hermes","workflows","orchestration","plugin","agents","kanban"],"category":"autonomous-ai-agents"}} |
Dynamic Workflows Plugin Skill
Use this when operating the hermes-dynamic-workflows plugin itself. It is not the generic fan-out pattern skill. It tells you how to call the plugin tools that ship with this repo.
Plugin-provided skills are explicit-load only. Load this one as:
skill_view(name="hermes-dynamic-workflows:dynamic-workflows")
When to Use
Use this skill when the user asks to:
- validate, run, inspect, pause, resume, stop, or retry a Dynamic Workflows run;
- author or run a workflow-script harness;
- use
agent(...), kanban_agent(...), parallel(...), pipeline(...), or capability(...) inside a workflow script;
- inspect blocked waits, approvals, finalizers, or child-agent state;
- debug the plugin installation or its workflow state stores.
Do not use this for small one-off tool sequences. Just call the normal tools.
Installed Surface
The plugin registers two model-facing tools in the dynamic_workflows toolset:
workflow — validate/run/status/catalog/script operations.
workflow_control — operator controls and blocked-wait/status inspection.
The plugin stores state under the active HERMES_HOME by default:
$HERMES_HOME/dynamic-workflows/runs/
$HERMES_HOME/dynamic-workflows/controls/
$HERMES_HOME/dynamic-workflows/script-runs/
$HERMES_HOME/dynamic-workflows/background-runs/
$HERMES_HOME/dynamic-workflows/scripts/
$HERMES_HOME/dynamic-workflows/templates/
Useful overrides:
HERMES_WORKFLOWS_STATE_DIR # run store root; sibling stores live beside it
HERMES_WORKFLOWS_SCRIPT_CATALOG_DIR # saved script harness catalog root
HERMES_WORKFLOWS_CATALOG_DIR # JSON workflow template catalog root
JSON Workflow Definitions
Fast path:
workflow(action="validate", definition={...})
workflow(action="run", definition={...}, inputs={...})
workflow(action="status", run_id="wf_...")
Minimal definition:
{
"version": "1",
"name": "hello",
"policy": {"network": false, "filesystem": false, "max_parallel": 2},
"inputs": {"name": "string"},
"steps": [
{
"kind": "agent",
"id": "greet",
"agent": "hermes.greeter",
"input": {"subject": "$ref:inputs.name"},
"output_schema": {"greeting": "string"}
}
]
}
Supported JSON step kinds in this release: agent, kanban_agent, if, parallel, pipeline, phase.
Always include an explicit policy block. Missing policy is treated as default-deny and strict validation reports it as an error/warning depending on call path.
Script Harnesses
Use scripts when the workflow needs loops, branching, fan-out, replay, or a reusable harness.
Operations:
workflow(action="script_catalog", include_versions=True)
workflow(action="script_save", script_name="name", script_source=source, replace=False)
workflow(action="script_inspect", script_name="name", script_version=1, include_source=True)
workflow(action="run_script", script_name="name", script_args={...})
Claude-style facade aliases also work in the current plugin schema:
workflow(script=source, args={...})
workflow(name="name", args={...})
workflow(scriptPath="name/v000001.workflow.py", args={...})
workflow(name="name", args={...}, resumeFromRunId="...")
Final script return values are compact by default. Small results stay inline;
if the compact JSON result exceeds result_preview_bytes (default 4096 bytes),
workflow(...), workflow(action="status"), and workflow_control(status) return
a __workflow_result_spill__ preview envelope plus spill.path / result_path.
Read the full JSON only on demand from:
$HERMES_HOME/dynamic-workflows/script-runs/<run_id>/tasks/<run_id>.output
Set result_preview_bytes=<positive int> on script run calls when a different
preview cap is needed. The artifact is written before the run snapshot points to
it; missing artifact means storage is corrupt, not "no result".
Script globals available inside .workflow.py harnesses:
args
budget
meta
agent
kanban_agent
agent_start
agent_check
agent_cancel
agent_list
capability
workflow
log
phase
parallel
pipeline
json, math
Example script source:
meta = {"name": "triage", "description": "fan out reviews", "phases": ["Plan", "Review", "Synthesize"]}
phase("Review")
items = args.get("items", [])
async def review(item):
return await agent(
"review this item",
{"item": item},
{"schema": {"ok": "boolean", "notes": "string"}},
)
results = await parallel([lambda item=item: review(item) for item in items])
return {"results": results}
Child-Agent Backends
Prompt-agent effort accepts only low, medium, high, xhigh, or max; invalid values fail closed before dispatch.
By default, prompt agents use the plugin's local/stub runner unless the host injects another runner.
For live Hermes delegate_task integration from the plugin tool surface:
workflow(
action="run_script",
script_name="triage",
script_args={...},
child_agent_backend="delegate_task"
)
Backend choices:
delegate_task — foreground structured child result. Use when the script must wait for the child output.
delegate_task_background — returns a redacted dispatch-handle envelope. Use only when the workflow expects async handoff semantics.
Do not pretend delegate_task_background handles are durable workflow state by themselves. The workflow store is durable; the underlying child backend still has its own lifecycle limits.
Async lifecycle handles
agent_start(...) / agent_check(...) / agent_cancel(...) / agent_list() are the script-native async child-agent lifecycle. In foreground script runs with a durable store, unresolved agent_start handles suspend the run as AsyncAgentSuspended; workflow_control(action="status", ...) surfaces them as async_agent waits, and workflow(..., resumeFromRunId="...") reattaches to the same host token instead of dispatching duplicate children. Terminal agent_check/agent_cancel states are sticky and replayable from cache.
Kanban Backend
For real Hermes Kanban cards from kanban_agent(...), use the foreground script path with:
workflow(
action="run_script",
script_name="release_lane",
script_args={"board": "project-board", "repo": "owner/repo"},
kanban_backend="hermes",
kanban_suspend_after_s=30
)
The script must pass that board into every real card, for example:
await kanban_agent("planner", title="plan", prompt="...", board=args["board"], on_block="pause")
Rules:
kanban_backend="hermes" is valid only for foreground script runs.
- It is not supported with local background script execution.
- Real Hermes Kanban runs fail closed if
kanban_agent(...) omits board or passes an empty board; do not rely on the profile-global active board.
kanban_suspend_after_s should be set for real cards so the run suspends instead of burning runtime while workers execute.
- Suspended runs expose the explicit board, logical
kbc_* waits, and real Hermes Kanban t_* task ids in workflow_control(action="status", ...).
workflow_control(action="kanban_bridge_drain") drains terminal Hermes Kanban task events (completed, blocked, failed, timed_out, crashed, gave_up), maps real t_* ids back to logical kbc_* cards, publishes the durable workflow event, and auto-resumes suspended script runs when a resume manifest exists.
workflow_control(action="kanban_publish", ...) remains the manual repair path when an adapter cannot drain the real Kanban event stream.
- Manual resume still uses
workflow(..., resumeFromRunId="previous_run_id"); bridge auto-resume uses the same replay contract and must match the same script identity/fingerprint.
Gateway-origin breadcrumbs
Foreground script runs launched from a gateway thread can persist their origin and send compact progress breadcrumbs:
workflow(
script=source,
args={...},
kanban_backend="hermes",
kanban_suspend_after_s=30,
gateway_notify=True,
gateway_notify_target="discord:chan:thread"
)
Breadcrumbs are visibility only: run state, Kanban state, and workflow journals remain authoritative. The plugin suppresses unchanged healthy waits with a fingerprint and sends only compact start/wait/resume/terminal status.
Operator Control
Use workflow_control for run inspection and operator decisions:
workflow_control(action="overview")
workflow_control(action="status", run_id="wf_...")
workflow_control(action="pause", run_id="wf_...", reason="operator requested")
workflow_control(action="resume", run_id="wf_...")
workflow_control(action="stop", run_id="wf_...")
workflow_control(action="task_stop", run_id="wf_...", target_ref="call_...")
workflow_control(action="retry", run_id="wf_...", target_ref="call_...")
workflow_control(action="decide_call", run_id="wf_...", target_ref="call_...", decision="approve")
workflow_control(action="kanban_bridge_drain", limit=200, auto_resume=True)
Approval decisions:
approve — run pending call as-is.
edit — run with operator-supplied input.
reject — deterministic denial, catchable/non-retryable.
respond — return operator-supplied value without running the call.
Verification
Before saying a workflow is done:
- Validate first with
workflow(action="validate", ...) or script validator/catalog status.
- Run a scoped smoke before full fan-out.
- Check
workflow_control(action="status", run_id=...) for lifecycle, waits, phases, child refs, and pending approvals.
- Inspect
include_journal=True only when needed; keep output compact.
- Confirm cleanup/finalizers ran or explicitly report live resources with owner/TTL.
- For repo changes, run targeted tests and
git diff --check before handoff.
Pitfalls
- Plugin skills are not in the flat
<available_skills> index. Use the qualified name.
workflow(action="validate") with strict mode can reject missing policy; that is intended. Add the policy.
scriptPath is catalog-relative and must point to .workflow or .workflow.py.
resumeFromRunId must match the same script identity/fingerprint. Identity mismatch fails closed.
- Unknown capability names fail closed. Side effects must cross the parent-owned capability registry/policy.
- Do not pass secrets through script args or capability inputs. Results and waits are redacted/bounded, but scripts are not a secret vault.
- Do not run huge fan-out without a scoped dry run and cost/limit check.