claude-cookbooks Observability Agent 架构与通信流解析:从 MCP 到 GitHub API 的全链路监控设计
导读
本文以 claude-cookbooks 仓库 claude_agent_sdk/observability_agent/architecture_diagram.md 中的两张 Mermaid 架构图为骨架,完整拆解 Observability Agent(可观测性 Agent) 的组件拓扑与运行时消息流转:用户如何把查询交给 Agent,Agent 如何经容器化的 GitHub MCP Server 调用 GitHub API,并将结论返回给用户。通过对照同目录下的 agent.py、docker/Dockerfile、docker/docker-compose.yml 以及教程 02_The_observability_agent.ipynb,你将掌握这类 "Agent + MCP Server + 外部 API" 架构中每一层的职责边界、关键配置项(allowed_tools/disallowed_tools/permission_mode 等)及其底层原理,可直接复用于构建 CI/CD 健康度监控、issue/PR 分析等只读型 DevOps 助手。
架构图定位:一张图说清三层职责
architecture_diagram.md 全篇由两幅 Mermaid 图构成,是 observability_agent 这个例子的架构总纲。第一幅是静态拓扑图(组件依赖关系),第二幅是时序图(一次查询请求从发起到返回的完整消息序列)。它与同目录 Python 实现是一一对应的,不是"示意图",而是对真实运行结构的精确描述:
| 架构图中的节点 | 代码/配置中的落点 |
|---|---|
| User | 调用方(notebook 交互或程序化调用 send_query) |
| Observability Agent | agent.py 中由 ClaudeSDKClient 驱动的 Agent 循环 |
| GitHub MCP Server | agent.py get_github_mcp_server() 返回的 McpServerConfig,命令为 docker run ... ghcr.io/github/github-mcp-server |
| Docker Container | 承载 GitHub MCP Server 的容器(详见 Dockerfile 与 docker-compose.yml) |
| GitHub API | GitHub 官方 REST/GraphQL 接口,由 MCP Server 在容器内代理访问 |
| WebSearch / Read Files | agent.py 中被显式禁用(disallowed_tools)的兜底工具 |
组件层架构解读:每个框都是什么、为什么存在
原图(第一幅)用 graph TD 定义了自上而下的数据/调用方向,Mermaid 图中以 style 高亮了核心节点。下面逐层还原其源码事实。
User → Observability Agent:一个面向值班工程师的系统提示词
Agent 之所以叫 "observability agent",根因在于 agent.py 内置的 DEFAULT_SYSTEM_PROMPT:
DEFAULT_SYSTEM_PROMPT = """You are an observability agent specialized in monitoring \
GitHub repositories and CI/CD workflows. Provide concise, actionable insights \
suitable for on-call engineers. Focus on identifying issues, assessing severity, \
and recommending next steps."""
这正是架构图中 Agent 框的"人格"来源:只读式监控(read-only observability)。例如教程中给出的真实查询就要求 Agent "分析 facebook/react 仓库 CI 健康度——最近一次 CI workflow 运行的状态与触发方式、失败时定位具体 job/测试并评估严重性、通过时留意长耗时与 flaky 历史、最后给出带优先级的行动建议,且明确 不要创建 issue 或 PR"(见 02_The_observability_agent.ipynb 中 prompt 定义)。系统提示词与用户提示词共同约束了 Agent 的行为边界,使架构图中的 User --> Agent 链路具备明确的领域语义。
Agent → GitHub MCP Server:为何必须以 Docker 方式接入
架构图中 Agent --> GitHub[GitHub MCP Server] 与 GitHub --> Docker[Docker Container] 两层箭头,对应的正是 agent.py 的 MCP 配置:
def get_github_mcp_server() -> dict[str, McpServerConfig]:
token = os.environ.get("GITHUB_TOKEN")
if not token:
return {}
return {
"github": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"GITHUB_PERSONAL_ACCESS_TOKEN",
"ghcr.io/github/github-mcp-server",
],
"env": {"GITHUB_PERSONAL_ACCESS_TOKEN": token},
}
}
几个与架构图直接对应的实现要点:
- 官方容器镜像:使用的是 GitHub 官方发布镜像
ghcr.io/github/github-mcp-server。Agent 通过本机 Docker CLI 以交互模式(-i)拉起容器,--rm保证容器用后即删,不留残留进程——这正是架构图中Docker Container框的运行时语义:进程隔离、随用随灭。 - Token 透传方式:
-e GITHUB_PERSONAL_ACCESS_TOKEN(不带值)表示从父进程环境继承同名变量;随后env字段又把当前进程环境里的GITHUB_TOKEN显式注入。因此运行前必须在.env中配置GITHUB_TOKEN="<token>"并通过load_dotenv()加载(见 agent.py 第 28 行)。 - 未配置 Token 时的降级:
get_github_mcp_server()在缺少GITHUB_TOKEN时返回空字典,后续会由allowed_tools列表推导逻辑自动收敛(见下文),整个 Agent 仍可启动,只是失去 GitHub 能力。
容器镜像本身与安全基线由 observability_agent/docker/Dockerfile 保证:它以 python:3.11 为基底,安装 docker-ce-cli、nodejs,全局安装 @anthropic-ai/claude-code,随后 pip install claude-agent-sdk、fastapi、uvicorn[standard]、mcp-server-git 等运行时依赖,并用 claude --version 验证安装。而 docker-compose.yml 提供了完整服务化编排:将宿主 Docker socket 挂载进容器(/var/run/docker.sock:/var/run/docker.sock)以便在容器内拉起 MCP Server 容器,声明 DOCKER_HOST=unix:///var/run/docker.sock、固定 DNS 与 restart: unless-stopped,并把容器 8000 端口映射到宿主机 8001(注释明确说明 "Different port to avoid conflict with research agent",即与本仓库 research agent 的端口隔离)。
GitHub MCP Server → GitHub API:超过 100 个工具的背后
教程 02_The_observability_agent.ipynb 的说明性文本指出:接入官方 GitHub MCP Server 后,Agent 将获得 超过 100 个与 GitHub 生态交互的工具,覆盖 issue/PR 管理、CI/CD workflow 监控、代码安全告警分析,且同时支持 public 与 private 仓库。架构图最底层 Docker --> API[GitHub API] 表达的就是这一层:真正的数据源是 GitHub API,MCP Server 在容器内部充当"协议翻译层",把 Agent 的 MCP 工具调用翻译为对 GitHub API 的 HTTP 请求。
Tools 层:WebSearch / Read Files 为何"存在又不可用"
架构图中有一组值得注意的节点:Agent --> Tools[Tools],其下又分出 WebSearch 与 Read Files。结合 agent.py 的实现可以解释它的真实含义——这些工具默认被列入禁用清单:
# Build allowed tools list based on configured MCP servers
allowed_tools = [f"mcp__{name}" for name in servers]
# Configure disallowed tools to ensure MCP usage
# Without this, the agent could bypass MCP by using Bash with gh CLI
disallowed_tools = ["Bash", "Task", "WebSearch", "WebFetch"] if restrict_to_mcp else []
allowed_tools是按已配置 MCP server 动态拼出的mcp__<server_name>列表(例如启用 GitHub 时即为["mcp__github"]),实现"只开放已接入的 MCP 工具"。disallowed_tools显式封禁Bash、Task、WebSearch、WebFetch。这是整个设计中最关键的一处强制约束:若不封禁 Bash,Agent 完全可以绕过 MCP、改用ghCLI 甚至裸curl访问 GitHub API,导致架构图中Agent → GitHub MCP → GitHub API的链路名存实亡。代码注释与教程均强调:allowed_tools只影响权限提示(permission prompting),真正"物理禁用"工具可用性的是disallowed_tools。restrict_to_mcp参数(默认True)提供开关:设为False时禁用列表为空,Agent 拥有 Bash/Task 等兜底能力,用于需要灵活降级的场景。
换言之,架构图 Tools 分支与其说描述"Agent 有哪些工具",不如说描述"Agent 的默认工具面被刻意收窄到 MCP 通道",这是本项目的一个核心架构决策(见 agent.py 模块 docstring:"Uses disallowed_tools to ensure MCP tools are used (not Bash with gh CLI)")。
通信流时序解读:一次查询如何走完全程
原图(第二幅)是一段 sequenceDiagram,共 5 个参与者(User、Agent、GitHub MCP、GitHub API)与 6 条消息,描述一次完整请求的生命周期:
sequenceDiagram
participant User
participant Agent
participant MCP as GitHub MCP
participant API as GitHub API
User->>Agent: Query about repo
Agent->>MCP: Connect via Docker
Agent->>MCP: Request data
MCP->>API: Fetch info
API-->>MCP: Return data
MCP-->>Agent: Process results
Agent-->>User: Display answer
对照 agent.py 的 ClaudeSDKClient 会话代码,每条消息都有明确的代码落点:
options = ClaudeAgentOptions(
model=model,
allowed_tools=allowed_tools,
disallowed_tools=disallowed_tools,
continue_conversation=continue_conversation,
system_prompt=DEFAULT_SYSTEM_PROMPT,
mcp_servers=servers, # 空 dict 合法,无需 None
permission_mode="acceptEdits",
)
...
async with ClaudeSDKClient(options=options) as agent:
await agent.query(prompt=prompt) # User -> Agent:提交查询
async for msg in agent.receive_response(): # 持续接收流式消息
...
if hasattr(msg, "result"):
result = msg.result
User->>Agent: Query about repo:对应await agent.query(prompt=prompt)。值得注意的是 Agent 初始化时mcp_servers=servers传入的正是上面get_github_mcp_server()的产物;当use_github=False或未配置 Token 时该 dict 为空,SDK 仍可正常工作(代码注释明确 "Empty dict is valid, no need for None")。Agent->>MCP: Connect via Docker:SDK 根据McpServerConfig中的command: docker启动子进程,即执行docker run -i --rm ... ghcr.io/github/github-mcp-server,通过 stdio 完成 MCP 握手,架构图中的 Docker 容器在此刻被拉起。Agent->>MCP: Request data与MCP->>API: Fetch info:Agent 在推理循环中基于allowed_tools选出一个mcp__github工具(例如查看 workflow run),MCP Server 收到调用请求后代表 Agent 向 GitHub API 发 HTTP 请求——API-->>MCP: Return data是同步应答。MCP-->>Agent: Process results:MCP Server 把 API 响应整理为结构化的工具调用结果返回给 Agent;Agent 依据系统提示词("identify issues, assess severity, recommend next steps")将多轮工具结果综合成面向值班工程师的结论。Agent-->>User: Display answer:在 notebook 场景中,结果经 utils/agent_visualizer.py 的print_activity()(实时反馈每个活动消息)、display_agent_response()(渲染最终答复)与visualize_conversation()(绘制对话树)呈现给用户;display_result参数设为False时则只返回文本、供程序化使用。
值得注意时序图里 User 与 Agent 的交互是一轮查询,而 send_query 通过 continue_conversation 参数把多轮会话也纳入了同一架构:首次调用会先 reset_activity_context() 清空可视化上下文,续接调用则保留历史消息,便于"先问 CI 状态、再追问 flaky 测试"这类纵深挖掘(见 notebook 中 result1 = await send_query(...) 与 result2 = await send_query(..., continue_conversation=True) 的两段式示例)。
从两张图看两个通用架构模式
- 协议桥接模式:Agent(Claude)不直接依赖任何一家 SaaS 的 SDK,而是通过 MCP(Model Context Protocol)这一开放标准接入
github-mcp-server,Server 与外部 API 之间再做一次协议转换。好处是同一套 Agent 逻辑可任意挂载 Git/MySQL/浏览器等不同 MCP Server 而无需改动业务代码——本仓库教程即演示了从本地 Git MCP Server 平滑切换到 GitHub MCP Server 的过程。 - 只读可观测 + 工具面收窄:通过
disallowed_tools强制 Agent 只能经 MCP 访问 GitHub,杜绝其用 Bash +gh走"捷径",既保证调用路径可审计,也契合"监控而不改动"的定位。这种"能力面显式收窄"的做法,对任何追求可审计、可回放的生产级 Agent 都具有直接借鉴意义。
从架构图到可运行代码的快速对照
想亲手跑通架构图中的链路,最小步骤是(仓库为只读,以下均为本地运行方式):
-
准备凭据与运行时:在
.env中写入GITHUB_TOKEN="<token>"(建议在 GitHub 创建 Fine-grained Token,默认公开仓库权限即可跑通本示例),并确保本机 Docker 可用(docker --version验证)。 -
本地直跑 Agent 模块:将
claude_agent_sdk目录加入 Python 路径后调用 observability_agent/agent.py 导出的send_query:from observability_agent.agent import send_query result = await send_query( "Check the CI status for the last 2 runs in anthropics/claude-agent-sdk-python. Just do 3 tool calls, be efficient." )该模块已内部处理活动显示、上下文重置与结果可视化;多轮追问时追加
continue_conversation=True。 -
容器化整体部署:参照 observability_agent/docker/docker-compose.yml 构建服务(它会从
../../.env读取环境变量并把 Docker socket 挂载进容器),宿主机访问映射端口8001。 -
对照验证:架构图中的每一条边都可在 agent.py(链路与选项配置)、docker/Dockerfile 与 docker-compose.yml(容器层)、02_The_observability_agent.ipynb(端到端演示)中找到对应的实现与调用证据。
小结
architecture_diagram.md 用一静一动两张 Mermaid 图精炼概括了 Observability Agent 的全部架构语义:静态拓扑交代"谁依赖谁、谁被谁隔离"(Agent 依赖容器化的 GitHub MCP Server,MCP Server 代理 GitHub API,WebSearch/Read 类兜底工具被刻意收窄),动态时序交代"一次查询如何分层穿透"(User → Agent → MCP → GitHub API → 原路返回)。两图叠加,即是对 agent.py 中 McpServerConfig、allowed_tools、disallowed_tools、ClaudeSDKClient 会话管理的可运行注脚——理解了这张图,就理解了如何用 Claude Agent SDK 构建"只读、可审计、面向值班运维"的 GitHub 监控型 Agent。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0627
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00