内容
# 代理感知
**理解您的AI代理的行为。** 一个本地优先、MCP原生的可观察性和调试工具:一个透明的MCP代理跟踪每一个协议消息,**无需对代理进行任何代码修改**,个人身份信息(PII)在写入路径上确定性地被删除,跟踪信息全部存储(无字段白名单)到本地的SQLite数据库中 —— 然后 **重放和比较** 以查看不同模型将如何做出决策。
*Apache-2.0 · 本地优先 · 无需云端注册*

> *比较视图 — 相同的运行结果针对两个模型进行重放,第一次决策分歧的位置被高亮显示。*
## 它有什么不同
代理可观察性工具通常缺少以下至少一项 —— 代理感知结合了所有四项:
- **本地优先** — 完全在您的机器上运行;无需云端注册或账户。
- **MCP原生** — 在Model Context Protocol(MCP)内部进行跟踪,而不是通过OpenTelemetry包装,因此它可以跟踪工具调用而无需任何代码修改。
- **跟踪重放 + 轨迹比较** — 重新运行一个记录的跟踪结果针对不同的模型,并查看决策结果在何处出现分歧。
- **开源** — Apache-2.0许可证。
## 为什么它有用
当AI代理行为异常时 —— 错误的工具、错误的决策、失控的成本 —— 您通常只能靠猜测。代理感知为您提供事实依据:
- **协议级别的跟踪,无需代码修改。** 将代理的MCP配置指向代理,它将捕获每个工具调用、输入/输出、延迟和成本 —— 即使对于您无法检测的代理。
- **“如果使用不同的模型会怎么样?”** 重放记录的跟踪结果针对另一个模型/提示,输入存储的工具结果,并比较轨迹以查看行为在何处出现分歧 —— 无需实时工具调用、无API成本、无副作用。
- **符合合规要求的审计跟踪。** 个人身份信息(PII)在存储之前确定性地被删除,并且删除过程本身被记录 —— 为欧盟AI法案执行提供审计跟踪故事(从2026年8月开始)。
- **本地优先。** 无需云端注册,完全可自行托管。
## 包含内容
| 组件 | 模块 | 状态 |
|---|---|---|
| MCP代理(stdio,透明) | `proxy/` | ✅ |
| 确定性个人身份信息(PII)删除 | `redaction/` | ✅ write-path |
| SQLite跟踪存储(完整对象) | `store/` | ✅ |
| 重放 + 轨迹比较 | `replay/` | ✅ pluggable model client |
| Python捕获SDK | `sdk/` | ✅ OTel GenAI conventions |
| 本地跟踪浏览器UI | `ui/` | ✅ read-only, FastAPI |
## 设计保证
- 代理转发原始字节 **不变**;仅复制一份用于跟踪。
- 日志输出到 **stderr / file, 绝不输出到stdout** (stdout是JSON-RPC通道)。
- 跟踪存储保留 **未知/供应商字段** —— 完整对象,无白名单。
- 删除是 **确定性** 的(基于哈希的令牌),因此重放对齐。
## 安装
```bash
pip install agentsense-ai # 分发名称;CLI和导入为`agentsense`
# 额外功能:pip install "agentsense-ai[ui,replay]" # 网页UI + 实时重放模型客户端
```
安装/导入名称不同(如 `scikit-learn` → `sklearn`):软件包为 `agentsense-ai`,但运行 `agentsense …` 和 `import agentsense`.
## 使用方法
捕获 → 探索 → 重放:
1. **捕获运行结果** — 两种方式:
- **无需代码修改:** 将代理放在MCP服务器前面([快速入门](#快速入门))—— 它跟踪每个工具调用。
- **更丰富的信息:** 使用 [捕获SDK](#捕获sdk) 包装您自己的循环,以记录推理和模型调用。
2. **探索** — `agentsense ui --db traces.db` 打开 [跟踪浏览器](#本地跟踪浏览器ui): span树、时间线、PII删除徽章。
3. **重放** — 重新运行捕获的跟踪结果针对不同的模型,并 [比较轨迹](#重放--轨迹比较) 以查看决策结果在何处出现分歧。
## 快速入门
代理是一个stdio MCP服务器,您的客户端启动,包装真实服务器。将它添加到您的MCP客户端配置中(例如Claude Desktop,Cursor):
```jsonc
{
"mcpServers": {
"filesystem": {
"command": "agentsense",
"args": ["proxy", "--db", "traces.db",
"--", "npx", "-y", "@modelcontextprotocol/server-filesystem", "/data"]
}
}
}
```
像平常一样使用您的代理,然后探索它做了什么:
```bash
agentsense ui --db traces.db # 打开 http://127.0.0.1:8000
```
**想立即看到效果?** 使用MCP Inspector驱动它 —— 无需配置编辑:
```bash
npx @modelcontextprotocol/inspector \
agentsense proxy --db traces.db -- npx -y @modelcontextprotocol/server-filesystem /tmp
# 在Inspector中进行工具调用,然后: agentsense ui --db traces.db
```
## 测试
```bash
uv run pytest # 离线运行单元测试;代理无模型依赖
uv run ruff check .
```
`test_proxy_transparency.py` 是一个集成测试,通过代理驱动 `server-filesystem`,使用真正的MCP客户端;如果 `npx` 不可用,它将自动跳过。
## UI(本地跟踪浏览器)
一个只读的网页应用,基于跟踪存储构建 —— 无需构建步骤,无需Node。它提供JSON API和单个静态页面(跟踪列表 → span树 + 时间线 + 删除徽章)。

```bash
uv sync --extra ui
uv run agentsense ui --db traces.db # 打开 http://127.0.0.1:8000
```
**比较** 标签页渲染侧边重放轨迹比较:选择两个捕获的跟踪结果,查看它们的决策序列对齐,第一次分歧位置高亮显示。
**实时重放** — 在任何捕获的跟踪结果上,选择一个模型并在那里重新运行:代理重建记录,重放它针对您选择的模型(OpenAI兼容/Ollama或AWS Bedrock),并将结果与代理实际执行的结果进行比较。临时 — 无存储写入。

端点:`GET /api/traces`, `GET /api/traces/{id}/spans`, `GET /api/diff?a=&b=`, `POST /api/replay`. 前端是纯HTML/JS,位于 `ui/static/` — 可替换为React以支持相同API。
## 捕获SDK
对于您可以检测的代理,SDK记录推理级别的详细信息,而代理无法看到。它通过相同的存储写入 —— 因此是相同的删除路径 —— 使用OpenTelemetry GenAI属性命名(`gen_ai.*`)进行互操作。
```python
from agentsense.sdk import Tracer
from agentsense.store import SpanStore
tracer = Tracer(SpanStore("traces.db"))
with tracer.session("booking-agent") as s:
s.step("plan", reasoning=..., model="claude-opus-4-8")
s.llm_call("claude-opus-4-8", messages=[...], response={...},
usage={"input_tokens": 1200, "output_tokens": 80})
s.tool_calls("search_flights", args={...}, result={...}, cost=0.002)
```
Span形成一个浅树(会话 → 步骤)。`llm_call` 存储整个对话(消息、工具、响应),因此捕获的运行结果可以重建为可重放的 `Recording`. 示例:`uv run python examples/sdk_capture.py`.
## 重放 + 轨迹比较
重新驱动代理运行针对不同模型,**注入记录的工具结果** (引擎无法调用实时工具 —— 保证通过构造保持),然后比较两个决策轨迹以找到第一个分歧点。
```bash
# 离线,无需凭证 — 两个脚本“模型”在相同的记录结果上:
uv run python examples/replay_scripted.py
# → 在决策0处分歧:haiku-4.5 → 调用 get_weather(...) | opus-4.8 → 调用 get_forecast(...)
```
模型客户端 **可通过适配器插件** (`replay/adapters/`):`BedrockAdapter`(AWS Bedrock Converse),`OpenAICompatAdapter`(OpenAI,Ollama或任何OpenAI兼容端点),和`ScriptedAdapter`(离线/测试)。引擎仅使用提供者中立类型 —— 交换提供者从不触及它。记录的工具结果可以直接提供或通过 `Recording.from_trace_store(...)` 从捕获的代理跟踪中提取。
### 捕获 → 重放(完整循环)
SDK捕获的运行结果重放端到端:`Recording.from_sdk_trace(store, trace_id)` 重建问题、工具、模型和记录的工具结果,`captured_trajectory(store, trace_id)` 重建代理实际执行的操作。比较两者以回答“如果使用不同的模型,是否会与我的代理做出不同的决策?”
```bash
uv run python examples/capture_then_replay.py
# → 在决策0处分歧:claude-haiku-4-5 → 调用 get_weather(...) | rushed-model → 最终答案
```
## 模型访问(仅实时重放 — 不适用于代理)
实时重放调用模型,因此它需要您选择的提供者的凭证 —— 兼容OpenAI的端点(`OPENAI_API_KEY`,或本地Ollama基准URL)或AWS Bedrock。对于Bedrock示例:
```bash
aws sso login --profile <your-aws-profile> # 临时SSO凭证
export AWS_PROFILE=<your-aws-profile> AWS_REGION=eu-west-1
uv run --extra replay python examples/replay_bedrock.py
```
## 贡献
欢迎提出问题和PR — 请参阅 [CONTRIBUTING.md](./CONTRIBUTING.md)。所有测试均离线运行(`uv run pytest`);代理无模型依赖。
## 许可证
[Apache License 2.0](./LICENSE) — 包括明确的专利授权。