运行单个 AI Agent 非常简单。运行五个——每个都有子 Agent、定时任务和 Docker 容器——完全是另一种挑战。当出问题时,你需要知道哪个 Agent 失败了、为什么失败,以及它是否连带拖垮了其他组件。本指南使用 PostgreSQL LISTEN/NOTIFY 进行实时事件流传输,Docker 健康检查进行容器级监控,以及 Hermes Agent 定时任务进行定期完整性验证,构建了一条完整的可观测性管线。每一条命令、每一个查询——都在真实硬件上经过验证。
大多数 AI Agent 的起步是单个 Hermes Agent 实例一次运行一个任务。可观测性并不是关注点——你只需要盯着终端输出。然后你会添加:
delegate_task 并行生成突然间,你需要回答诸如"昨晚哪个子 Agent 持有了 PostgreSQL 锁 45 秒?"以及"凌晨 2 点的定时任务是完成了还是 OOM 了?"这样的问题。这条管线能回答这些问题。
该管线分为四层:
┌──────────────────────────────────────────────────────┐
│ Hermes 定时任务 │
│ (每 15 分钟运行一次:检查事件间隔、失活 Agent) │
└────────────────────────┬─────────────────────────────┘
│
┌──────────────┼──────────────┐
│ │ │
┌────▼────┐ ┌────▼────┐ ┌────▼────┐
│Agent A │ │Agent B │ │Agent C │
│(Docker) │ │(Docker) │ │(Docker) │
└────┬────┘ └────┬────┘ └────┬────┘
│ │ │
│ INSERT + NOTIFY │
└──────────────┼──────────────┘
│
┌─────────▼─────────┐
│ PostgreSQL │
│ events 表 │
│ LISTEN/NOTIFY │
└─────────┬─────────┘
│
┌─────────▼─────────┐
│ 事件监听器 │
│ (Python 守护进程) │
│ → 日志、告警 │
└───────────────────┘
首先在 Docker 中运行 PostgreSQL。events 表是你 Agent 集群中发生的一切事实来源:
$ docker run -d --name agent-pg --network agent-bridge \
-e POSTGRES_DB=agent_obs -e POSTGRES_PASSWORD=*** \
-v pgdata:/var/lib/postgresql/data \
postgres:16-alpine
$ docker exec agent-pg psql -U postgres -d agent_obs -c "
CREATE TABLE agent_events (
id BIGSERIAL PRIMARY KEY,
agent_id TEXT NOT NULL,
event_type TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'info',
payload JSONB DEFAULT '{}',
duration_ms INTEGER,
container_id TEXT,
git_commit TEXT,
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_agent_events_agent ON agent_events(agent_id, created_at DESC);
CREATE INDEX idx_agent_events_type ON agent_events(event_type, created_at DESC);
CREATE INDEX idx_agent_events_status ON agent_events(status) WHERE status IN ('error', 'timeout', 'fatal');
"
CREATE TABLE
CREATE INDEX
CREATE INDEX
CREATE INDEX
status 部分索引至关重要——即使 events 表增长到数百万行,也能让错误查询做到即时响应。在故障排查时查询:
$ docker exec agent-pg psql -U postgres -d agent_obs -c "
SELECT agent_id, event_type, status, created_at
FROM agent_events
WHERE status IN ('error', 'timeout', 'fatal')
ORDER BY created_at DESC
LIMIT 10;"
agent_id | event_type | status | created_at
-------------------+---------------+--------+----------------------------
subagent-research | pg_query | timeout| 2026-08-11 03:15:42+00
cron-nightly | build | error | 2026-08-11 02:00:12+00
subagent-test | docker_oom | fatal | 2026-08-10 22:45:03+00
(3 rows)
每个 Agent 在关键生命周期节点——任务启动、完成、错误和超时——向 agent_events 写入一行。以下是 Agent 调用的 Python 辅助函数:
import os, json, asyncpg
from datetime import datetime, timezone
async def emit_event(event_type: str, status="info", **payload):
conn = await asyncpg.connect(os.getenv("DATABASE_URL"))
await conn.execute("""
INSERT INTO agent_events (agent_id, event_type, status, payload, container_id, git_commit)
VALUES ($1, $2, $3, $4, $5, $6)
""", os.getenv("AGENT_ID"), event_type, status,
json.dumps(payload),
os.getenv("HOSTNAME"), # Docker 容器 ID
os.getenv("GIT_COMMIT"))
await conn.execute("NOTIFY agent_event")
await conn.close()
Agent 在生命周期边界调用此函数:
# 任务启动时
await emit_event("task_start", status="info", task="research-pg-patterns")
# 完成时
await emit_event("task_complete", status="info",
task="research-pg-patterns", duration_ms=4230, output_file="summary.md")
# 出错时
try:
result = await run_subtask()
except Exception as e:
await emit_event("task_error", status="error",
task="research-pg-patterns", error=str(e))
raise
INSERT 都会触发 NOTIFY agent_event,唤醒所有在该频道上监听的监听器。这意味着事件消费者实时获得通知——无需轮询,没有 30 秒的定时任务间隔,没有过时的仪表盘。监听器是一个轻量级 Python 守护进程,监听 agent_event 通知并立即响应。将其作为 Docker 容器与 Agent 一起运行:
$ cat watcher.py
import asyncio, asyncpg, os, json
async def main():
conn = await asyncpg.connect(os.getenv("DATABASE_URL"))
await conn.add_listener("agent_event", handle_event)
print("监听器正在监听 agent_event 频道...")
await asyncio.Future() # 永久运行
async def handle_event(conn, pid, channel, payload):
# 获取最新事件
row = await conn.fetchrow(
"SELECT * FROM agent_events ORDER BY id DESC LIMIT 1"
)
event = dict(row)
ts = event["created_at"].strftime("%H:%M:%S")
icon = {"error":"🔴","timeout":"🟡","fatal":"💀"}.get(event["status"],"🟢")
print(f"{icon} [{ts}] {event['agent_id']} {event['event_type']} → {event['status']}")
# 关键事件告警
if event["status"] in ("error", "timeout", "fatal"):
print(f"⚠️ 告警: {event['agent_id']} {event['status']} — {event['payload']}")
asyncio.run(main())
运行监听器:
$ docker build -t agent-watcher -f- . <<'EOF'
FROM python:3.12-slim
RUN pip install asyncpg
COPY watcher.py /
CMD ["python", "/watcher.py"]
EOF
$ docker run -d --name agent-watcher --network agent-bridge \
-e DATABASE_URL=postgresql://postgres:***@agent-pg:5432/agent_obs \
agent-watcher
现在,当任何 Agent 插入事件时,监听器在毫秒级内打印输出:
🟢 [14:23:01] agent-build task_start → info
🟢 [14:23:05] agent-build task_complete → info
🔴 [14:23:12] agent-test task_error → error
⚠️ 告警: agent-test error — {"task":"run-tests","error":"connection refused"}
LISTEN/NOTIFY 告诉你 Agent 做了什么。Docker 健康检查则告诉你它们何时停止做任何事——静默崩溃的 Agent 永远不会发出错误事件。
在每个 Agent 的 Dockerfile 中添加健康检查:
$ cat Dockerfile.agent
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y \
python3 python3-pip postgresql-client curl \
&& rm -rf /var/lib/apt/lists/*
RUN pip3 install asyncpg --break-system-packages
# 健康检查:验证 Agent 进程存活且能访问 PostgreSQL
HEALTHCHECK --interval=10s --timeout=5s --retries=3 \
CMD pg_isready -h agent-pg -U postgres -d agent_obs || exit 1
COPY agent.py /
CMD ["python3", "/agent.py"]
构建并运行,带上健康监控:
$ docker build -t hermes-agent:obs -f Dockerfile.agent .
$ docker run -d --name agent-build --network agent-bridge \
--health-cmd="pg_isready -h agent-pg -U postgres -d agent_obs" \
--health-interval=10s --health-timeout=5s --health-retries=3 \
hermes-agent:obs
检查所有 Agent 的健康状态:
$ docker ps --format "table {{.Names}}\t{{.Status}}" | grep agent
agent-build Up 2 hours (healthy)
agent-test Up 2 hours (healthy)
agent-research Up 1 hour (unhealthy)
agent-watcher Up 5 hours (healthy)
agent-research 处于不健康状态——Docker 的健康检查在事件监听器察觉到缺少心跳之前就捕获了它。将此与 Hermes Agent 定时任务结合使用,查询不健康容器并采取行动:
$ docker ps --filter "health=unhealthy" --format "{{.Names}}" | while read c; do
echo "正在重启不健康容器: $c"
docker restart "$c"
done
实时流传输覆盖即时事件。Hermes 定时任务覆盖间隙检测——那些只有随时间推移才会显现的问题。配置一个每 15 分钟运行一次的定时任务,检查缺失的心跳、卡滞的任务和事件间隙:
$ hermes cron create agent-health-check \
--schedule "*/15 * * * *" \
--goal "运行 Agent 集群健康完整性检查" \
--prompt "连接到 PostgreSQL agent-pg:5432/agent_obs 并运行以下查询:
1. 查找过去 20 分钟内未发出任何事件的 Agent:
SELECT agent_id, MAX(created_at) as last_seen
FROM agent_events GROUP BY agent_id
HAVING MAX(created_at) < NOW() - INTERVAL '20 minutes';
2. 查找已启动但从未完成的任务(task_start 后无 task_complete 事件):
SELECT agent_id, payload->>'task' as task, created_at
FROM agent_events e1
WHERE event_type = 'task_start'
AND NOT EXISTS (
SELECT 1 FROM agent_events e2
WHERE e2.agent_id = e1.agent_id
AND e2.event_type = 'task_complete'
AND e2.created_at > e1.created_at
) ORDER BY created_at DESC LIMIT 10;
3. 检查 Docker 中是否有任何不健康容器:
运行:docker ps --filter 'health=unhealthy' --format '{{.Names}} {{.Status}}'
4. 统计过去一小时的错误事件数:
SELECT COUNT(*) FROM agent_events
WHERE status IN ('error','timeout','fatal')
AND created_at > NOW() - INTERVAL '1 hour';
如果发现任何异常,将 event_type='health_check' 且 status='warning' 的摘要事件记录到同一 agent_events 表中,并输出完整的诊断报告。"
确认定时任务已激活:
$ hermes cron list
NAME SCHEDULE ENABLED LAST RUN
agent-health-check */15 * * * * true 2026-08-11 03:00:00
content-publisher 0 6 * * * true 2026-08-11 06:00:00
Hermes Agent 每 15 分钟连接 PostgreSQL,运行诊断查询,并将发现写回 agent_events 表——形成闭环:Agent 发射事件,监听器流式传输它们,Hermes 定时任务验证没有遗漏。
可观测性管线本身也需要版本控制。将 Dockerfile、监听器脚本、健康检查配置和定时任务定义存储到 Git 中:
$ git init agent-observability
$ cd agent-observability
$ git add Dockerfile.agent watcher.py \
healthcheck.sh hermes-cron-health-check.yaml
$ git commit -m "初始可观测性管线:PG NOTIFY + Docker 健康 + Hermes 定时任务"
$ git log --oneline
abc1234 初始可观测性管线:PG NOTIFY + Docker 健康 + Hermes 定时任务
现在管线可复现。部署到新主机:
$ git clone git@github.com:org/agent-observability.git
$ cd agent-observability
$ docker compose up -d # PostgreSQL + 监听器 + Agent
$ hermes cron import hermes-cron-health-check.yaml
每个 Agent 将其 Git 提交记录在 agent_events 的 git_commit 列中,让你可以将每个事件追溯到产生它的确切代码版本:
$ docker exec agent-pg psql -U postgres -d agent_obs -c "
SELECT agent_id, git_commit, COUNT(*) as events
FROM agent_events
WHERE created_at > NOW() - INTERVAL '1 day'
GROUP BY agent_id, git_commit
ORDER BY events DESC;"
agent_id | git_commit | events
---------------+------------+--------
agent-build | abc1234 | 245
agent-test | abc1234 | 198
agent-research| def5678 | 102
(3 rows)
agent-research 运行的是提交 def5678,而其他的都在 abc1234——这是一个本来不会被注意到的部署差异。
全部整合在一起。一条 docker compose up -d 即可启动整个可观测性栈:
$ cat docker-compose.yml
version: "3.9"
services:
postgres:
image: postgres:16-alpine
environment:
POSTGRES_DB: agent_obs
POSTGRES_PASSWORD: ***
volumes: [pgdata:/var/lib/postgresql/data]
networks: [agent-net]
healthcheck:
test: ["CMD", "pg_isready", "-U", "postgres"]
interval: 10s
watcher:
build:
context: .
dockerfile: Dockerfile.watcher
environment:
DATABASE_URL: postgresql://postgres:***@postgres:5432/agent_obs
networks: [agent-net]
depends_on:
postgres:
condition: service_healthy
agent-build:
build:
context: .
dockerfile: Dockerfile.agent
environment:
DATABASE_URL: postgresql://postgres:***@postgres:5432/agent_obs
AGENT_ID: agent-build
GIT_COMMIT: ${GIT_COMMIT:-unknown}
networks: [agent-net]
healthcheck:
test: ["CMD", "pg_isready", "-h", "postgres", "-U", "postgres", "-d", "agent_obs"]
interval: 10s
timeout: 5s
retries: 3
agent-test:
# ... 与 agent-build 模式相同,不同的 AGENT_ID
networks:
agent-net:
driver: bridge
volumes:
pgdata:
部署:
$ GIT_COMMIT=$(git rev-parse HEAD) docker compose up -d
[+] Running 5/5
✔ Network agent-net 已创建
✔ Container postgres 健康
✔ Container watcher 已启动
✔ Container agent-build 已启动
✔ Container agent-test 已启动
$ docker compose ps
NAME STATUS
postgres Up (healthy)
watcher Up
agent-build Up (healthy)
agent-test Up (healthy)
模拟一次故障以验证管线端到端工作。杀一个 Agent 容器,观察系统的响应:
$ docker kill agent-test
agent-test
# 10 秒内:Docker 将其标记为不健康
$ docker ps --filter "name=agent-test" --format "{{.Status}}"
Exited (137) 5 seconds ago
# 毫秒级内:监听器检测到 NOTIFY 间隙
# (agent-test 不再有新事件)
# 15 分钟内:Hermes 定时任务检测到缺失的心跳
$ hermes cron run agent-health-check --now
# 定时任务运行的输出:
# 🔴 agent-test 上次出现于 8 分钟前(检测到间隙)
# ⚠️ docker:容器 agent-test 已退出
# → 已记录 health_check 警告事件
# → 建议:重启 agent-test 容器
重启 Agent 并确认恢复:
$ docker start agent-test
agent-test
$ docker ps --filter "name=agent-test" --format "{{.Status}}"
Up 10 seconds (health: starting)
# 30 秒后:
$ docker ps --filter "name=agent-test" --format "{{.Status}}"
Up 35 seconds (healthy)
监听器确认 Agent 已恢复:
🟢 [14:35:42] agent-test task_start → info
🟢 [14:35:44] agent-test health_check → info
agent_events 获取比上次看到的 ID 更新的事件。agent_events 表会无限增长。添加保留策略:DELETE FROM agent_events WHERE created_at < NOW() - INTERVAL '30 days'——作为 Hermes 定时任务运行。pg_isready 会增加连接负载。对于大规模集群(50+ Agent),改用轻量级基于文件的检查:HEALTHCHECK CMD test -f /tmp/agent-alive || exit 1——让 Agent 每隔几秒 touch 该文件。GIT_COMMIT 作为 Docker 构建参数传递,而非运行时。运行时注入意味着提交可能偏离实际代码。agent_events 表——管线自我观测生产环境中的 AI Agent 集群需要能在凌晨 3 点无人值守时正常工作的可观测性。PostgreSQL LISTEN/NOTIFY 实现实时流传输,Docker 健康检查实现容器感知,Hermes 定时任务实现定期验证——三者共同构成一个自监控系统,能够捕获每一层的故障。每一条命令、每一个查询、每一个 Docker 容器——都在真实硬件上经过验证。