Learn Hermes AI Agent - Multi-agent Coordination
Episode 17 of 23

Learn Hermes AI Agent - Multi-agent Coordination

This episode turns one agent into a team: learning communication patterns between agents, building an orchestrator that delegates subtasks to workers and merges the results, and devising arbitration and consistency strategies so many agents can work simultaneously.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Introduction

In episode 16 you expanded the agent's capabilities with custom actions, domain-specific tools, and plugins packaged as modules. Now imagine you have not one but several agents with different expertise: one great at research, one great at data analysis, and another great at communication. The question: how do they work together without tripping each other up?

Here is the roadmap for this episode: recognizing when multi-agent is actually the right call, understanding communication patterns between agents, building an orchestrator that delegates subtasks and merges results, and then devising consistency and arbitration strategies when agent results collide.

When Multi-agent Is Actually the Right Call

One agent has limits: a bounded context window, a ballooning tool set, and all decisions passing through one brain. When a task starts requiring a lot of knowledge at once — compare prices from three sources, analyze large logs, then write the summary — a single agent will be slow and easily "lost" in the middle of a bursting context.

Multi-agent splits the load: each worker has a small context and focused tools, and the orchestrator only manages the traffic. But this is not a free solution. Every agent is a token cost, and coordination adds latency. The practical rule: start with one agent, move to multi-agent only when there is a clear bottleneck — a context window running out, too many tools of one kind, or one agent overwhelmed by parallel tasks.

Communication Patterns Between Agents

There are three common communication patterns, and each suits a different situation:

  • Direct channel — agent A sends a message directly to agent B. Suited for one-to-one delegation where the direction is already clear.
  • Message bus — agents publish events to a topic, and anyone interested may subscribe. Suited for fan-out: one event read by many agents.
  • Shared memory / blackboard — several agents write and read the same state. Powerful but risky, because consistency problems live here.

The Hermes bus is configured through channel declarations:

channels:
  orders:
    type: topic
    durability: 24h
  support:
    type: direct

Use direct for results that must return to the sender, and topics for events relevant to many agents at once. Shared memory is the most efficient for shared state, but save it for the very end of this episode — its consistency needs special attention.

Subtask Delegation: Orchestrator and Workers

The most widely used pattern is orchestrator-worker: one orchestrator agent breaks a big task into subtasks, delegates each subtask to a competent worker, waits for results, and merges them. The orchestrator does not need to know the execution details — it only makes sure everything runs and the results are complete.

orchestrator.ts - splitting tasks to workers
import { HermesAgent } from "@hermes/sdk";
 
const orchestrator = new HermesAgent({ profile: "./profiles/orchestrator.ts" });
 
async function runBatch(task, subtasks) {
  const results = await Promise.all(
    subtasks.map((sub) =>
      orchestrator.spawn({
        agent: sub.agent,
        task: sub.task,
        replyTo: "orchestrator",
      }),
    ),
  );
  return orchestrator.merge(results);
}

The flow: the orchestrator breaks the task into a list of subtasks, each worker is spawned with its task and replyTo as the reply address, results are collected in parallel, and then merge assembles them into one coherent answer. Because each worker has its own context, the model is not overwhelmed by the combined context. In the CLI, manual spawning is available via hermes agent spawn to test one worker before wiring it into a pipeline.

Maintaining Consistency Across Many Agents

Once several agents touch the same data, consistency becomes a problem. Two workers editing the same record in parallel can overwrite each other. Three of the most practical strategies:

  • Single writer per resource — for each resource (for example, one order), only one worker may write. The orchestrator assigns ownership up front.
  • Idempotent tool calls — make tools safe to call many times with the same result, complete with an idempotency key, so retries or duplicates do not cause double effects.
  • Versioned shared state — if a blackboard is used, every write carries a version; a worker reading an old version knows the data has changed and must fetch it again.
state.ts - writing with a version
export async function writeOrder(store, orderId, patch) {
  const current = await store.get(orderId);
  if (patch.baseVersion !== current.version) {
    throw new Error("stale write: versi sudah berubah");
  }
  return store.set(orderId, {
    ...current,
    ...patch.data,
    version: current.version + 1,
  });
}

This pattern rejects "stale" writes up front instead of silently overwriting another worker's data. If conflicts still happen, they must be handled explicitly — and that is where arbitration comes in.

Arbitrating When Results Clash

When several agents give different answers to the same question, you need rules to pick one. Arbitration is that mechanism. The most common strategies: pick the one with the highest confidence, or ask for a majority — and if none is confident enough, escalate to a human rather than force it.

arbitrate.ts - choosing the best answer
export function arbitrate(results) {
  const ranked = [...results].sort((a, b) => b.confidence - a.confidence);
  const best = ranked[0];
 
  if (best.confidence < 0.6) {
    return { winner: null, escalate: true };
  }
  return { winner: best, escalate: false };
}

Arbitration rules are best declared, not hard-coded: the configuration contains the strategy (confidence, majority, priority), the threshold that triggers escalation, and where results go up if there is no winner. Consistency maintained from the moment of state writing, plus clear arbitration at the point of collision, are the two sides that make an agent team work like one system — not five applications that happen to share a database.

Info

Do not let arbitration create an agent that never makes a wrong choice. Log every arbitration decision to the observability logs (episode 7) and compare them with the final outcome; that way your arbitration rules keep improving from data, not from feelings.

Conclusion

Episode 17 assembled your agents into a team. You know when multi-agent is worth using, choose a communication pattern between direct channel, message bus, and shared memory, build an orchestrator that splits tasks and delegates subtasks to workers, then maintain consistency with single writer and idempotency and resolve result clashes through confidence-based arbitration.

Key takeaways:

  • Multi-agent is not just for show — use it when a single agent's context window or tool set has become a bottleneck.
  • Direct for one-to-one delegation, topics for fan-out, shared memory for shared state.
  • The orchestrator splits, delegates, and merges; workers keep their contexts small.
  • Consistency is maintained with a single writer per resource, idempotent tool calls, and versions on shared state.
  • Arbitration needs a declared strategy and logs to be evaluated.

In the next episode 18 we give this agent team self-awareness: Adaptive Behavior & Reflection — a reflective loop for evaluating its own results, monitoring confidence and uncertainty, and changing strategy based on feedback. See you there!

Learn Hermes AI Agent - Multi-agent Coordination | Learn Hermes AI Agent