enhance hcom-agent-messaging skill + add hcom-workflow-scripts skill#17
enhance hcom-agent-messaging skill + add hcom-workflow-scripts skill#17aannoo merged 2 commits intoaannoo:mainfrom
Conversation
enhanced the existing hcom-agent-messaging skill with: - tested command reference with real timing data - per-tool delivery details (claude <1s, codex 1-3s) - scripting patterns section with working examples - 4 reference docs (patterns, cli-reference, cross-tool, gotchas) - intent system documentation - codex session binding gotchas added new hcom-workflow-scripts skill for building multi-agent workflows: - 6 tested scripts (basic messaging, review loop, cross-tool duo, ensemble consensus, cascade pipeline, codex-worker) - all scripts tested with real claude + codex agents (6/6 passed) - architecture reference (db schema, hooks, delivery pipeline) - script template with annotated commentary - agent topology guide (worker-reviewer, pipeline, ensemble, hub-spoke, reactive) - cross-tool scripting guide (claude + codex quirks, timing data) - debugging reference (stale agents, message delivery, codex binding)
There was a problem hiding this comment.
Pull request overview
This PR expands the existing hcom-agent-messaging skill with more tested, tool-specific operational guidance and adds a new hcom-workflow-scripts skill focused on authoring and running multi-agent orchestration scripts (with references and runnable examples).
Changes:
- Enhanced
hcom-agent-messagingwith a quick-reference command section plus new deep-dive reference docs (CLI reference, patterns, cross-tool notes, gotchas). - Added new
hcom-workflow-scriptsskill with architecture/debugging/pattern references and a script template. - Added 6 runnable workflow script examples (basic messaging, review loop, ensemble consensus, cascade pipeline, cross-tool duo, codex worker).
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 18 comments.
Show a summary per file
| File | Description |
|---|---|
| skills/hcom-workflow-scripts/SKILL.md | New skill entrypoint and overview for workflow scripting patterns and references |
| skills/hcom-workflow-scripts/references/architecture.md | hcom internal architecture reference (DB schema, routing, lifecycle, delivery pipeline) |
| skills/hcom-workflow-scripts/references/cross-tool-scripting.md | Cross-tool behavior notes (Claude/Codex/Gemini/OpenCode) and timing/binding guidance |
| skills/hcom-workflow-scripts/references/debugging.md | Troubleshooting guide for script hangs, delivery failures, stale cleanup, etc. |
| skills/hcom-workflow-scripts/references/patterns.md | Tested multi-agent patterns with example scripts and sample event JSON |
| skills/hcom-workflow-scripts/references/script-template.md | Annotated script template and conventions for safe orchestration scripts |
| skills/hcom-workflow-scripts/references/scripts/basic-messaging.sh | Example script: two-agent messaging + DONE signal |
| skills/hcom-workflow-scripts/references/scripts/review-loop.sh | Example script: worker/reviewer feedback loop until approval |
| skills/hcom-workflow-scripts/references/scripts/ensemble-consensus.sh | Example script: 3 contestants + judge fan-out/fan-in |
| skills/hcom-workflow-scripts/references/scripts/cascade-pipeline.sh | Example script: sequential plan → execute pipeline using transcript handoff |
| skills/hcom-workflow-scripts/references/scripts/cross-tool-duo.sh | Example script: Claude spec → Codex implementation cross-tool workflow |
| skills/hcom-workflow-scripts/references/scripts/codex-worker.sh | Example script: Codex codes, Claude reviews transcript |
| skills/hcom-agent-messaging/SKILL.md | Updated skill guide with essential commands, tool support matrix, and scripting patterns |
| skills/hcom-agent-messaging/references/patterns.md | Multi-agent patterns reference (tested examples + event JSON) |
| skills/hcom-agent-messaging/references/cli-reference.md | CLI command/flag reference for launches, messaging, events, transcripts, scripts, config |
| skills/hcom-agent-messaging/references/cross-tool.md | Cross-tool collaboration behavior and binding/delivery gotchas |
| skills/hcom-agent-messaging/references/gotchas.md | Script gotchas and operational troubleshooting guidance |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| echo "Thread: $thread" | ||
| echo "Waiting..." | ||
|
|
||
| hcom events --wait 120 --sql "type='message' AND msg_thread='${thread}' AND msg_text LIKE '%FINAL%'" $name_arg >/dev/null 2>&1 && echo "PASS" || echo "FAIL" |
There was a problem hiding this comment.
hcom events --wait ... is used as a boolean with output redirected away. Given the repo’s docs (in this same PR) that hcom events --wait returns exit code 0 on both match and timeout, this will always print PASS. Capture output and check for empty/non-empty to correctly detect whether FINAL arrived.
| hcom events --wait 120 --sql "type='message' AND msg_thread='${thread}' AND msg_text LIKE '%FINAL%'" $name_arg >/dev/null 2>&1 && echo "PASS" || echo "FAIL" | |
| final_events=$(hcom events --wait 120 --sql "type='message' AND msg_thread='${thread}' AND msg_text LIKE '%FINAL%'" $name_arg 2>/dev/null) | |
| if [[ -n "$final_events" ]]; then | |
| echo "PASS" | |
| else | |
| echo "FAIL" | |
| fi |
| cleanup() { | ||
| for name in "${LAUNCHED_NAMES[@]}"; do | ||
| hcom kill "$name" --go 2>/dev/null || true | ||
| done |
There was a problem hiding this comment.
The script parses --name into name_arg but doesn’t pass it through to the launch/kill calls. If these scripts are intended for hcom run, this can cause hcom subcommands to fail to identify the caller. Forward $name_arg to all hcom invocations (including cleanup).
| trap cleanup ERR | ||
|
|
There was a problem hiding this comment.
trap cleanup ERR won’t run if the script exits explicitly (e.g., exit 1) or is interrupted (SIGINT/SIGTERM). Since this script can exit 1 on timeouts, it can leave headless agents orphaned. Consider trapping EXIT (and optionally INT/TERM) to ensure cleanup always runs, and keep ERR if you still want early cleanup on failing commands.
| launch_out=$(hcom 1 claude --tag arch --go --headless \ | ||
| --hcom-prompt "Design a 2-3 sentence spec for: ${task}. Send to @eng-: hcom send \"@eng-\" --thread ${thread} --intent request -- \"SPEC: <spec>\". Wait for confirmation. Then send: hcom send \"@bigboss\" --thread ${thread} --intent inform -- \"APPROVED\". Then stop: hcom stop" 2>&1) | ||
| track_launch "$launch_out" | ||
| arch=$(echo "$launch_out" | grep '^Names: ' | sed 's/^Names: //' | tr -d ' ') | ||
| echo "Architect (Claude): $arch" | ||
|
|
||
| launch_out=$(hcom 1 codex --tag eng --go --headless \ | ||
| --hcom-prompt "Wait for spec from @arch-. Implement it. Then confirm: hcom send \"@${arch}\" --thread ${thread} --intent inform -- \"IMPLEMENTED\". Then stop: hcom stop" 2>&1) | ||
| track_launch "$launch_out" | ||
| eng=$(echo "$launch_out" | grep '^Names: ' | sed 's/^Names: //' | tr -d ' ') | ||
| echo "Engineer (Codex): $eng" |
There was a problem hiding this comment.
Cross-tool scripts are documented elsewhere in this PR as requiring an hcom events --wait ... --idle "$codex_name" wait before any messages are sent to Codex. Here, Claude is launched first and will likely send the SPEC immediately, before the Codex session binds, which can cause the spec message to be dropped or never delivered. Reorder to launch Codex first (and wait for idle) or add an explicit idle/binding wait before Claude sends the SPEC.
| launch_out=$(hcom 1 claude --tag arch --go --headless \ | |
| --hcom-prompt "Design a 2-3 sentence spec for: ${task}. Send to @eng-: hcom send \"@eng-\" --thread ${thread} --intent request -- \"SPEC: <spec>\". Wait for confirmation. Then send: hcom send \"@bigboss\" --thread ${thread} --intent inform -- \"APPROVED\". Then stop: hcom stop" 2>&1) | |
| track_launch "$launch_out" | |
| arch=$(echo "$launch_out" | grep '^Names: ' | sed 's/^Names: //' | tr -d ' ') | |
| echo "Architect (Claude): $arch" | |
| launch_out=$(hcom 1 codex --tag eng --go --headless \ | |
| --hcom-prompt "Wait for spec from @arch-. Implement it. Then confirm: hcom send \"@${arch}\" --thread ${thread} --intent inform -- \"IMPLEMENTED\". Then stop: hcom stop" 2>&1) | |
| track_launch "$launch_out" | |
| eng=$(echo "$launch_out" | grep '^Names: ' | sed 's/^Names: //' | tr -d ' ') | |
| echo "Engineer (Codex): $eng" | |
| launch_out=$(hcom 1 codex --tag eng --go --headless \ | |
| --hcom-prompt "Wait for spec from @arch-. Implement it. Then confirm: hcom send \"@arch-\" --thread ${thread} --intent inform -- \"IMPLEMENTED\". Then stop: hcom stop" 2>&1) | |
| track_launch "$launch_out" | |
| eng=$(echo "$launch_out" | grep '^Names: ' | sed 's/^Names: //' | tr -d ' ') | |
| echo "Engineer (Codex): $eng" | |
| # Ensure Codex is fully bound and idle before Claude can send it any messages. | |
| hcom events --wait 180 --idle "${eng}" $name_arg >/dev/null 2>&1 | |
| launch_out=$(hcom 1 claude --tag arch --go --headless \ | |
| --hcom-prompt "Design a 2-3 sentence spec for: ${task}. Send to @eng-: hcom send \"@eng-\" --thread ${thread} --intent request -- \"SPEC: <spec>\". Wait for confirmation. Then send: hcom send \"@bigboss\" --thread ${thread} --intent inform -- \"APPROVED\". Then stop: hcom stop" 2>&1) | |
| track_launch "$launch_out" | |
| arch=$(echo "$launch_out" | grep '^Names: ' | sed 's/^Names: //' | tr -d ' ') | |
| echo "Architect (Claude): $arch" |
| for i in 1 2 3; do | ||
| launch_out=$(hcom 1 claude --tag "c${i}" --go --headless \ | ||
| --hcom-prompt "Answer: ${task}. Send ONLY your answer: hcom send \"@judge-\" --thread ${thread} --intent inform -- \"C${i}: <answer>\". Then stop: hcom stop" 2>&1) | ||
| track_launch "$launch_out" | ||
| name=$(echo "$launch_out" | grep '^Names: ' | sed 's/^Names: //' | tr -d ' ') | ||
| echo "Contestant $i: $name" | ||
| done | ||
|
|
||
| launch_out=$(hcom 1 claude --tag judge --go --headless \ | ||
| --hcom-prompt "Wait for 3 answers in thread '${thread}'. Check: hcom events --sql \"msg_thread='${thread}'\" --last 10. Pick best. Send: hcom send \"@bigboss\" --thread ${thread} --intent inform -- \"VERDICT: <winner>\". Then stop: hcom stop" 2>&1) |
There was a problem hiding this comment.
The --name flag is parsed into name_arg, but it isn’t forwarded to the hcom commands in this script besides the events --wait. If these scripts are expected to work via hcom run (which injects --name), propagate $name_arg to all hcom calls (launch, kill, events queries) for consistent identity resolution.
| launch_out=$(hcom 1 claude --tag worker --go --headless \ | ||
| --hcom-prompt "Do this: ${task}. Send result to @reviewer- via: hcom send \"@reviewer-\" --thread ${thread} --intent inform -- \"RESULT: <your answer>\". Then stop: hcom stop" 2>&1) | ||
| track_launch "$launch_out" | ||
| worker=$(echo "$launch_out" | grep '^Names: ' | sed 's/^Names: //' | tr -d ' ') | ||
| echo "Worker: $worker" | ||
|
|
||
| launch_out=$(hcom 1 claude --tag reviewer --go --headless \ | ||
| --hcom-prompt "Wait for a message from @worker-. When received, reply: hcom send \"@${worker}\" --thread ${thread} --intent ack -- \"ACK: received\". Then send: hcom send \"@bigboss\" --thread ${thread} --intent inform -- \"DONE\". Then stop: hcom stop" 2>&1) |
There was a problem hiding this comment.
The script parses --name into name_arg, but most hcom invocations (launches, kills, final events --sql) don’t include it. If this is run via hcom run (which injects --name), those commands may not resolve the caller identity consistently. Pass $name_arg through to all hcom commands in the script (including kill in cleanup).
| echo "Waiting for plan..." | ||
| hcom events --wait 60 --sql "type='message' AND msg_thread='${thread}' AND msg_text LIKE '%PLAN DONE%'" $name_arg >/dev/null 2>&1 || { echo "FAIL (planner timeout)"; exit 1; } | ||
|
|
There was a problem hiding this comment.
hcom events --wait ... is used as a boolean (and stdout is discarded), but this repository’s docs state hcom events --wait returns exit code 0 on both match and timeout. That means the planner timeout branch won’t trigger and failures may be reported as PASS. Capture the output and check whether it is empty to detect timeouts reliably.
| echo "Thread: $thread" | ||
| echo "Waiting..." | ||
|
|
||
| hcom events --wait 180 --sql "type='message' AND msg_thread='${thread}' AND msg_text LIKE '%APPROVED%'" $name_arg >/dev/null 2>&1 && echo "PASS" || echo "FAIL" |
There was a problem hiding this comment.
hcom events --wait ... is used as a boolean with output discarded. This PR’s own debugging docs state hcom events --wait returns exit code 0 on both match and timeout, so this will always print PASS. Capture the output and test for empty/non-empty to distinguish match vs timeout.
| hcom events --wait 180 --sql "type='message' AND msg_thread='${thread}' AND msg_text LIKE '%APPROVED%'" $name_arg >/dev/null 2>&1 && echo "PASS" || echo "FAIL" | |
| events_out=$(hcom events --wait 180 --sql "type='message' AND msg_thread='${thread}' AND msg_text LIKE '%APPROVED%'" $name_arg 2>/dev/null || true) | |
| if [[ -n "$events_out" ]]; then | |
| echo "PASS" | |
| else | |
| echo "FAIL" | |
| fi |
| trap - ERR | ||
| for name in "${LAUNCHED_NAMES[@]}"; do hcom kill "$name" --go 2>/dev/null || true; done | ||
| hcom events --sql "msg_thread='${thread}'" --last 10 2>&1 |
There was a problem hiding this comment.
The script parses --name into name_arg, but most hcom invocations don’t include it (launches, kills, final events --sql). If the script is run under hcom run, this can break identity resolution for those commands. Pass $name_arg to all hcom commands for consistency.
| echo "Thread: $thread" | ||
| echo "Waiting..." | ||
|
|
||
| hcom events --wait 120 --sql "type='message' AND msg_thread='${thread}' AND msg_text LIKE '%VERDICT%'" $name_arg >/dev/null 2>&1 && echo "PASS" || echo "FAIL" |
There was a problem hiding this comment.
hcom events --wait ... is treated as a success/failure boolean with stdout discarded. This PR’s debugging docs say the exit code is 0 on both match and timeout, so this will always print PASS and won’t detect timeouts. Capture the output and check for non-empty instead of relying on the exit status.
| hcom events --wait 120 --sql "type='message' AND msg_thread='${thread}' AND msg_text LIKE '%VERDICT%'" $name_arg >/dev/null 2>&1 && echo "PASS" || echo "FAIL" | |
| events_out=$(hcom events --wait 120 --sql "type='message' AND msg_thread='${thread}' AND msg_text LIKE '%VERDICT%'" $name_arg 2>/dev/null) | |
| if [[ -n "$events_out" ]]; then | |
| echo "PASS" | |
| else | |
| echo "FAIL" | |
| fi |
- events --wait returns 0/1/2 (match/timeout/SQL error), not 0 for both - stale cleanup threshold is 120s not 30s (CLEANUP_PLACEHOLDER_THRESHOLD) - cross-tool-duo.sh: launch Codex first and wait for idle before Claude sends spec — avoids race where spec arrives before session binds - trap cleanup ERR INT TERM in all scripts (was ERR-only, missing signals) Co-authored-by: Yigit Konur <9989650+yigitkonur@users.noreply.github.com>
what this does
enhances the existing
hcom-agent-messagingskill and adds a newhcom-workflow-scriptsskill — both built from hands-on testing with real claude + codex agents.hcom-agent-messaging (enhanced)
the existing skill was a solid setup/troubleshooting guide. this PR keeps the original name and description but adds practical depth:
hcom events --wait 30 --idle $name)patterns.md,cli-reference.md,cross-tool.md,gotchas.mdhcom-workflow-scripts (new skill)
a new skill focused on writing custom multi-agent workflow scripts. includes:
how this was tested
all 6 scripts were run with real hcom v0.7.6 agents. each test launched headless claude and/or codex agents, exchanged messages via threads, and verified completion signals via
hcom events --wait --sql. real event JSON from test runs is included in the pattern docs.test results:
files changed
17 files changed, 3377 insertions, 66 deletions.