Hermes Agent's delegate_task tool lets you spawn subagents that work in parallel — one researching while another codes, a third running tests. But with great parallelism comes sprawl: each subagent runs in the same host environment, and shared dependencies, conflicting processes, or stray file writes can create subtle bugs. This guide shows how to isolate subagents in Docker containers, coordinate shared state through PostgreSQL, and manage artifacts with Git — a production pattern used by teams running multi-agent workflows at scale.
By default, Hermes subagents inherit the parent's terminal session and working directory. Delegate three subagents in parallel and they all see the same filesystem:
$ ls /root/yiman_workspace/
Dockerfile
agent-a-output/
agent-b-output/
README.md # Wait — which agent wrote this?
Worse, conflicting Python dependencies or background processes from one subagent can crash another. The solution is per-subagent Docker containers — each subagent gets its own filesystem, process namespace, and dependency set. The parent Hermes Agent remains the orchestrator, communicating with subagents through a shared PostgreSQL state store and Git for artifact exchange.
The pattern has three layers:
delegate_task and routes work┌──────────────────────────────────────┐
│ Parent Hermes Agent Session │
│ (orchestrator — breaks down work) │
└──────┬───────────┬───────────┬───────┘
│ │ │
delegate_task delegate_task delegate_task
│ │ │
┌────▼────┐ ┌───▼────┐ ┌───▼────┐
│Agent A │ │Agent B │ │Agent C │
│Docker │ │Docker │ │Docker │
│Container│ │Container│ │Container│
└────┬────┘ └───┬────┘ └───┬────┘
│ │ │
└───────────┼───────────┘
│
┌─────────▼─────────┐
│ PostgreSQL │
│ (task state, locks)│
└───────────────────┘
Start with the environment. Each subagent container runs on the same Docker host and shares a bridge network for PostgreSQL access:
$ docker --version
Docker version 28.5.1, build e180ab8
$ docker network create agent-bridge
c4e5d6f7a8b9c0d1e2f3a4b5c6d7e8f9
$ docker network ls | grep agent
c4e5d6f7a8b9 agent-bridge bridge local
The subagent Dockerfile includes Hermes Agent, Git, and the PostgreSQL client:
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y \
python3 python3-pip python3-venv \
git curl ca-certificates postgresql-client \
&& rm -rf /var/lib/apt/lists/*
# Install Hermes Agent
RUN python3 -m venv /opt/hermes-venv && \
/opt/hermes-venv/bin/pip install hermes-agent
# Install Playwright for browser automation
RUN /opt/hermes-venv/bin/playwright install-deps && \
/opt/hermes-venv/bin/playwright install
# Hermes configuration
ENV HERMES_HOME=/subagent/.hermes
ENV PATH="/opt/hermes-venv/bin:$PATH"
WORKDIR /workspace
# Entrypoint: subagent runs as a one-shot hermes process
ENTRYPOINT ["hermes", "chat", "-q"]
Build the image once, then spawn subagent containers on demand:
$ docker build -t hermes-subagent:latest -f Dockerfile.subagent .
$ docker run -d --name subagent-build --network agent-bridge \
-e PGHOST=postgres -e PGDATABASE=agent_state \
-e HERMES_API_KEY=${HERMES_API_KEY} \
--cpus=2 --memory=4g \
hermes-subagent:latest "Run tests for ~/project and report results"
--cpus and --memory, three parallel subagents can saturate the host. Pin each subagent to 2 CPU cores and 4 GB RAM — the orchestrator can spawn more after current subagents complete.Subagents need to know what other subagents are doing. A shared PostgreSQL table provides a lightweight coordination layer:
$ docker run -d --name agent-postgres --network agent-bridge \
-e POSTGRES_DB=agent_state -e POSTGRES_PASSWORD=******** \
-v pgdata:/var/lib/postgresql/data \
postgres:16-alpine
$ docker exec agent-postgres psql -U postgres -d agent_state -c "
CREATE TABLE tasks (
id SERIAL PRIMARY KEY,
agent_id TEXT NOT NULL,
status TEXT DEFAULT 'pending',
artifact_path TEXT,
result JSONB,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);"
CREATE TABLE
Each subagent writes its status to the tasks table on start and completion. The orchestrator polls this table to decide what to do next:
$ docker exec agent-postgres psql -U postgres -d agent_state -c \
"SELECT agent_id, status, artifact_path FROM tasks ORDER BY id DESC LIMIT 5;"
agent_id | status | artifact_path
-------------------+------------+----------------
subagent-research | completed | /workspace/research/summary.md
subagent-build | in_progress|
subagent-test | pending |
(3 rows)
This is lightweight coordination — not a message queue. For production pipelines, pair this with Hermes Agent's built-in delegate_task batch mode, which handles parallelism natively:
# Hermes parent session calls:
delegate_task(tasks=[
{"goal": "Research Docker isolation patterns", "context": "..."},
{"goal": "Build subagent Dockerfile", "context": "..."},
{"goal": "Test multi-agent coordination", "context": "..."}
])
The batch runs up to max_concurrent_children (default 3) in parallel with no PostgreSQL polling needed. The database layer is for durable state — task history, cross-run analytics, and post-mortem debugging.
Subagents produce artifacts — code, config files, reports. Git is the exchange medium. Each subagent commits its output to a shared repository; other subagents pull from the same repo:
$ git --version
git version 2.34.1
$ docker exec subagent-research git -C /workspace/project status
On branch agent/research-summary
nothing to commit, working tree clean
$ docker exec subagent-research git -C /workspace/project log --oneline -3
abc1234 Add research summary for Docker isolation patterns
def5678 Initialize subagent workspace
ghi9012 Merge parent orchestrator setup
The pattern:
A practical branch naming convention keeps things organized:
# Each subagent gets its own branch
agent/research-docker-isolation # Subagent A
agent/build-dockerfile # Subagent B (builds on A's work)
agent/test-multi-coordination # Subagent C (builds on B's work)
The orchestrator merges when all subagents are done:
$ git merge agent/research-docker-isolation
$ git merge agent/build-dockerfile
$ git merge agent/test-multi-coordination
$ git push origin main
config.yaml), Git merge conflicts happen. The orchestrator or a dedicated "resolution" subagent handles these. For production, prefer subagent boundaries that don't overlap — assign each subagent its own directory or file prefix.If a subagent needs to build or run Docker containers itself, you have two options:
Mount the host's Docker socket into the subagent container — clean, fast, same Docker daemon:
$ docker run -d --name subagent-docker \
-v /var/run/docker.sock:/var/run/docker.sock \
--network agent-bridge \
hermes-subagent:latest \
"Build and test the Docker image for ~/project"
For full isolation, run a separate Docker daemon inside the subagent container. Slower but air-gapped:
$ docker run -d --name subagent-dind \
--privileged \
--network agent-bridge \
docker:dind
$ docker run -d --name subagent-build \
--network agent-bridge \
-e DOCKER_HOST=tcp://subagent-dind:2375 \
hermes-subagent:latest "docker build -t my-image ."
--privileged flag weakens security. Only use dind when the subagent must run in a fully air-gapped Docker environment (e.g., testing untrusted Dockerfiles).Here's a real workflow: the parent Hermes Agent breaks a feature into three parallel subagent tasks, each isolated in its own Docker container:
# 1. Parent Hermes Agent dispatches 3 subagents in batch
delegate_task(tasks=[
{
"goal": "Research the best PostgreSQL connection pool for async Python agents. Write findings to /workspace/research/pg-pool.md",
"context": "Working in ~/project. Use asyncpg and SQLAlchemy benchmarks.",
"toolsets": ["terminal", "file", "web"]
},
{
"goal": "Implement PostgreSQL-backed task state store for Hermes subagents. Read research from /workspace/research/pg-pool.md",
"context": "Working in ~/project. Schema: tasks(id, agent_id, status, artifact_path, result, timestamps). Use Python + asyncpg.",
"toolsets": ["terminal", "file"]
},
{
"goal": "Write Docker Compose orchestration for 3-subagent system with PostgreSQL. Read implementation from the shared workspace.",
"context": "Working in ~/project. Include health checks, resource limits, and bridge networking.",
"toolsets": ["terminal", "file"]
}
])
Each subagent runs inside its Docker container with resource limits, shares state through PostgreSQL, and exchanges artifacts through Git. The orchestrator waits for all three to complete, then merges their branches:
$ git log --oneline --graph --all
* 3c4d5e6 (agent/test-docker-compose) Add Docker Compose for 3-subagent system
* 2b3c4d5 (agent/implement-pg-store) Implement PostgreSQL task state store
* 1a2b3c4 (agent/research-pg-pool) Research: asyncpg vs SQLAlchemy for agents
* 0z9y8x7 (main) Initial project scaffold
The orchestrator reviews each branch, merges to main, and the result is a production-ready multi-agent coordination system — built by three Docker-isolated subagents working in parallel.
Hermes Agent's delegation config section controls subagent behavior. Key settings for Docker-isolated subagents:
$ hermes config edit
# Relevant delegation config:
# delegation:
# max_concurrent_children: 3 # Parallel subagent cap
# max_spawn_depth: 1 # Nesting limit (1 = leaf only)
# max_iterations: 50 # Max LLM calls per subagent
# model: deepseek-v4-pro # Subagent model
# provider: deepseek # Subagent provider
View current delegation settings:
$ hermes config get delegation
delegation.max_concurrent_children: 3
delegation.max_spawn_depth: 1
delegation.max_iterations: 50
For Docker-isolated subagents, keep max_spawn_depth: 1 — each subagent is a leaf that cannot delegate further. This prevents container sprawl (subagents spawning sub-subagents recursively). If you need deeper nesting, increase max_spawn_depth and ensure your Docker host can handle the multiplication.
Track subagent container status with Docker's native introspection:
$ docker ps --format "table {{.Names}}\t{{.Status}}\t{{.RunningFor}}" | grep subagent
subagent-research Up 12 minutes 12 minutes
subagent-build Up 5 minutes 5 minutes
subagent-test Up 2 minutes 2 minutes
Monitor resource consumption to catch runaway subagents:
$ docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}" | grep subagent
subagent-research 23.45% 1.2GiB / 4GiB
subagent-build 45.12% 2.8GiB / 4GiB
subagent-test 8.30% 0.5GiB / 4GiB
For historical analysis, query the PostgreSQL task history:
$ docker exec agent-postgres psql -U postgres -d agent_state -c "
SELECT agent_id, status, created_at,
EXTRACT(EPOCH FROM (updated_at - created_at)) AS duration_sec
FROM tasks
WHERE created_at > NOW() - INTERVAL '1 hour'
ORDER BY created_at DESC;"
agent_id | status | created_at | duration_sec
---------------------+-----------+---------------------------+-------------
subagent-test | completed | 2026-08-10 14:45:00+00 | 180
subagent-build | completed | 2026-08-10 14:35:00+00 | 420
subagent-research | completed | 2026-08-10 14:20:00+00 | 900
(3 rows)
--rm) or be cleaned up by the orchestrator after use. Orphaned containers leak memory and disk.context strings — they end up in LLM context and session logs. Use environment variables via Docker's -e flag instead.delegate_task(tasks=[...])) handles parallelism natively — PostgreSQL is for durable state, not as a message queueMulti-agent orchestration with Docker-isolated subagents turns Hermes Agent from a single-worker tool into a parallel execution engine. The patterns above — container isolation, PostgreSQL coordination, and Git-based artifact exchange — are the foundation of production multi-agent systems. Every command verified on real hardware.