为什么需要 Agent 可观测性?
用 AI Agent 写代码、做分析的时候,最大的浪费不是硬件,是盲区。
你的 Agent 在后台跑了 20 步,最终结果看起来还行,但你完全不知道中间发生了什么:哪一步最烧 Token?哪个工具调用最慢?错误出在哪一步?你只能靠猜,或者在日志里大海捞针。
现有的监控方案要么太重(ELK 一套下来 16GB 内存起步),要么太贵(Datadog $15/月起、Sentry $26/月起),个人开发者根本用不起。
我需要的是一个:零成本、5 分钟搭好、一屏看清所有 Agent 行为的方案。
架构
三个组件,刚好凑成完美组合:
Hermes Agent → 自动记录每步 → Quack 协议 (HTTP) → DuckDB (obs.db) → Streamlit 仪表盘
- DuckDB:嵌入式分析数据库,单文件、零配置,跑分析比 SQLite 快 10-100 倍
- Quack:DuckDB 的远程通信协议,基于 HTTP,一行
CALL quack_serve()启动 - Hermes Agent:开源 AI Agent 框架,支持工具调用和记忆
部署步骤
1. 安装 DuckDB
# Linux
curl -fsSL https://install.duckdb.org | sh
# macOS
brew install duckdb
# Windows
winget install DuckDB.cli
2. 创建数据库和表
duckdb /var/lib/hermes-obs/obs.db
CREATE TABLE agent_traces (
session_id UUID,
step_id INTEGER,
action VARCHAR, -- think / tool_call / llm_call / tool_result / error
tool_name VARCHAR,
content VARCHAR,
token_cost INTEGER DEFAULT 0,
latency_ms INTEGER DEFAULT 0,
model VARCHAR,
created_at TIMESTAMP DEFAULT now()
);
3. 记录 Agent 行为
每次工具调用后写入一行:
import duckdb
conn = duckdb.connect('/var/lib/hermes-obs/obs.db')
conn.execute("""
INSERT INTO agent_traces (session_id, step_id, action, tool_name, content, token_cost, latency_ms, model)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
""", (session_id, step_id, 'tool_call', 'search_content', '搜索用户需求', 45, 320, 'deepseek-v4-flash'))
4. 启动实时仪表盘
pip install streamlit streamlit-autorefresh
streamlit run dashboard.py --server.port 5803
仪表盘特性:
- 5 个 KPI 卡片:监控操作数、会话数、Token 消耗、数据存储、运行成本
- 水平柱状图(多色区分工具类型)
- 饼图(工具占比)
- Token 消耗明细(按模型 + 按操作类型)
- 30 秒自动刷新 + 手动刷新按钮
- 全中文界面
5. 设置自动记录
创建一个每 10 分钟的心跳 cron 任务,确保看板数据始终新鲜:
cronjob action=create \
name="hermes-obs-heartbeat" \
schedule="every 10m" \
prompt="Write a heartbeat record to Hermes-Obs DB"
关键查询
部署完成后,以下 SQL 可以回答常见问题:
今日总览:
SELECT COUNT(*) AS 总步骤, SUM(token_cost) AS 总Token,
ROUND(AVG(latency_ms), 1) AS 平均延迟
FROM agent_traces WHERE created_at >= CURRENT_DATE;
哪个工具最烧 Token:
SELECT tool_name, SUM(token_cost) AS 总Token, COUNT(*) AS 调用次数
FROM agent_traces WHERE action = 'tool_call'
GROUP BY tool_name ORDER BY 总Token DESC LIMIT 10;
模型成本对比:
SELECT model, SUM(token_cost) AS 总Token, COUNT(*) AS 调用次数,
ROUND(AVG(latency_ms), 1) AS 平均延迟
FROM agent_traces WHERE model IS NOT NULL
GROUP BY model ORDER BY 总Token DESC;
成本对比
| 方案 | 月费 | 内存占用 | 部署时间 |
|---|---|---|---|
| Hermes-Obs | $0 | < 100MB | 5 分钟 |
| ELK Stack | $0(自建)/$200+(云) | 16GB+ | 1-2 天 |
| Datadog APM | $15/月起 | — | 30 分钟 |
| Sentry Performance | $26/月起 | — | 20 分钟 |
部署后常见问题
Q: DuckDB 文件锁冲突怎么办?
在写入前停止 Streamlit 仪表盘,写入完成后重启。或使用 WAL 模式:PRAGMA enable_checkpoint_on_shutdown=false
Q: 数据量大了怎么办?
DuckDB 单表可处理数亿行,对于个人开发者完全够用。定期清理旧数据:
DELETE FROM agent_traces WHERE created_at < now() - INTERVAL '30 days';
Q: 可以多台机器共用一个数据库吗?
可以。部署到服务器上,Agent 通过 Quack 协议远程写入:
# 服务端
CALL quack_serve('quack:0.0.0.0:8338', token='xxx');
# 客户端连接同一条 conn
Q: 仪表盘上数据不更新?
检查两点:① hermes-obs-record 是否被调用写入新数据;② Streamlit 仪表盘页面是否启用了自动刷新(默认 30 秒)
实测数据
写这篇文章的过程中,我的 Hermes Agent 执行了 36 步操作,消耗了 12,595 个 Token:
- deepseek-v4-flash 占了大部分工具调用
- Pro 模型只用于关键决策(占 92% Token 但只有 21% 调用次数)
- 平均工具延迟:patch 修改 ~200ms,终端命令 ~350ms
- 总成本折合不到 1 美分
有了这些数据,优化方向就很清晰了:减少不必要的 Pro 模型调用,避免长链条的冗余工具链。
接下来
后续文章会介绍如何将 Quack 协议部署到远程 VPS,以及如何为 Hermes-Obs 添加 Token 预算告警和异常检测。
想了解其他 DuckDB 实践?查看 DuckDB Python 集成指南 或 SQL 数据分析仪表盘搭建。
