Run a workflow template from a Claude Code session via the local control plane. Handles topological wave execution, artifact passing, sentinel resolution, and human review gates locally — no CP-side workflow expansion required. The pre-gathered "Available workflows" context uses python3 (not a ls|sed pipe) so the Bash permission checker accepts it without needing sed in allowed-tools — piped commands fail the check even when both sides match an allowed pattern individually. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
7.0 KiB
name, description, user_invocable, allowed-tools
| name | description | user_invocable | allowed-tools |
|---|---|---|---|
| manual-workflow | Run a workflow template from a Claude Code session using the control plane for task execution. Handles artifact passing, sentinel resolution, and human review gates locally. Usage: /manual-workflow <template-name> [param=value ...] | true | Read, Glob, Grep, Bash(curl *), Bash(python3 *), Bash(sleep *), Bash(date *), Bash(cat *), Bash(ls *), Bash(kill *), Bash(kubectl port-forward *), AskUserQuestion, Write, Edit |
/manual-workflow Skill
manual-workflow
Run a workflow template through the control plane, managing artifact passing and human review gates from this Claude session.
Arguments
$ARGUMENTS — Template name followed by optional key=value params.
Examples:
/manual-workflow spec-planning— interactive param prompting/manual-workflow spec-planning project_id=agent-runtimes task_description="Design artifact passing"
Pre-gathered context
Available workflows
!python3 -c "import glob,os; [print(os.path.basename(p).removesuffix('.yaml')) for p in sorted(glob.glob(os.path.expanduser('~/dev/claude/projects/agent-runtimes/workflows/*.yaml')))]"
Control plane access
!curl -s --connect-timeout 2 http://localhost:8100/health 2>/dev/null || echo "CP_NOT_AVAILABLE"
Instructions
Step 0: Parse arguments and validate
Parse $ARGUMENTS to extract the template name (first word) and any key=value params.
If no template name provided, list available workflows and ask the user to pick one.
Step 1: Load and validate template
Read the workflow YAML from ~/dev/claude/projects/agent-runtimes/workflows/<name>.yaml.
Parse it to extract: params, nodes, node depends_on, and model_override fields.
Display a summary:
Workflow: <name> v<version>
Description: <description>
Nodes: <count> (<node_ids>)
DAG: <visual showing phases>
Step 2: Resolve parameters
For each required param not provided via arguments, ask the user with AskUserQuestion.
For each optional param, show the default and ask if they want to override.
For model_a / model_b: if not provided and the user doesn't override, set sensible defaults:
model_a= the harness context that runs via MiniMax (useminimax/v1harness)model_b= the default Claude model (useanthropic-cloud/v1harness)
Or let the user specify model names and you'll map them to harnesses.
Step 3: Ensure CP access
Check if http://localhost:8100/health responds. If not:
kubectl port-forward -n agent-runtimes svc/controlplane 8100:8100 &
Wait for health check to pass.
Step 4: Execute in topological waves
Process nodes in dependency order. Nodes with no deps (or all deps satisfied) form a "wave" and run in parallel.
For each wave:
-
Resolve sentinels in each node's prompt: replace
<<ARTIFACT:node_id:key>>with the collected output from that node. Wrap injected content in[BEGIN ARTIFACT: node_id:key]/[END ARTIFACT: node_id:key]markers. -
Render Jinja2 — replace
{{ param }}references with resolved param values. For Jinja2 conditionals ({% if %},{% for %}), render them with the params dict. Use Python:from jinja2.sandbox import SandboxedEnvironment env = SandboxedEnvironment() rendered = env.from_string(prompt).render(**params) -
Determine harness for each node:
- If
model_overrideresolves to a value containing "model_a" and model_a is minimax → useminimax/v1 - If
model_overrideresolves to a value containing "model_b" or is empty → useanthropic-cloud/v1 - The harness controls which provider's auth the agent gets
- If
-
Submit tasks to the CP via:
curl -s -X POST http://localhost:8100/tasks \ -H "Content-Type: application/json" \ -d '{"name": "<node_name>", "project_id": "<project_id>", "prompt": "<rendered_prompt>", "harness": "<harness>", "runtime": {"cli": "claude", "model": "<model_if_applicable>", "timeout": 3600}}' -
Monitor tasks — poll every 30s:
curl -s http://localhost:8100/tasks/<task_id>Display progress updates to the user: which nodes are running, which completed, duration.
-
Collect outputs — when a task succeeds, extract the assistant's output from the task logs:
# Parse NDJSON logs, find assistant message content for line in logs.split('\n'): entry = json.loads(line) if entry.get('type') == 'assistant': content = entry['message']['content'] for block in content: if block['type'] == 'text': result += block['text']Store the output as
artifacts[node_id]['output']for sentinel resolution in downstream nodes. -
Handle failures — if a task fails:
- Show the error and logs to the user
- Ask: "Retry this node, skip it, or abort the workflow?"
- On retry: resubmit with the same prompt
- On skip: mark the artifact as
[NODE FAILED — no output available] - On abort: stop the workflow
Step 5: Human review gate
When the escalate node completes (or any node whose name contains "human" or "escalat"):
- Display the full escalation output to the user
- Ask for decisions on each "Decision needed: YES" item using
AskUserQuestion - Append the human decisions to the escalation artifact:
## Human Decisions (from manual review) ### Decision 1: [topic] **Choice:** [user's answer] **Rationale:** [user's explanation if provided] ### Decision 2: [topic] ... - The updated artifact (original + human decisions) is then used for sentinel resolution in the
synthesizenode.
Step 6: Final output
When the synthesize node completes:
- Display a summary: total nodes, succeeded/failed, wall-clock time per phase
- Write the final spec output to a file in the project:
- Ask the user where to save it (suggest
spec/<name>.md) - Write the file
- Ask the user where to save it (suggest
- Show the file path and suggest next steps: "Review the spec, then commit when ready."
Error handling
- If the CP goes offline mid-workflow, pause and tell the user to fix it
- If a node times out (>3600s), treat as failure
- If ALL nodes in a wave fail, ask the user before continuing
- Never leave orphan tasks running — cancel them on abort
Progress display
Keep the user informed with a compact status line after each check:
[Phase 2] spec_review_a: running (2m) | spec_review_b: running (1m45s) | security_review_a: succeeded (3m) | ...
Important notes
- This skill runs the workflow LOCALLY from your Claude session — it does NOT use the CP's workflow expansion (Phase 2 artifact passing isn't implemented yet)
- Artifacts are passed by embedding the full text in downstream prompts — this works but means large artifacts consume context
- The harness mapping (model name → harness context) is specific to the agent-runtimes project's current provider setup
- Monitor the agent-monitor in another terminal for richer progress:
scripts/agent-monitor --filter "project=<project_id>" --filter "age<30m"