Back to articles
AI Agents

Building an army of AI agents with Hermes: orchestration, delegation and kanban

Set up an organization of 48 AI agents on Hermes: orchestrator, delegation kanban, autonomous cron and real pitfalls (s6, conflicts, minimal environment).

Daryl Ngako

Building an army of AI agents with Hermes: orchestration, delegation and kanban

A single AI agent is already powerful. But when you ask him for a complex task (to monitor, produce a report, launch a campaign), he does everything himself, serially, and ends up running out of steam on the big issues.

The next step is multi-agent orchestration: a conductor who breaks down an objective into tasks, distributes them to specialists, and coordinates everything. In this guide, I show you how I set up a real organization of 48 agents on Hermes, with an orchestrator, sub-teams (marketing, dev, sales, R&D) and a shared kanban board which manages the delegation.

You will understand the Hermes profiles system, how to expose an orchestrator in a chat interface, how the delegation kanban works, and how to automate all of this with a cron. With the real technical pitfalls that I had to resolve: the s6 supervisor limit, bot conflicts, and the minimal environment which breaks delegation.

If you don't yet have Hermes installed on your VPS, start with my previous article on Docker deployment. Here, we build on top.

What is a profile in Hermes?

A Hermes profile is an isolated instance of the agent, with its own configuration: its model, its tools, its authentication, its personality, its sessions. Think of it like different employees in a company: each has their own role, skills and office, but they share the same premises.

You list your profiles with:

docker exec -it hermes-api hermes profile list

In my installation, it displays 48 profiles organized in hierarchy:

  • orchestrator: the conductor
  • Management: ceo, cfo, cto, cmo, coo, cro, crdo
  • Platform: ops, coder, wikicurator (+ their sub-agents)
  • Marketing: mkt-x, mkt-li, reddit (+ analysts, editors, publishers)
  • Growth: SEO and its specialists (technical, content, offpage), geo-specialist
  • Sales: sales, sales-research, sales-copy, sales-crm
  • R&D: rnd, rnd-research, rnd-proto, rnd-eval
  • Quality: critical (the adversary verifier)

Each profile runs on a model adapted to its role: the coordination roles use an advanced reasoning model (Claude Sonnet type), the execution roles a faster and lighter model.

To view the details of a profile:

docker exec hermes-api hermes profile show orchestrator

You obtain its path, its model, the number of skills, the state of its gateway and the presence of a SOUL.md file.

What is SOUL.md (and why is it the orchestrator's brain)?

A profile's SOUL.md defines its personality and behavior. For the orchestrator, it is the most important document in the system: it contains the map of the entire organization and the routing rules.

Here is an extract from my orchestrator's SOUL.md:

You are the Orchestrator of an AI agent organization. You turn a high-level
objective into an explicit plan: decompose it into tasks, assign each to the
best-fit specialist (match by their role description), sequence dependencies,
and run it on the kanban.

You insert human-approval gates before any action that is irreversible, costly,
externally visible, or touches production. You do NOT do specialists' work
yourself.

This file specifies several fundamental things:

  • Routing: which specialist to entrust which type of task to.
  • Workflows: for marketing, for example, analyst (collection) → editor (draft) → critic (review) → publisher (publication).
  • Human approval gates: before any irreversible, costly or public action, the orchestrator stops and requests validation.
  • Persistence in the vault: each agent places their deliverables in a shared folder.

Key point: two profiles can run on the same model but have different SOUL.md, therefore radically different behaviors. The SOUL is what turns a generic LLM into a specialist.

What is delegation kanban?

The Hermes kanban is a task table shared between all profiles, stored in an SQLite database (kanban.db). It is the driving force of the entire organization.

The principle: the orchestrator receives an objective, decomposes it into tasks, places them on the board, and each task is executed by the right profile in an isolated workspace. Tasks can depend on each other, be claimed atomically, and go through stages (triage, todo, in progress, done).

You list the board's tasks with:

docker exec hermes-api hermes kanban list

In my system, after several runs, the board displayed dozens of tasks completed by the right agents:

✓ done  researcher      Map the wiki concepts
✓ done  critic          Verify swarm outputs
✓ done  wikicurator     Synthesize swarm outputs
✓ done  mkt-x-analyst   Collect sourced AI intelligence from X
✓ done  cto             Technology brief (ops, dev, technical docs)

This is proof that delegation works: a single objective (for example “produce an executive report”) mobilized all C-levels, each producing their brief.

The important point about the shared board

The kanban is unique and shared between all profiles and all containers. Whether you create a task from any profile, it always appears on the same board. What changes depending on the configuration is who decomposes and executes the task, not where it appears.

In the orchestration settings (accessible via the dashboard), you define:

  • The Orchestrator Profile: which agent plays the conductor.
  • The Default Assignee: to whom the unassigned tasks go.
  • Auto-decompose: if the orchestrator automatically divides new triage tasks.

How to expose the orchestrator in a chat interface

You want to be able to speak to your orchestrator in natural language, not just via kanban. To do this, you must launch your API server and plug it into Open WebUI.

First important discovery: in Hermes, you cannot run two gateways in the same container. The image uses an s6-overlay supervisor which prohibits it. If you try to launch a second gateway, you get:

ERROR gateway.run: Another gateway instance (PID 1) started during our
startup. Exiting to avoid double-running.

The clean solution: a separate container for the orchestrator. It shares the same /root/.hermes (so the same profiles, the same kanban, the same auth), but runs in isolation on the orchestrator profile.

The orchestrator startup script

start-orchestrator.sh
#!/bin/sh
umask 0000
hermes profile use orchestrator
exec hermes gateway run --no-supervise

Note the hermes profile use orchestrator carefully. I first tried passing the profile via an environment variable HERMES_PROFILE, but it is ignored by Hermes. The only reliable method for targeting a profile is hermes profile use.

The docker-compose orchestrator

docker-compose.orchestrator.yml
services:
  hermes-orchestrator:
    build: .
    container_name: hermes-orchestrator
    restart: unless-stopped
    expose:
      - "8642"
    environment:
      - DOCKER_HOST=tcp://docker-socket-proxy:2375
    volumes:
      - /home/user/hermes-proxy/auth:/root/.hermes
      - /home/user/hermes-proxy/vault:/root/vault
    networks:
      - n8nnet

networks:
  n8nnet:
    external: true
    name: my-docker-network

The DOCKER_HOST points to a docker-socket-proxy. This is a good security practice: instead of mounting the raw Docker socket (which gives root access to the host), we go through a proxy which filters authorized commands. The orchestrator needs it to create the sandbox containers for its subagents.

Once the container is launched, check that it exposes the correct profile:

docker exec hermes-orchestrator python -c "import urllib.request; r=urllib.request.Request('http://localhost:8642/v1/models', headers={'Authorization':'Bearer TA_CLE_API'}); print(urllib.request.urlopen(r).read().decode())"

You should see "id": "orchestrator". Then you add it in Open WebUI as a new connection (http://hermes-orchestrator:8642/v1), and it appears in the menu.

The trap that breaks everything: the minimal environment

This is the mistake that kept me going in circles the longest. My orchestrator container responded in chat, but as soon as it tried to delegate, everything failed:

ERROR tools.terminal_tool: Docker executable not found in PATH
WARNING agent.tool_executor: Tool web_search returned error: Feature
'search.firecrawl' unavailable

The cause: I had built the orchestrator container with a minimal Dockerfile, whereas to delegate it needs the same complete environment as the main container. It was missing the Docker binary (to create sandboxes) and certain Python dependencies (for web search).

The lesson: An orchestrating agent needs full execution capabilities. Align your orchestrator's Dockerfile with that of your main container, with the static Docker binary and full dependencies:

Dockerfile
RUN curl -fsSL https://download.docker.com/linux/static/stable/x86_64/docker-27.3.1.tgz \
    | tar -xz -C /usr/local/bin --strip-components=1 docker/docker
RUN pip install --no-cache-dir pipx && \
    pipx install hermes-agent && \
    pipx inject hermes-agent aiohttp fastapi uvicorn ptyprocess "mcp>=1.27" httpx-sse langfuse

After this fix, delegation became unblocked. swarm: tasks started appearing on the kanban, executed by researcher, wikicurator, seo-analyst and others.

Automate delegation with a cron

The true power of an army of agents is that it works without you. Hermes has a native cron system for scheduling recurring tasks.

Create a daily monitoring job:

docker exec hermes-orchestrator hermes cron create \
  --name "veille-dev-web" \
  --profile orchestrator \
  --deliver local \
  "0 7 * * *" \
  "Autonomous task: do not wait for approval or ask for clarification. Search the web for recent developments in web development and AI. Write a dated page in /root/vault/wiki/. Update index.md and log.md."

Several details matter here:

  • "0 7 * * *" is in standard cron format. Pay attention to the time zone: your container is probably in UTC. For 8 a.m. local time in UTC+1, you program 7 a.m. UTC.
  • --deliver local deposits the result in the vault rather than reporting it elsewhere.
  • Ultra-directive instructions are the key to success. This is my biggest lesson about cron.

Why the instructions must be directive

On my first tries, the orchestrator created "Clarify the task request" tasks and remained stuck. The reason: in standalone cron mode, there is no one to respond to requests for clarification. His SOUL.md tells him to insert human gates, so he stops waiting for a response that never comes.

The solution: instructions that cut short any hesitation. The phrases “wait for no validation, ask for no clarification, execute directly” prevent it from blocking. With self-explanatory numbered steps and a precise file path, it knows exactly what to do.

Check that your scheduler is running:

docker exec hermes-orchestrator hermes cron status

You should see ✓ Gateway is running — cron jobs will fire automatically.

To test without waiting for the programmed time:

docker exec hermes-orchestrator hermes cron run veille-dev-web

After a few minutes, a fresh page appears in the vault. The complete chain worked: cron → orchestrator → web search → synthesis → write to vault.

Two operating modes: solo vs delegation

In use, you have two ways to make your orchestrator work, with different compromises:

ModeDescriptionAdvantageDisadvantage
SoloThe orchestrator does everything himselfFast, reliableNo division of labor
DelegationHe distributes to specialistsRich and structured workSlower, more expensive in quota

For simple standby, solo mode is sufficient and it is more robust. For a complex deliverable (multi-domain report, campaign), delegation to specialists gives a much richer result, but consumes significantly more.

Beware of cost: a single request to the orchestrator can trigger a cascade of model calls (the orchestrator, then each sub-agent, then the critic). Monitor your consumption, especially on profiles using an advanced reasoning model.

The pitfalls of cohabitation on a shared system

When multiple containers share the same /root/.hermes, some resources conflict. The most common case: the messaging bot.

If two containers read the same bot token (Telegram for example), they compete for the same connection and you obtain:

Conflict: terminated by other getUpdates request; make sure that only one
bot instance is running

This is a limitation of the messaging platform, not of Hermes: a bot can only have one active connection. Two clean solutions:

  • Only one container manages the bot: you deactivate messaging on the second.
  • A second dedicated bot: you create a new bot (different token) for the orchestrator container.

As each profile reads its own .env file, you can give a different token to the orchestrator profile without changing the default profile. The modification is surgical: a single line in the .env of the profile concerned.

Best practice: if you work with several people on the same system, agree on who manages what (the bot, shared crons, profile configs). On a shared architecture, two people who modify the same config quickly neutralize each other.

Summary

Here are the essential steps to set up your multi-agent orchestration:

ActionKey command
List profileshermes profile list
View a profilehermes profile show orchestrator
See kanbanhermes kanban list
Target a profilehermes profile use orchestrator
Create a cronhermes cron create --name ... --profile ...
Test a cronhermes cron run [nom]
Check the schedulerhermes cron status

And the technical lessons to remember:

  • Only one gateway per container (s6 limit): uses a separate container for the orchestrator.
  • HERMES_PROFILE does not work: uses hermes profile use.
  • The orchestrator needs the complete environment (Docker + dependencies) to delegate.
  • In cron mode, a directive instruction avoids blockages on clarification.
  • The kanban is shared: only one board, but which is broken down depends on the settings.

You now have an organization of AI agents who break down your objectives, delegate to specialists, and work independently on a schedule. It's a change of scale compared to a single agent: you no longer give tasks, you give objectives, and the organization takes care of the rest.

The next logical step? Refine the descriptions of each profile to improve the orchestrator's routing, and create dedicated Kanban boards per project. But that’s for a future article.

It's up to you to build your army!