ในบทความนี้
- 1. The Four Layers of Multi-Agent Hermes
- 2. delegate_task — Fork-Join Subagents ที่เกิดมาพร้อม Context สดใหม่
- 3. Background Delegation และ Live Steering
- 4. Worktree Isolation — ขนานกันโดยไม่ชนกัน
- 5. Hermes Kanban — บอร์ดงานถาวรของทีม Agents
- 6. Bot Mode — สังคมของ Bots, Group Chats และ Peer DMs
- 7. Always-On Work — cron Jobs vs Session Heartbeats
- 8. Serving a Whole Team — Profiles, Gateways และ Allowlists
- 9. Choosing the Right Layer — เลือกชั้นให้ถูกงาน
In this post
- 1. The Four Layers of Multi-Agent Hermes
- 2. delegate_task: Fork-Join Subagents with Fresh Contexts
- 3. Background Delegation and Live Steering
- 4. Worktree Isolation: Parallel Work Without Collisions
- 5. Hermes Kanban: A Durable Task Board Your Agents Share
- 6. Bot Mode: Named Agents, Group Chats, and Peer DMs
- 7. Always-On Work: cron Jobs vs Session Heartbeats
- 8. Serving a Whole Team: Profiles, Gateways, Allowlists
- 9. Choosing the Right Layer
🤔 ลองนึกภาพว่าคุณ clone เพื่อนร่วมงานเก่ง ๆ ได้ไม่จำกัด — แต่ clone แต่ละตัวเกิดมาพร้อมความจำว่างเปล่า ทำงานชิ้นเดียวเสร็จก็หายตัวไปตลอดกาล คำถามคือ คุณจะประกอบ "ทีม" จากสิ่งมีชีวิตแบบนี้อย่างไร ให้งานที่ใหญ่กว่าหนึ่ง context window เดินได้จริง?
นี่คือคำถามกลางของ multi-agent ทุกระบบ และเป็นคำถามเดียวกับที่ผมเคยชวนคิดไว้ในบทความ Agent Teams ฝั่ง OpenClaw ของซีรีส์ OpenClaw for Organizations — โลกที่เราประกอบทีมจาก session, subagent และการ route ข้อความผ่าน gateway ด้วย pattern ที่หลายส่วนต้องออกแบบกันเอง ผมรัน OpenClaw ในงานจริงมาพักใหญ่ และตอนนี้กำลังไล่ดู Hermes Agent ของ Nous Research อย่างจริงจัง ว่า harness ที่คนให้ดาวบน GitHub เกือบ 240,000 ดวงตอบคำถามข้อนี้ต่างไปอย่างไร
คำตอบสั้น ๆ คือ Hermes ไม่ได้มี "ฟีเจอร์ multi-agent" หนึ่งอัน แต่มีถึง สี่ชั้น ที่แก้ปัญหาคนละแบบ — subagent แบบ fork-join, บอร์ด Kanban ถาวรบน SQLite, สังคมของ bots ที่ DM หากันได้ และการเสิร์ฟหลายคนหลายบทบาทจากเครื่องเดียว ต่อจาก Hermes 101 บทความนี้คือแผนที่ของทั้งสี่ชั้น ทุกรายละเอียดอ้างอิง official docs และ release notes ณ v0.21.0 (31 สิงหาคม 2026)
1. The Four Layers of Multi-Agent Hermes
ก่อนลงรายละเอียด ผมอยากกางแผนที่ให้เห็นก่อน เพราะความสับสนส่วนใหญ่เรื่อง multi-agent ใน Hermes มาจากการเอาชั้นที่ต่างกันมาปนกัน แต่ละชั้นมี tool surface ของตัวเอง มี "อายุงาน" ต่างกัน และเกิดมาแก้ปัญหาคนละข้อ:
| ชั้น | Tool surface | ความคงทน | เหมาะกับ |
|---|---|---|---|
| 1. In-session subagents | delegate_task | ตายพร้อม session | fork-join งานขนานที่สรุปกลับเข้าบทสนทนาเดียว |
| 2. Kanban board | /kanban + kanban_* verbs | ถาวร (SQLite, ข้าม restart) | งานข้ามวัน มี audit trail ให้มนุษย์แทรกได้ |
| 3. Bot Mode + A2A | message_agent, hermes peer, A2A plugin | ตามอายุ gateway/relay | ทีม bots ถาวรที่คุยกันเอง ข้ามเครื่อง ข้าม harness |
| 4. Multi-profile serving | profiles + gateway routes | ระดับ service (systemd) | หนึ่งเครื่องเสิร์ฟหลายคน หลายบทบาท |
แกนที่ควรจับไว้คือ ความคงทน (durability) ไล่ขึ้นตามตาราง — subagent ในชั้นแรกตายพร้อม session, task บน Kanban อยู่ข้าม restart, ส่วน profile คือตัวตนถาวรระดับ service และสี่ชั้นนี้ไม่ได้แข่งกัน มันซ้อนกันได้: bot หนึ่งตัว (ชั้น 3) อาจแตก subagent (ชั้น 1) เพื่อเคลียร์ card บนบอร์ด Kanban (ชั้น 2) บนเครื่องที่เสิร์ฟทั้งทีม (ชั้น 4)
💡 ของที่มักถูกเข้าใจผิดว่าเป็นอีกชั้น: Mixture of Agents (MoA) ไม่ใช่ delegation — docs จัดมันเป็น "virtual model provider" ที่ให้ reference models หลายตัวทำหน้าที่ advisor ขนานกัน (ไม่มี tool schema) แล้วมี aggregator ตัวเดียวเขียนคำตอบและยิง tool calls ตั้งค่าผ่านmoa.default_preset/moa.presets— MoA คือหลายสมองในหนึ่งเทิร์น ไม่ใช่หลาย agent ทำหลายงาน
2. delegate_task — Fork-Join Subagents ที่เกิดมาพร้อม Context สดใหม่
ชั้นแรกคือเครื่องมือ delegate_task: agent แตกงานให้ child ที่มีบทสนทนาสดใหม่ของตัวเอง เอกสาร delegation เขียนไว้ชัดว่า "Each child gets a fresh conversation and works independently — only its final summary enters the parent's context" — ลูกไม่เห็นประวัติแชทของ parent เลย และสิ่งเดียวที่ไหลกลับเข้า parent คือ summary สุดท้าย
# ภายใน session — agent เรียก tool นี้เพื่อแตกงาน (pseudo-call)
delegate_task(
task="อ่านโค้ดทั้ง src/billing แล้วสรุป edge cases พร้อมชี้ไฟล์อ้างอิง"
)
# child เริ่มจากบทสนทนาว่างเปล่า + project context file เท่านั้น
# สิ่งเดียวที่ย้อนกลับเข้า parent: final summary
อะไรไหลเข้า อะไรไหลออก
ข้อยกเว้นเดียวของ "ความจำว่างเปล่า" คือ project context: ถ้ามี workspace, Hermes จะฝัง context file ตามลำดับความสำคัญ .hermes.md → AGENTS.md → CLAUDE.md → .cursorrules ลงใน system prompt ของ subagent ทุกตัวโดยอัตโนมัติ
ค่า default ที่ควรรู้
ตัวเลขชุดนี้เคยเปลี่ยนข้ามเวอร์ชันมาแล้ว (release notes บางฉบับพูดถึงเพดาน iteration คนละค่ากับ docs) ค่าด้านล่างคือค่าตามเอกสารทางการ ณ วันที่ 1 กันยายน 2026 — ก่อน tune ควรเช็ค doc ปัจจุบันอีกครั้งเสมอ:
# ~/.hermes/config.yaml — ค่า default ของ delegation (ตาม docs, v0.21.0)
delegation:
max_concurrent_children: 3 # env: DELEGATION_MAX_CONCURRENT_CHILDREN (ขั้นต่ำ 1, ไม่มีเพดาน)
max_iterations: 50 # ต่อ child หนึ่งตัว
max_spawn_depth: 1 # flat โดย default — เพิ่มเป็น 2+ เพื่อ nested orchestration
worktree_isolation: false
orchestrator_enabled: true
child_timeout_seconds: 0 # 0 = ไม่มี hard timeout (ถ้าเปิดใช้ มี floor 30s)
จาก tool เดี่ยวสู่ทีมย่อย
สามความสามารถที่ยกระดับชั้นนี้จาก "ผู้ช่วยชั่วคราว" เป็น "ทีมย่อย":
- Batch dispatch — ส่ง
tasks=[...]หลายงานในครั้งเดียว วิ่งขนานกันสูงสุดmax_concurrent_children - Nested orchestration — ส่ง
role="orchestrator"ให้ลูกแตกลูกต่อได้ (ต้องยกmax_spawn_depthเป็น 2+ ก่อน) - Worker ถูกกว่า parent — ตั้ง
delegation.model/provider/base_urlแยกจาก parent เพื่อให้ลูกใช้โมเดลราคาถูกลง
# batch dispatch — สามงานอิสระ วิ่งขนาน
delegate_task(tasks=[
"วิเคราะห์ log สัปดาห์นี้ หากลุ่ม error ที่เกิดซ้ำ",
"รีวิว PR #42 เฉพาะมุม security",
"เทียบ library A กับ B สำหรับงาน ingest"
])
# nested orchestration — ลูกที่คุมทีมย่อยของตัวเอง
delegate_task(
task="แตกงาน refactor ทั้ง module แล้วคุมทีมย่อยให้จบ",
role="orchestrator"
)
ขอบเขตของชั้นนี้ก็ชัดพอ ๆ กับความสามารถ — และเป็นความตั้งใจของ design: subagent คุยกันเองไม่ได้ docs ระบุว่า "No direct messaging between subagents … all coordination flows through parent's reasoning" และ leaf subagent ถูกตัด tools สำคัญออกทั้งชุด: delegate_task, clarify, memory, send_message, cronjob (orchestrator ได้ delegate_task คืนมาหนึ่งอย่าง ข้อห้ามอื่นเหมือนกัน และทั้งสอง role ยังใช้ execute_code ได้)
ระหว่างลูกวิ่ง คุณส่องได้ตลอด: /agents แสดง tree สดของลูกทุกตัว (จำนวน API calls, tool ที่กำลังใช้, activity ล่าสุด), /stop ยกเลิก background delegation และ transcript สดของแต่ละ task อยู่ที่ ~/.hermes/cache/delegation/live/<delegation_id>/task-<n>.log
3. Background Delegation และ Live Steering
เดิมที delegate_task เป็นการรอแบบ synchronous — parent นั่งเฝ้าจนลูกเสร็จ จุดเปลี่ยนแรกคือ v0.17.0 (19 มิถุนายน 2026) ที่เพิ่ม background=true: dispatch แล้วได้ handle กลับมาทันที ทำงานอื่นต่อได้เลย ตาม release notes "The full result re-enters the conversation as a new turn the moment it finishes" — ผลฉบับเต็มเด้งกลับเข้าบทสนทนาเองเมื่อเสร็จ
จุดเปลี่ยนที่สองเพิ่งมาใน v0.21.0 (31 สิงหาคม 2026) ใต้หัวข้อ "Steer your subagents while they run": delegate_task ได้ live orchestration — ดูรายชื่อลูกที่วิ่งอยู่, ส่งคำสั่งแก้ทิศกลางคัน, หรือหยุดก่อนกำหนดแล้วเก็บผลบางส่วน พร้อมของแถมอีกสองอย่างคือ JSON-schema validation ของ output ลูก และต้นทุนต่อ delegation ที่โผล่ในผลลัพธ์
# v0.17.0+ — ปล่อยงานเป็น background ได้ handle ทันที
delegate_task(task="crawl เอกสารทั้งชุดแล้วสร้าง index", background=true)
# v0.21.0+ — live orchestration ระหว่างลูกยังวิ่ง
delegate_task(action="list") # ลูกตัวไหนวิ่งอยู่บ้าง
delegate_task(action="steer", subagent_id="abc123",
message="ข้ามเอกสารเวอร์ชันเก่า โฟกัส v2 API เท่านั้น")
delegate_task(action="stop", subagent_id="abc123") # หยุดก่อนกำหนด เก็บผลบางส่วน
สำหรับงาน background ที่แขวนค้าง Hermes มี stall monitor เปิดตลอด: เงียบเกิน 450 วินาที (หรือ 1,200 วินาทีถ้ากำลังค้างอยู่ในการเรียก tool) จะถูกนับเป็น stalled โดยมี grace อีก 120 วินาทีให้คลี่คลายตัวเอง พร้อม metadata บอก phase ของ stall ส่วนเพดานเวลาแบบ hard (child_timeout_seconds) เป็น opt-in และปิดโดย default — และผลของ background delegation ยัง persist ใน state.db ของ profile ข้าม restart ด้วย
เกร็ดที่สะท้อนจังหวะพัฒนาอันเร็วของโปรเจกต์นี้: บทความ third-party ช่วงกลางมิถุนายน 2026 (MarkTechPost และ kno2gether) บรรยายชุดเครื่องมือ "async_delegation" หกตัวแยกกัน — delegate_task_async, check_task, steer_task ฯลฯ — แต่ docs ปัจจุบันไม่เหลือชื่อเหล่านี้เลย ดูเหมือน surface ทั้งชุดถูกยุบรวมเข้า delegate_task ตัวเดียวระหว่างมิถุนายนถึงกันยายน ใครอ่าน tutorial เก่าแล้วหา tool ไม่เจอ ไม่ต้องตกใจ
4. Worktree Isolation — ขนานกันโดยไม่ชนกัน
ปัญหาคลาสสิกของ agent หลายตัวในหนึ่ง repo คือแก้ไฟล์ชนกัน Hermes ตอบเรื่องนี้ สองระดับ ที่คนมักจำสลับกัน — และข้อมูลบนอินเทอร์เน็ตเองก็สับสนเรื่องนี้อยู่ (เดี๋ยวเล่า)
ระดับ CLI session — hermes -w
ระดับแรกคือการรัน Hermes หลาย process ขนานกันคนละ terminal: เอกสาร git worktrees ระบุว่า "every invocation gets its own worktree and branch automatically" — ทุกการรัน hermes -w ได้ git worktree ชั่วคราวใต้ .worktrees/ พร้อม branch แยกของตัวเอง
# CLI-level parallelism — คนละ terminal คนละ worktree ไม่ชนกัน
hermes -w # ทุก invocation ได้ worktree + branch อัตโนมัติ
/worktree new my-experiment # สร้าง .worktrees/my-experiment/ บน branch hermes/my-experiment
# เปิดหลาย terminal รัน hermes หลาย process ขนานกันได้เลย
# checkpoint history และ /rollback แยก scope ต่อ worktree
Feature นี้เก่ากว่าที่หลายบทความอ้าง: feature request คือ issue #652 เปิดเมื่อ 8 มีนาคม 2026 และอยู่ในเอกสารตั้งแต่กลางเดือนมีนาคม — ส่วนคำเล่าที่แพร่กันว่ามัน "มากับ v0.8.0" นั้นเช็คกับ primary sources แล้วไม่ตรง (v0.8.0 เมื่อเมษายน 2026 ให้เพียง "aggressive worktree and branch cleanup") คำสั่งกลาง session /worktree ที่ docs ระบุว่า "Inspired by Copilot CLI" ถูกเพิ่มเข้าเอกสารกลางเดือนสิงหาคม 2026
ระดับ subagent — delegation.worktree_isolation
ระดับที่สองใหม่กว่าและละเอียดกว่า: เปิด delegation.worktree_isolation: true (default คือ false) แล้ว subagent ทุกตัวจากข้อ 2 จะได้ git worktree ของตัวเองที่ <repo>/.worktrees/subagent-<id> บน branch hermes-subagent/subagent-<id> แตกจาก HEAD ปัจจุบัน (docs ให้เครดิตแรงบันดาลใจจาก Muse Code's --subagent-worktree-isolation) worktree ที่สะอาด — ไม่มี commit — จะถูก prune อัตโนมัติ
# ~/.hermes/config.yaml
delegation:
worktree_isolation: true # default: false
# ผลลัพธ์ของแต่ละ child จะมี field "worktree" เพิ่มมา:
# path: <repo>/.worktrees/subagent-<id>
# branch: hermes-subagent/subagent-<id>
# commits ahead of base / dirty / pruned
worktree ในผลลัพธ์ของลูกทุกครั้ง
5. Hermes Kanban — บอร์ดงานถาวรของทีม Agents
ทุกอย่างในสองหัวข้อก่อนหน้ามีจุดอ่อนร่วมกันหนึ่งข้อ: มัน ตายพร้อม session ปิด process เมื่อไร ทีมย่อยก็ระเหย นี่คือช่องที่ Hermes Kanban เข้ามาปิด — ship ครั้งแรกใน v0.13.0 (7 พฤษภาคม 2026) กับ headline ที่ตรงจุดมาก: "Multi-agent Kanban — delegate to an AI team that actually finishes"
หัวใจคือฐานข้อมูล SQLite หนึ่งไฟล์ที่ ~/.hermes/kanban.db — docs สรุปปรัชญาไว้ว่า "Every task is a row … every handoff is a row anyone can read and write" งานทุกชิ้นคือแถวในตาราง handoff ทุกครั้งคือแถวที่ profile ไหนก็อ่านเขียนได้ ไม่ใช่ state ที่ลอยอยู่ในหัวของ agent ตัวใดตัวหนึ่ง
กลไก dispatcher
dispatcher ฝังอยู่ใน gateway (kanban.dispatch_in_gateway: true) ตื่นทุก 60 วินาที เพื่อ (1) reclaim งานจาก worker ที่ heartbeat หายเกิน 4 ชั่วโมง (2) เลื่อนงานที่ dependencies ครบแล้วเป็น ready และ (3) claim งานแบบ atomic แล้ว spawn worker เป็น OS process เต็มตัว: hermes -p <assignee> chat -q <prompt> พร้อมฉีด KANBAN_GUIDANCE และ env vars อย่าง HERMES_KANBAN_TASK, HERMES_KANBAN_DB, HERMES_KANBAN_WORKSPACE, HERMES_PROFILE, HERMES_TENANT ให้ worker รู้บริบทของตัวเอง
# ~/.hermes/config.yaml — knobs หลักของ Kanban (ค่า default ตาม docs)
kanban:
dispatch_in_gateway: true
dispatch_interval_seconds: 60 # dispatcher tick
dispatch_stale_timeout_seconds: 14400 # 4 ชม. — reclaim งานจาก worker ที่เงียบหาย
failure_limit: 2 # circuit breaker ต่อ task
max_in_progress: ~ # default: ไม่จำกัดทั้งบอร์ด
max_in_progress_per_profile: ~
auto_promote_children: true
Protocol ที่ worker ต้องเคารพ
ความน่าเชื่อถือของบอร์ดมาจาก protocol ที่เข้มงวด: worker ต้องจบ run ด้วย verb ใด verb หนึ่ง เท่านั้น — kanban_complete, kanban_request_review หรือ kanban_block ถ้าจบโดยไม่เรียกสักตัว งานจะถูกจัดสถานะ crashed / gave_up / timed_out โดยระบบ nudge ซ้ำอัตโนมัติได้สูงสุด 2 ครั้ง และมี retry budget (default: ผิด protocol ติดกัน 3 ครั้งคือหมดสิทธิ์) release notes สรุปชุดกลไกนี้ว่า "Heartbeats, reclaim, zombie detection, retry budgets, and a hallucination gate keep the team honest"
orchestrator ฝั่ง Kanban ทำงานผ่าน verbs สร้างงานล้วน ๆ — แตก goal เป็น card ลูก ผูก dependency โดยไม่มี implementation tools ในมือ:
# orchestrator แตกงานเป็น card ลูก ผูก dependency ด้วย parents
kanban_create(title="รวบรวม changelog v0.21.0", assignee="researcher")
kanban_create(title="ร่างประกาศภายในจาก changelog",
assignee="writer",
parents=["<task-id-ของงานแรก>"])
# card ลูกได้ "## Parent task results" (summary + metadata ของ parent)
# ฉีดเข้า context ของ worker โดยอัตโนมัติ
แต่ละ card เลือก workspace ได้สามแบบ: worktree (git worktree ที่ .worktrees/<id>/ เก็บไว้หลังงานเสร็จ), scratch (ลบทิ้งเมื่อเสร็จ) และ dir:<path> (แชร์ร่วมกัน คงอยู่ตลอด) ส่วน card แบบ goal-mode (--goal / goal_mode=True พร้อม --goal-max-turns) จะรัน loop สไตล์ Ralph ภายใน card เดียว โดยมี judge model ตรวจผลกับ acceptance criteria ทุกเทิร์น — ถ้า budget หมดก่อนผ่าน card จะถูก block ไว้ให้มนุษย์รีวิว ไม่ fail เงียบ
Kanban vs delegate_task — ตารางเทียบทางการ
docs มีตารางเทียบสองชั้นนี้ตรง ๆ ซึ่งผมถอดใจความมาให้:
| delegate_task | Hermes Kanban | |
|---|---|---|
| โมเดล | fork → join RPC | durable queue + state machine |
| ตัวตน worker | anonymous, resume ไม่ได้ | named profile + persistent memory |
| การกู้คืน | ตายพร้อม session | block / unblock / re-run ได้ |
| มนุษย์แทรก | — | comment / unblock ได้ทุกจุด |
| Audit trail | — | SQLite บันทึกทุก handoff |
| Coordination | ผ่าน parent เท่านั้น | peer — profile ไหนก็อ่าน/เขียน task ได้ |
docs ยังรวบรวม collaboration patterns ไว้ 8 แบบ — fan-out, pipeline, voting/quorum, long-running journal, human-in-the-loop, @mention, thread-scoped workspace และ fleet farming (ตัวอย่างในเอกสาร: หนึ่ง profile ดูแล 50 social accounts) และมี soft multi-tenancy ผ่าน --tenant: "One specialist fleet can serve multiple businesses (--tenant business-a) with data isolation" — ฝูง specialist ชุดเดียวเสิร์ฟหลายธุรกิจโดยแยก workspace และ memory key กัน
ใช้งานจากมือถือก็ได้: verb ทั้งหมดเข้าถึงผ่าน /kanban จากทุก gateway platform (Telegram, Discord, Slack, WhatsApp, Signal, Matrix ฯลฯ) และแชทที่สั่งงานจะ auto-subscribe เหตุการณ์ปลายทางของ task — เลือกโหมดได้ว่าแค่ notify, notify+wake หรือ wake ให้ agent ตื่นขึ้นมาจัดการต่อเมื่องาน completed / blocked / crashed
6. Bot Mode — สังคมของ Bots, Group Chats และ Peer DMs
ชั้นที่สามคือชั้นที่ทำให้คำว่า "สังคมของ bots" ในชื่อบทความไม่ใช่คำเปรียบเปรย Bot Mode เริ่มชีวิตเป็นปลั๊กอิน public beta ของ Teknium (co-founder ของ Nous) และตามรายงานของ MarkTechPost มันถูก bundle แบบ default-on ใน Hermes Desktop ตั้งแต่ราว v0.20.3 กลางเดือนสิงหาคม ก่อนถูกผนวกอย่างเป็นทางการใน v0.21.0 "The Pantheon Release" (31 สิงหาคม 2026) ซึ่งบรรยายมันว่า "a society of named agents with their own faces and group chats, where your bots talk to each other — and to you — like a team, not a toolbox"
Bot = Profile
ประโยคเดียวที่ต้องจำ: Bot หนึ่งตัวคือ Hermes profile หนึ่งอัน — config, memory, skills, credentials และประวัติแชทแยกขาดกันใต้ ~/.hermes/profiles/<name>/ pin โมเดล/provider ต่อ bot ได้ เขียนบุคลิกใน SOUL.md ได้ และเลือกเปิด skills / toolsets / MCP เป็นราย bot ทุกอย่างมี CLI parity: hermes -p <bot> chat, hermes profile create, hermes cron list ส่วน "กิจวัตร" ของ bot ก็คือ cron job ธรรมดาที่ namespace เป็น [bot:<name>] <routine>
message_agent และ Group Chats
bots คุยกันผ่าน tool message_agent (เปิดด้วย agent.bot_mode_protocol: true — ฉีดให้อัตโนมัติใน Bot Chats): ส่งแบบ fire-and-forget แล้วคำตอบวิ่งกลับมาเป็น background notification ถ้าส่งไม่ผ่าน retry ให้ 1 ครั้งพร้อมเหตุผลแบบ typed เช่น provider_auth_or_access, provider_quota_limit, context_overflow
# จาก bot หนึ่ง ส่งข้อความหาอีก bot
message_agent(target="researcher",
message="ขอ 5 bullet ล่าสุดเรื่อง A2A adoption")
# fire-and-forget: reply กลับมาเป็น background completion notification
# ล้มเหลว retry สูงสุด 1 ครั้ง + typed failure reason
ใน group chat กติกาถูกออกแบบกันน้ำท่วม: แต่ละการส่งกระตุ้นได้สูงสุด 3 รอบ serial ของสมาชิก รวมไม่เกิน 10 ข้อความ โดย bot "replies only when it has something new to add and passes otherwise" — ตอบเมื่อมีของใหม่ ไม่งั้นผ่าน และ escalate หามนุษย์ด้วย @user ได้เสมอ ห้องแชทข้ามเครื่องได้ผ่าน Desktop relay
Peers และ A2A — ข้ามเครื่อง ข้าม harness
ไม่ใช้ Desktop ก็ต่อ gateway ถึง gateway ตรง ๆ ได้ ผ่าน platform api_server กับ key ที่แข็งแรง:
# gateway-to-gateway โดยไม่มี Desktop
hermes peer add spark --url http://spark.lan:8377 --key <API_SERVER_KEY>
hermes peer dm spark "สรุปสถานะ pipeline ล่าสุดให้หน่อย"
hermes peer run spark "deploy staging" --idempotency-key deploy-20260901
# key เก็บใน ~/.hermes/.env เป็น HERMES_PEER_<NAME>_KEY
# URL อยู่ใต้ bot_peers ใน config.yaml
และสำหรับโลกนอก Hermes: v0.20.0 "The Herald Release" (3 สิงหาคม 2026) bundle ปลั๊กอิน A2A v1.0 — ปิด issue #514 ซึ่ง release notes เรียกว่า "one of the oldest open feature requests in the repo" — ทำให้ Hermes "discover, talk to, and be driven by other A2A-compatible agents" ได้ตามมาตรฐานกลาง พร้อม outbound webhooks แบบ signed (HMAC) สำหรับ lifecycle events ระบบ heterogeneous ที่ผสม agent หลายค่ายจึงมี wire protocol กลางให้เกาะ
7. Always-On Work — cron Jobs vs Session Heartbeats
ทีมที่ดีไม่ได้ทำงานเฉพาะตอนถูกสั่ง Hermes มีกลไก "ตื่นเอง" สองแบบที่ปรัชญาตรงข้ามกันพอดี — และการเลือกผิดตัวคือ bug คลาสสิกของมือใหม่
cronjob — ถาวรแต่ isolated
tool cronjob (actions: create / list / update / pause / resume / run / remove) รับ schedule ได้สี่ภาษา และ gateway daemon เดินนาฬิกาให้ทุก 60 วินาที:
# รูปแบบ schedule ที่ cronjob รับ — เลือกอย่างใดอย่างหนึ่ง
cronjob(action="create", schedule="in 30m", prompt="...") # one-shot สัมพัทธ์
cronjob(action="create", schedule="every 2h", prompt="...") # interval
cronjob(action="create", schedule="weekdays at 9am", prompt="...") # ภาษาธรรมชาติ
cronjob(action="create", schedule="0 9 * * *", prompt="...") # cron expression
ทุก run เกิดใน session สดใหม่ที่ isolated — ไม่มีประวัติแชทติดไป และเพื่อกัน agent สั่งตัวเองวนไม่รู้จบ cron-management tools ถูกปิดภายใน cron execution (override ได้ที่ cron.allow_agent_scheduling, default false) เพดานงานขนานคุมด้วย cron.max_parallel_jobs
ความ isolated ไม่ได้แปลว่าโง่ซ้ำซาก — สองกลไกต่อความจำข้าม run ให้:
- continuity=True — ฉีด output ล่าสุดของ job ตัวเองกลับเข้า run ถัดไป (เหมาะกับ scout ที่ต้อง dedup ของที่รายงานไปแล้ว)
- context_from="<job_id>" — chain งาน: เอา output ล่าสุดของ Job A ไปเป็น context ของ Job B
# scout ประจำที่จำผลรอบก่อนได้ และส่งเข้า Telegram thread ของทีม
cronjob(action="create",
schedule="every 6h",
prompt="สแกนหา multi-agent papers ใหม่ ถ้าไม่มีของใหม่ตอบ [SILENT]",
continuity=True, # จำ output รอบก่อน — ไม่รายงานซ้ำ
deliver="telegram:-100123456:42") # รูปแบบ chat_id:thread_id
ปลายทางของผลลัพธ์ยืดหยุ่นมาก: deliver รับ origin (default บนแพลตฟอร์มแชท), local, telegram / discord / slack / email / sms, all และ bot-chat โดยตอบ [SILENT] เพื่อกลืนผลเงียบ ๆ ได้ ส่วนงาน script ล้วนใช้ no_agent=True รันโดยไม่เรียก LLM เลย และ v0.21.0 เพิ่งอุดจุดอ่อนเก่าด้วย headline "Cron jobs that remember" — cron agent โหลด/อัปเดต persistent memory ได้แล้ว พร้อม notepad ถาวรของตัวเอง
/heartbeat — in-context แต่ต้องมีชีวิต
ขั้วตรงข้ามคือ session heartbeat: prompt ที่เด้งกลับเข้า session ปัจจุบันตามรอบเวลา เห็นประวัติสนทนาเต็ม แต่ต้องมี process มีชีวิตรออยู่
/heartbeat every 10m เช็คบอร์ด Kanban — มี card ไหน blocked ค้างไหม
# ขั้นต่ำ 60s · ทำงานเฉพาะตอน idle ไม่แทรกงานที่กำลังรัน
# tick ที่พลาดถูก coalesce เหลือครั้งเดียว
# state เก็บใน SessionDB.state_meta ใต้ heartbeat:<session_id>
| cronjob | /heartbeat | |
|---|---|---|
| Context | session สดใหม่ ไม่มีประวัติแชท | ประวัติสนทนาเต็ม |
| ความคงทน | อยู่ข้าม restart (gateway daemon) | ต้องมี process มีชีวิต |
| จังหวะ | ตาม schedule จริงจัง | idle-only, coalesced |
| เหมาะกับ | งานประจำระยะยาว | เตือนตัวเองใน session ที่เปิดอยู่ |
8. Serving a Whole Team — Profiles, Gateways และ Allowlists
สามชั้นแรกคือ agent ทำงานร่วมกับ agent ชั้นสุดท้ายคือคำถามที่องค์กรถามผมบ่อยที่สุด: เครื่องเดียวเสิร์ฟ คน หลายคน หลายบทบาท ได้ไหม — คำตอบของ Hermes คือได้ ผ่านการประกอบ profiles + gateways + allowlists
หนึ่ง profile ต่อหนึ่งบทบาท
ค่า default คือ หนึ่ง gateway process ต่อหนึ่ง profile — ตัวอย่างใน docs: "A personal assistant on one Telegram bot and a coding agent on another" ข้อดีคือ crash domain แยกขาดกันจริง และติดตั้งเป็น service ถาวรได้ราย profile ด้วย hermes -p <name> gateway install (สร้าง systemd / LaunchAgent ให้)
Multiplex — หนึ่ง gateway หลาย profile
ถ้าไม่อยากเปลือง process ก็ opt-in รวมได้:
# ~/.hermes/config.yaml — หนึ่ง gateway process เสิร์ฟหลาย profile
gateway:
multiplex_profiles: true
profile_routes:
- platform: discord
guild_id: "111111"
profile: research-team # ทั้ง guild → profile นี้
- platform: discord
chat_id: "222222"
profile: ops # เจาะจงกว่า guild → ชนะ
- platform: telegram
thread_id: "333"
profile: finance # เจาะจงสุด: thread ชนะ chat ชนะ guild
# credentials ไม่ถูก union รวมกัน · session key แยก namespace ต่อ profile
# bot token ซ้ำข้าม profile = fail ตั้งแต่ startup
กติกา routing คือ most-specific-first (thread_id ชนะ chat_id ชนะ guild_id) และจุดที่ผมชอบในฐานะคนดู security: docs ยืนยันว่า credentials "are never unioned into a shared environment" — การรวม process ไม่ได้รวมสิทธิ์ และ token ซ้ำถูกดักตั้งแต่ start ไม่ใช่ตอนเกิดเหตุ
Multi-user บนแพลตฟอร์มเดียว
อีกแกนหนึ่งคือ bot ตัวเดียวเสิร์ฟทั้งทีม — คู่มือ team Telegram assistant วางแนวไว้ครบ: แต่ละคนได้ session สนทนาแยกของตัวเอง คุมการเข้าถึงได้สองทาง และมี home channel กลางไว้รับ scheduled output:
# ทางเลือก 1 — static allowlist
TELEGRAM_ALLOWED_USERS=1001,1002,1003
# ทางเลือก 2 — DM pairing codes (หมดอายุใน 1 ชั่วโมง)
hermes pairing approve telegram <CODE>
hermes pairing list
hermes pairing revoke telegram <USER>
# ช่องกลางของทีมสำหรับผลงานตาม schedule
TELEGRAM_HOME_CHANNEL=@team-agent-output # หรือพิมพ์ /sethome ในแชท
TERMINAL_ENV=docker สำหรับ multi-user เพื่อกันงาน execute แตะ host ตรง ๆ
9. Choosing the Right Layer — เลือกชั้นให้ถูกงาน
Nous มี คู่มือ delegation patterns อย่างเป็นทางการ ตั้งชื่อ pattern ไว้ห้าแบบ: Parallel Research, Code Review (audit ด้วยสายตาที่ context สดใหม่ — หลักการเดียวกับคำสั่ง /review ที่ spawn subagent รีวิว 10 ข้อความล่าสุดเป็น background), Compare Alternatives, Multi-File Refactoring ("split a large refactoring task across parallel subagents, each handling a different part of the codebase") และ Gather Then Analyze
rules of thumb ของคู่มือเดียวกัน: delegate งานที่ reasoning หนักหรือจะท่วม context ของ parent และงานอิสระที่ขนานกันได้ — แต่งาน mechanical ล้วนใช้ execute_code ตรง ๆ ถูกกว่า และที่สำคัญที่สุด: delegation "tied to the owning session and Hermes process" — งานที่ต้องรอดข้ามการปิด session ให้ไป cronjob หรือ terminal(background=True)
ผมสรุปเป็นบันไดตัดสินใจของตัวเองแบบนี้:
- จบใน session เดียว ขนานกันได้ →
delegate_task(เปิด worktree isolation ถ้าแตะ repo เดียวกัน) - ข้ามวัน ต้องมี audit และมนุษย์ตรวจ → Kanban board
- ทีมถาวรหลายบทบาท คุยกันเอง ข้ามเครื่อง → Bot Mode /
hermes peer/ A2A - หลายคนใช้เครื่องเดียว → profiles + multiplexed gateway + allowlists
- งานตามเวลา →
cronjob· เตือนใน session ที่เปิดอยู่ →/heartbeat
มุมมองส่วนตัวปิดท้าย ในฐานะคนที่ดูแลระบบ OpenClaw อยู่: สิ่งที่ Hermes เพิ่มเข้ามาในภาพ multi-agent ไม่ใช่ "ความฉลาด" ของ agent แต่ละตัว แต่คือ ความคงทนของโครงสร้างทีม — Kanban เปลี่ยน subagent ชั่วคราวให้เป็นแถวใน SQLite ที่มนุษย์ comment และ unblock ได้ทุกจุด นี่แหละคือชิ้นที่ pattern ยุคที่ผมเขียนบทความ agent teams ฝั่ง OpenClaw ยังต้องประกอบเอง ส่วนคำถามว่า memory ของทีมพวกนี้ถูกจัดการอย่างไร — บทความ #3 ของซีรีส์ว่าด้วยเรื่องนั้นโดยเฉพาะ
🎯 สิ่งสำคัญที่ต้องจำ
- delegate_task = fork-join subagent ที่ context สดใหม่ — มีแต่ summary สุดท้ายกลับเข้า parent (default: 3 children / 50 iterations / depth 1)
- background=true + steer/stop = ปล่อยงานแล้วไปต่อ (v0.17.0) และคุมกลางคันได้ (v0.21.0)
- Worktree isolation = กันชนกันด้วย git worktree ทั้งระดับ CLI (
hermes -w) และระดับ subagent — git-only, local-only, degrade เงียบ - Hermes Kanban = บอร์ด SQLite ถาวร + dispatcher ทุก 60s — named profiles, reclaim 4 ชม., มนุษย์ unblock ได้ทุกจุด, single-host โดย design
- Bot Mode = ทุก bot คือ profile — DM ผ่าน
message_agent, group chat จำกัด 3 รอบ / 10 ข้อความ, ข้ามเครื่องผ่าน relay หรือhermes peer - A2A v1.0 = wire protocol มาตรฐานสำหรับคุยข้าม harness (มากับ v0.20.0)
- cron vs heartbeat = ถาวร-แต่-isolated vs in-context-แต่ต้องมี process มีชีวิต
- ไม่มี role system = authorization มีแค่ allowlist / pairing — แยกสิทธิ์ด้วย profile และรัน multi-user ใน docker
Imagine you could clone a competent colleague at will — except every clone is born with an empty memory, finishes exactly one task, and then vanishes forever. How do you assemble a team out of creatures like that, one capable of work bigger than a single context window?
That is the central question of every multi-agent system, and it is the same question I explored in the OpenClaw Agent Teams post of my OpenClaw for Organizations series — a world where you compose teams out of sessions, subagents, and gateway message routing, with many of the patterns hand-built. I run an OpenClaw deployment in real work, and I am now examining Hermes Agent from Nous Research seriously — curious how the harness that has collected close to 240,000 GitHub stars answers this question differently.
The short answer: Hermes does not have a multi-agent feature. It has four distinct layers, each solving a different problem — fork-join subagents, a durable SQLite Kanban board, a society of bots that DM each other, and multi-profile serving for a whole team on one machine. Following Hermes 101, this post is the map of all four, with every detail drawn from the official docs and release notes as of v0.21.0 (August 31, 2026).
1. The Four Layers of Multi-Agent Hermes
Before the tour, the map. Most of the confusion I see around multi-agent Hermes comes from mixing layers that were never the same thing. Each layer has its own tool surface, its own lifespan, and its own problem to solve:
| Layer | Tool surface | Durability | Built for |
|---|---|---|---|
| 1. In-session subagents | delegate_task | Dies with the session | Fork-join parallel work summarized back into one conversation |
| 2. Kanban board | /kanban + kanban_* verbs | Durable (SQLite, survives restarts) | Multi-day work with an audit trail humans can step into |
| 3. Bot Mode + A2A | message_agent, hermes peer, A2A plugin | As long as the gateway/relay | Persistent named bots talking to each other, across machines and harnesses |
| 4. Multi-profile serving | Profiles + gateway routes | Service-level (systemd) | One machine serving many people and roles |
The axis to hold onto is that durability climbs as you go down the table — a subagent dies with its session, a Kanban task survives restarts, and a profile is a permanent service-level identity. The layers also compose rather than compete: one bot (layer 3) can spawn subagents (layer 1) to clear a card on the Kanban board (layer 2), on a machine that serves the whole team (layer 4).
💡 The thing most often mistaken for a fifth layer: Mixture of Agents (MoA) is not delegation. The docs classify it as a "virtual model provider" — several reference models act as parallel advisors (no tool schemas) while a single aggregator writes the response and emits the tool calls, configured viamoa.default_preset/moa.presets. MoA is many brains in one turn, not many agents doing many jobs.
2. delegate_task: Fork-Join Subagents with Fresh Contexts
The first layer is the delegate_task tool: the agent forks work off to a child with a conversation of its own. The delegation doc is explicit: "Each child gets a fresh conversation and works independently — only its final summary enters the parent's context." The child sees none of the parent's chat history, and the only thing that flows back is the final summary.
# Inside a session — the agent invokes this tool to fork work (pseudo-call)
delegate_task(
task="Read all of src/billing and summarize the edge cases, citing files"
)
# The child starts from an empty conversation + the project context file only
# The single thing that returns to the parent: the final summary
What flows in, what flows out
The one exception to the empty-memory rule is project context: when a workspace exists, Hermes embeds a context file into every subagent's system prompt, resolved along the priority chain .hermes.md → AGENTS.md → CLAUDE.md → .cursorrules.
The defaults worth knowing
These numbers have shifted across versions before (some release notes quote different iteration ceilings than the docs), so treat the current doc as the authority. As of September 1, 2026, the documented defaults are:
# ~/.hermes/config.yaml — delegation defaults (per the docs, v0.21.0)
delegation:
max_concurrent_children: 3 # env: DELEGATION_MAX_CONCURRENT_CHILDREN (floor 1, no ceiling)
max_iterations: 50 # per child
max_spawn_depth: 1 # flat by default — raise to 2+ for nested orchestration
worktree_isolation: false
orchestrator_enabled: true
child_timeout_seconds: 0 # 0 = no hard timeout (30s floor if enabled)
From single tool to a small team
Three capabilities promote this layer from "temp help" to "small team":
- Batch dispatch — pass
tasks=[...]and several jobs run in parallel, up tomax_concurrent_children - Nested orchestration — pass
role="orchestrator"so a child can spawn its own workers (raisemax_spawn_depthto 2+ first) - Cheaper workers than the parent — set
delegation.model/provider/base_urlseparately so children run on a lower-cost model
# Batch dispatch — three independent jobs, run in parallel
delegate_task(tasks=[
"Analyze this week's logs for recurring error clusters",
"Review PR #42 from a security angle only",
"Compare library A vs B for the ingest job"
])
# Nested orchestration — a child that manages its own sub-team
delegate_task(
task="Decompose the module refactor and manage a sub-team to completion",
role="orchestrator"
)
The boundaries are as deliberate as the powers: subagents cannot talk to each other. The doc states "No direct messaging between subagents … all coordination flows through parent's reasoning," and leaf subagents lose a whole set of tools: delegate_task, clarify, memory, send_message, cronjob. An orchestrator gets delegate_task back — bounded by spawn depth — but inherits the other blocks, and both roles keep execute_code.
While children run, you have full visibility: /agents shows a live tree of every child (API call counts, current tool, last activity), /stop cancels background delegations, and a live transcript per task sits at ~/.hermes/cache/delegation/live/<delegation_id>/task-<n>.log.
3. Background Delegation and Live Steering
Originally delegate_task was purely synchronous — the parent sat and waited. The first turning point was v0.17.0 (June 19, 2026), which added background=true: dispatch, get a handle back immediately, and keep working. Per the release notes, "The full result re-enters the conversation as a new turn the moment it finishes."
The second turning point arrived in v0.21.0 (August 31, 2026) under the headline "Steer your subagents while they run": delegate_task gained live orchestration — list running children, steer one mid-flight with a course correction, or stop it early and keep the partial result — plus optional JSON-schema validation on child outputs and per-delegation cost surfaced in results.
# v0.17.0+ — dispatch in the background, handle returned immediately
delegate_task(task="Crawl the whole doc set and build an index", background=true)
# v0.21.0+ — live orchestration while children are still running
delegate_task(action="list") # which children are running?
delegate_task(action="steer", subagent_id="abc123",
message="Skip legacy docs; focus on the v2 API only")
delegate_task(action="stop", subagent_id="abc123") # stop early, keep partial result
For background jobs that hang, an always-on stall monitor watches: quiet for more than 450 seconds (1,200 seconds while inside a tool call) counts as stalled, with a 120-second grace window to unwind, and structured metadata reporting the stall phase. The hard wall-clock cap (child_timeout_seconds) is opt-in and off by default — and background results persist in the profile's state.db across restarts.
One footnote that captures how fast this project moves: mid-June 2026 third-party writeups (MarkTechPost, kno2gether) described a separate six-tool "async_delegation" surface — delegate_task_async, check_task, steer_task, and friends. None of those names survive in the current official doc; the whole surface appears to have been consolidated into delegate_task itself between June and September. If an older tutorial names tools you cannot find, that is why.
4. Worktree Isolation: Parallel Work Without Collisions
The classic failure mode of several agents in one repo is editing the same files at once. Hermes answers this at two distinct levels that people routinely conflate — and the internet is genuinely confused about their history, so let me untangle both.
CLI-session level — hermes -w
The first level is running several Hermes processes in parallel terminals: the git worktrees doc promises that "every invocation gets its own worktree and branch automatically" — each hermes -w run gets a temporary git worktree under .worktrees/ with an isolated branch.
# CLI-level parallelism — one worktree per terminal, no collisions
hermes -w # every invocation gets its own worktree + branch
/worktree new my-experiment # creates .worktrees/my-experiment/ on branch hermes/my-experiment
# Open several terminals, run several Hermes processes in parallel
# Checkpoint history and /rollback are scoped per worktree
This feature is older than many articles claim: the request is issue #652, opened March 8, 2026, and it was documented by mid-March. The oft-repeated claim that it "shipped in v0.8.0" does not hold up against primary sources — v0.8.0 (April 2026) shipped only "aggressive worktree and branch cleanup." The mid-session /worktree command, which the docs describe as "Inspired by Copilot CLI," was added to the docs in mid-August 2026.
Subagent level — delegation.worktree_isolation
The second level is newer and finer-grained: flip delegation.worktree_isolation: true (default false) and every subagent from section 2 gets its own git worktree at <repo>/.worktrees/subagent-<id> on branch hermes-subagent/subagent-<id>, branched from current HEAD (the doc credits the inspiration to Muse Code's --subagent-worktree-isolation). Clean, commit-less worktrees are pruned automatically.
# ~/.hermes/config.yaml
delegation:
worktree_isolation: true # default: false
# Each child's result gains a "worktree" field:
# path: <repo>/.worktrees/subagent-<id>
# branch: hermes-subagent/subagent-<id>
# commits ahead of base / dirty / pruned
worktree field in every child's result.
5. Hermes Kanban: A Durable Task Board Your Agents Share
Everything in the previous two sections shares one weakness: it dies with the session. Close the process and the sub-team evaporates. That is the gap Hermes Kanban was built to close — first shipped in v0.13.0 (May 7, 2026) under a headline that names the problem precisely: "Multi-agent Kanban — delegate to an AI team that actually finishes."
The heart is a single SQLite database at ~/.hermes/kanban.db. The docs compress the philosophy into one line: "Every task is a row … every handoff is a row anyone can read and write." Work is not state floating in some agent's head — it is rows any profile can inspect.
The dispatcher mechanics
A dispatcher embedded in the gateway (kanban.dispatch_in_gateway: true) wakes every 60 seconds to (1) reclaim tasks whose worker heartbeat has been silent for over 4 hours, (2) promote tasks whose dependencies have cleared, and (3) atomically claim ready tasks and spawn workers as full OS processes: hermes -p <assignee> chat -q <prompt>, with injected KANBAN_GUIDANCE and environment variables like HERMES_KANBAN_TASK, HERMES_KANBAN_DB, HERMES_KANBAN_WORKSPACE, HERMES_PROFILE, and HERMES_TENANT so each worker knows its own context.
# ~/.hermes/config.yaml — the main Kanban knobs (documented defaults)
kanban:
dispatch_in_gateway: true
dispatch_interval_seconds: 60 # dispatcher tick
dispatch_stale_timeout_seconds: 14400 # 4h — reclaim tasks from silent workers
failure_limit: 2 # per-task circuit breaker
max_in_progress: ~ # default: unlimited board-wide
max_in_progress_per_profile: ~
auto_promote_children: true
The protocol workers must honor
The board's reliability comes from a strict protocol: a worker must end its run with exactly one of kanban_complete, kanban_request_review, or kanban_block. Exit without one and the task is classified crashed / gave_up / timed_out, with up to 2 automatic nudges and a bounded retry budget (default: 3 consecutive protocol violations and you are out). The release notes summarize the machinery as "Heartbeats, reclaim, zombie detection, retry budgets, and a hallucination gate keep the team honest."
Kanban-side orchestrators work purely through creation verbs — decomposing goals into child cards and wiring dependencies, with no implementation tools in hand:
# An orchestrator fans a goal out into child cards, wired with parents
kanban_create(title="Collect the v0.21.0 changelog", assignee="researcher")
kanban_create(title="Draft the internal announcement from it",
assignee="writer",
parents=["<task-id-of-the-first-card>"])
# Child cards automatically receive "## Parent task results"
# (the parent's summary + metadata) in their worker context
Each card picks one of three workspace kinds: worktree (a git worktree at .worktrees/<id>/, preserved on completion), scratch (deleted on completion), or dir:<path> (shared, preserved). And goal-mode cards (--goal / goal_mode=True with --goal-max-turns) run a Ralph-style loop confined to a single card, an auxiliary judge checking output against acceptance criteria every turn — when the budget runs out before the criteria pass, the card blocks for human review instead of failing silently.
Kanban vs delegate_task — the official comparison
The docs compare the two layers head-on; here is the substance of that table:
| delegate_task | Hermes Kanban | |
|---|---|---|
| Model | fork → join RPC | durable queue + state machine |
| Worker identity | anonymous, non-resumable | named profile + persistent memory |
| Recovery | dies with the session | block / unblock / re-run |
| Human in the loop | — | comment / unblock at any point |
| Audit trail | — | SQLite records every handoff |
| Coordination | through the parent only | peer — any profile reads/writes any task |
The docs also codify 8 collaboration patterns — fan-out, pipeline, voting/quorum, long-running journal, human-in-the-loop, @mention, thread-scoped workspace, and fleet farming (the docs' example: one profile running 50 social accounts) — plus soft multi-tenancy via --tenant: "One specialist fleet can serve multiple businesses (--tenant business-a) with data isolation," each tenant getting its own workspace path and memory key prefix.
You can even run the board from your phone: every verb is reachable as /kanban from any gateway platform (Telegram, Discord, Slack, WhatsApp, Signal, Matrix, and more), and the originating chat auto-subscribes to the task's terminal events — choose plain notify, notify+wake, or wake so the agent rouses itself to act when a task completes, blocks, or crashes.
6. Bot Mode: Named Agents, Group Chats, and Peer DMs
The third layer is what makes "a society of bots" in this post's title literal rather than a metaphor. Bot Mode began life as a one-day public beta plugin by Teknium (a Nous co-founder), was — per MarkTechPost's reporting — bundled default-on in Hermes Desktop around v0.20.3 in mid-August, and was formalized in v0.21.0 "The Pantheon Release" (August 31, 2026), which describes it as "a society of named agents with their own faces and group chats, where your bots talk to each other — and to you — like a team, not a toolbox."
A Bot is a Profile
The one sentence to remember: a Bot IS a Hermes profile — isolated config, memory, skills, credentials, and chat history under ~/.hermes/profiles/<name>/. You can pin a model/provider per bot, write its persona in a SOUL.md, and enable skills, toolsets, and MCP servers per bot. Everything has CLI parity: hermes -p <bot> chat, hermes profile create, hermes cron list. A bot's recurring "routines" are plain Hermes cron jobs namespaced as [bot:<name>] <routine>.
message_agent and group chats
Bots DM each other through the message_agent tool (gated by agent.bot_mode_protocol: true, injected automatically in canonical Bot Chats): delivery is fire-and-forget, with the reply arriving as a background completion notification. A failed delivery retries at most once, with typed failure reasons such as provider_auth_or_access, provider_quota_limit, and context_overflow.
# One bot messaging another
message_agent(target="researcher",
message="Give me the 5 latest bullets on A2A adoption")
# Fire-and-forget: the reply arrives as a background completion notification
# On failure: at most 1 retry, with a typed failure reason
Group chats are engineered against flooding: each send triggers at most 3 serial rounds of member turns, capped at 10 messages, and a bot "replies only when it has something new to add and passes otherwise" — with @user always available to escalate to a human. Rooms can span machines via the Desktop relay.
Peers and A2A — across machines, across harnesses
No Desktop? Gateways can talk to each other directly over the api_server platform with a strong key:
# Gateway-to-gateway, no Desktop required
hermes peer add spark --url http://spark.lan:8377 --key <API_SERVER_KEY>
hermes peer dm spark "Summarize the latest pipeline status for me"
hermes peer run spark "deploy staging" --idempotency-key deploy-20260901
# Peer keys live in ~/.hermes/.env as HERMES_PEER_<NAME>_KEY
# URLs sit under bot_peers in config.yaml
And for the world beyond Hermes: v0.20.0 "The Herald Release" (August 3, 2026) bundled an A2A v1.0 plugin — closing issue #514, which the release notes call "one of the oldest open feature requests in the repo" — so Hermes can "discover, talk to, and be driven by other A2A-compatible agents," alongside signed (HMAC) outbound lifecycle webhooks. Heterogeneous multi-agent systems that mix harnesses finally get a standard wire protocol to meet on.
7. Always-On Work: cron Jobs vs Session Heartbeats
A good team does not only work when commanded. Hermes has two "wake yourself up" mechanisms with exactly opposite philosophies — and picking the wrong one is the classic beginner's bug.
cronjob — durable but isolated
The cronjob tool (actions: create / list / update / pause / resume / run / remove) accepts schedules in four dialects, and the gateway daemon ticks the scheduler every 60 seconds:
# The schedule forms cronjob accepts — pick one
cronjob(action="create", schedule="in 30m", prompt="...") # relative one-shot
cronjob(action="create", schedule="every 2h", prompt="...") # interval
cronjob(action="create", schedule="weekdays at 9am", prompt="...") # natural language
cronjob(action="create", schedule="0 9 * * *", prompt="...") # cron expression
Every run happens in a fresh, isolated session — no chat history comes along. And to stop an agent from scheduling itself into infinity, cron-management tools are disabled inside cron executions (override: cron.allow_agent_scheduling, default false), with concurrency capped by cron.max_parallel_jobs.
Isolated does not mean amnesiac — two mechanisms carry memory across runs:
- continuity=True — injects the job's own most recent output into each subsequent run (ideal for scouts that must deduplicate what they already reported)
- context_from="<job_id>" — chains jobs: Job A's latest output becomes context for Job B
# A recurring scout that remembers its last round and posts to a team thread
cronjob(action="create",
schedule="every 6h",
prompt="Scan for new multi-agent papers; reply [SILENT] if nothing new",
continuity=True, # remembers last output — no repeats
deliver="telegram:-100123456:42") # chat_id:thread_id addressing
Delivery is flexible: deliver accepts origin (the default on messaging platforms), local, telegram / discord / slack / email / sms, all, and bot-chat — and a final response of [SILENT] suppresses delivery entirely. Pure-script jobs run with no_agent=True, no LLM invoked at all. And v0.21.0 just fixed the layer's oldest weakness under the headline "Cron jobs that remember": cron agents now load and update persistent memory, and get a durable notepad scratchpad of their own.
/heartbeat — in-context but mortal
The opposite pole is the session heartbeat: a prompt that re-enters the current session on a cadence, with the full conversation history in view — but requiring a live process to come home to.
/heartbeat every 10m Check the Kanban board — any cards stuck in blocked?
# Minimum 60s · runs only while idle, never interrupts active processing
# Missed ticks are coalesced into one
# State persists in SessionDB.state_meta under heartbeat:<session_id>
| cronjob | /heartbeat | |
|---|---|---|
| Context | fresh session, no chat history | full conversation history |
| Durability | survives restarts (gateway daemon) | needs a live process |
| Cadence | a real schedule | idle-only, coalesced |
| Built for | long-lived recurring work | self-reminders in an open session |
8. Serving a Whole Team: Profiles, Gateways, Allowlists
The first three layers are agents working with agents. The last layer answers the question organizations ask me most often: can one machine serve many people, in many roles? Hermes' answer is yes — by composing profiles, gateways, and allowlists.
One profile per role
The default is one gateway process per profile — the docs' example: "A personal assistant on one Telegram bot and a coding agent on another." The payoff is hard crash-domain isolation, and each profile installs as a permanent service with hermes -p <name> gateway install (generating the systemd unit or LaunchAgent for you).
Multiplexing — one gateway, many profiles
If you would rather not spend a process per role, opt in to sharing:
# ~/.hermes/config.yaml — one gateway process serving several profiles
gateway:
multiplex_profiles: true
profile_routes:
- platform: discord
guild_id: "111111"
profile: research-team # the whole guild → this profile
- platform: discord
chat_id: "222222"
profile: ops # more specific than guild → wins
- platform: telegram
thread_id: "333"
profile: finance # most specific: thread beats chat beats guild
# Credentials are never unioned · session keys are namespaced per profile
# A duplicate bot token across profiles fails at startup
Routing is most-specific-first (thread_id beats chat_id beats guild_id). And the detail I like most with my security hat on: the docs guarantee credentials "are never unioned into a shared environment" — sharing the process does not merge the privileges, and duplicate tokens are caught at startup, not at incident time.
Multi-user on a single platform
The other axis is one bot serving a whole team. The team Telegram assistant guide lays out the pattern: each person gets their own conversation session, access is controlled one of two ways, and a shared home channel receives scheduled output:
# Option 1 — static allowlist
TELEGRAM_ALLOWED_USERS=1001,1002,1003
# Option 2 — DM pairing codes (expire in 1 hour)
hermes pairing approve telegram <CODE>
hermes pairing list
hermes pairing revoke telegram <USER>
# The team's shared channel for scheduled output
TELEGRAM_HOME_CHANNEL=@team-agent-output # or type /sethome in the chat
TERMINAL_ENV=docker for multi-user setups so executed work cannot touch the host directly.
9. Choosing the Right Layer
Nous publishes an official delegation patterns guide naming five patterns: Parallel Research, Code Review (an audit with fresh-context eyes — the same principle behind the /review command, which spawns a background subagent over the last 10 messages), Compare Alternatives, Multi-File Refactoring ("split a large refactoring task across parallel subagents, each handling a different part of the codebase"), and Gather Then Analyze.
The same guide's rules of thumb: delegate reasoning-heavy subtasks and anything that would flood the parent's context, plus independent parallel workstreams — but purely mechanical work is cheaper as a direct execute_code call. Most important of all: delegation is "tied to the owning session and Hermes process" — work that must survive a closed session belongs in cronjob or terminal(background=True).
My own decision ladder condenses to this:
- Fits in one session, parallelizable →
delegate_task(turn on worktree isolation if children touch the same repo) - Spans days, needs an audit trail and human review → the Kanban board
- A persistent multi-role team that talks to itself, across machines → Bot Mode /
hermes peer/ A2A - Many people on one machine → profiles + a multiplexed gateway + allowlists
- Work on a clock →
cronjob· self-reminders in an open session →/heartbeat
A closing observation, as someone who operates an OpenClaw deployment: what Hermes adds to the multi-agent picture is not smarter individual agents but durability of team structure. Kanban turns the ephemeral subagent into a row in SQLite that a human can comment on and unblock at any point — precisely the piece that the patterns I described in my OpenClaw agent-teams post still had to be assembled by hand. As for how these teams manage what they remember — that is the entire subject of post #3 in this series.
🎯 Key Takeaways
- delegate_task = fork-join subagents with fresh contexts — only the final summary re-enters the parent (defaults: 3 children / 50 iterations / depth 1)
- background=true + steer/stop = dispatch and keep going (v0.17.0), course-correct mid-flight (v0.21.0)
- Worktree isolation = collision-proofing via git worktrees at both the CLI level (
hermes -w) and the subagent level — git-only, local-only, degrades silently - Hermes Kanban = a durable SQLite board + a 60s dispatcher — named profiles, 4h reclaim, humans can unblock at any point, single-host by design
- Bot Mode = every bot is a profile — DMs via
message_agent, group chats capped at 3 rounds / 10 messages, cross-machine via the relay orhermes peer - A2A v1.0 = the standard wire protocol for talking across harnesses (since v0.20.0)
- cron vs heartbeat = durable-but-isolated vs in-context-but-mortal
- No role system = authorization is allowlists / pairing only — separate privileges with profiles, and run multi-user inside docker