atanus1502/cma-sre-agent

GitHub: atanus1502/cma-sre-agent

基于 Claude Managed Agents 构建的 SRE 事件响应智能体,通过关联日志、指标和部署信息自动定位故障根因。

Stars: 0 | Forks: 0

# 事件-4813 这是一个为虚构的电子商务技术栈构建的可用的故障仪表板。Metrics、Logs 和 Deploys 页面在开箱即用的 mock 数据下即可运行。在每个页面的侧边都有一个 **SRE Agent** 聊天面板,它基于 [Claude Managed Agents](https://platform.claude.com/docs/en/managed-agents/overview) 构建。 问它*“是什么导致了延迟飙升?”*,然后看着它在自己的云端沙箱中对 7 万行日志进行 grep,调用本地工具拉取指标和部署信息,关联时间戳,获取出问题的代码差异,并指出具体的 commit。 ## 设置说明 你需要 Python **3.10+** 和一个 [Anthropic API key](https://console.anthropic.com/settings/keys)。 ``` python -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\activate pip install -r requirements.txt cp .env.example .env # then put your ANTHROPIC_API_KEY in .env streamlit run app.py ``` 仪表板将在 `localhost:8501` 打开。随便点击看看 —— Metrics、Logs、Deploys 以及右侧的 SRE Agent 面板都是开箱即用的。 ## Agent 是如何连接的 `agent.py` 包含七个函数,每个都是一次 Managed Agents API 调用: | # | 函数 | API 调用 | |---|---|---| | 1 | `setup_agent()` | `client.beta.agents.create` | | 2 | `setup_environment()` | `client.beta.environments.create` | | 3 | `upload_log()` | `client.beta.files.upload` | | 4 | `start_session()` | `client.beta.sessions.create` | | 5 | `stream_reply()` | `client.beta.sessions.events.stream` + `.send` | | 6 | `handle_tool()` | 本地运行 —— 读取 `data/*.json` | | 7 | `delete_session()` | `client.beta.sessions.delete` | 其他所有内容 —— system prompt、工具 schema、聊天 UI、session 选择器 —— 都存放在 `provided.py` 中。 ## 故障事件 `data/` 提供了一个非常逼真的宕机事件:在 **14:31:18 UTC**,commit `a3f9c21` 被部署到了结账服务(checkout service),将批量查询替换为了逐行循环。几分钟之内,p99 延迟就从 65 毫秒攀升到了 3,600 毫秒,数据库连接池(DB connection pool)饱和,并且 20% 的结账开始失败。 证据分布在以下文件中: - `app.log` —— 70,000 行 JSON 日志,agent 必须在其沙箱中进行 grep - `metrics.json` / `deploys.json` / `diff.txt` —— 当 agent 调用 `get_metrics`、`get_recent_deploys` 和 `get_diff` 时返回的内容(这些处理程序在**你的**机器上运行,而不是在云端 —— 这正是关键所在) Agent 必须将这四者关联起来才能指出根本原因。它做到了。 ## 这展示了什么 - **Agent → Environment → Session → Events** —— 四个 Managed Agents 资源,按照 [快速入门](https://platform.claude.com/docs/en/managed-agents/quickstart) 中介绍的顺序 - **沙箱代码执行** —— agent 在你无需配置的托管容器中编写并运行 Python - **自定义工具(Custom tools)** —— 云端的 agent 通过事件流(event stream)调用你笔记本上的函数;将 mock 的 JSON 替换为 Datadog 客户端,它就可以用于生产环境了 - **有状态的 session** —— 聊天框上方的下拉菜单通过 `sessions.list()` 列出了过去的所有 session;选择一个,对话就会从 `events.list()` 重新加载。不需要数据库,也不需要本地状态。 ## 仓库布局 ``` agent.py ← the agent: seven functions, one Managed Agents call each agent_complete.py ← reference implementation provided.py ← system prompt, tool schemas, chat UI, session picker e2e.py ← headless test of the full path app.py ← incident overview pages/ ← Metrics, Logs, Deploys data/ ← log + metrics + deploys + diff fixtures ui.py, assets/ ← styling ``` ## 代码库详解 ### 启动序列 `streamlit run app.py` 在绘制任何内容之前会做四件事: 1. `load_dotenv()` 读取 `.env`,以便 `anthropic.Anthropic()`(在 `agent.py` 的导入阶段仅实例化一次)能够获取 `ANTHROPIC_API_KEY`。 2. `inject_style()`(`ui.py`)将 `assets/style.css` 内联到页面中。 3. 如果 `data/app.log` 尚不存在,`data/generate_log.py` 会构建它 —— 这是一个确定性的(带有随机种子)、约 6 万行、每行一个 JSON 的测试数据,时间跨度为 14:00–15:00 UTC,其中 N+1 回归问题被设定为从 14:31:18 开始。 这只运行一次;之后的每次启动都只会执行一次 `Path.exists()` 检查。 4. `st.navigation([...])` 注册四个页面 —— **Overview**(`app.py` 本身)、**Metrics**、**Logs**、**Deploys**(`pages/*.py`)—— 并运行当前处于活动状态的页面。 每个页面都遵循相同的布局:一个包含仪表板内容的宽 `main` 列,以及一个从 `provided.py` 调用 `chat_panel()` 的窄 `side` 列。从应用中的任何位置都可以访问该 agent,因为每个页面只需要进行那一次函数调用即可。 ### 四个 Managed Agents 资源 `agent.py` 刻意保持精简 —— 七个函数,每个对应一次 API 调用,建立起一条生命周期长于单次聊天轮次的资源链: ``` agent (model + system prompt + tools) ─┐ environment (cloud sandbox) ├─▶ session ─▶ events (stream) uploaded log file (app.log) ─┘ ``` - `setup_agent()` / `setup_environment()` / `upload_log()` 被包装在 `@st.cache_resource` 中,因此它们在每个 Streamlit 服务器进程中只运行一次,而不是每次页面加载或每条聊天消息时都运行 —— agent 定义、沙箱和上传的日志在该进程的每个 session 和每个用户之间都是共享复用的。 - `start_session()` 将一个新的 `agent` 和 `environment` 对绑定在一起,并将上传的日志挂载到沙箱内的 `/mnt/session/uploads/app.log`。仅当用户在聊天面板中点击 **+** 时才会创建新的 session —— 从不自动创建 —— 因此刷新页面不会产生云端资源。 - `stream_reply()` 是单次聊天轮次的请求/响应循环:它打开 session 的事件流(event stream),将用户的消息作为 `user.message` 事件发送,然后遍历该流。两种工具服务同时存在: - `agent_toolset_20260401` —— 沙箱自带的代码执行工具。 agent 在其托管容器内编写并运行 Python(例如用于对 `app.log` 进行 `grep` 或解析);这些 `agent.tool_use` 事件永远不会离开云端,也不需要在这边进行处理。 - `get_metrics` / `get_recent_deploys` / `get_diff` —— 在 `provided.TOOLS` 中被声明为 `type: "custom"` 工具。当 agent 调用其中一个时,事件会以 `agent.custom_tool_use` 的形式返回;`stream_reply()` 将其路由到 `handle_tool()`,后者根据在 `provided.py` 中从 `data/` 加载的 JSON/文本做出回答,并将结果作为 `user.custom_tool_result` 事件发回,以便 agent 可以继续运行。这就是上面提到的“将 mock 的 JSON 替换为 Datadog 客户端”的切入点 —— agent 通过这些工具看到的所有内容,都是由在你机器上运行的代码(而不是在沙箱中运行的代码)所获取的。 - `delete_session()` 在用户点击垃圾桶图标时销毁 session —— session 是需要计费的云端资源,而不是本地对象。 ### 一次完整的聊天轮次 ``` user types in st.chat_input │ ▼ agent.stream_reply(session_id, text) │ events.send({"type": "user.message", ...}) ▼ events.stream() yields: agent.message → append text, live-render in st.empty() agent.tool_use → sandbox code exec; shown as a collapsed status box agent.custom_tool_use → handle_tool() runs locally, result sent back user.custom_tool_result → status box filled in with the result session.status_idle → stop_reason == "end_turn" ⇒ break the loop │ ▼ provided.chat_panel() appends the assistant turn to st.session_state.hist ``` `provided.py` 拥有所有 UI 形状的内容,从而使 `agent.py` 保持纯粹的 API 调用:构建 agent 所使用的 system prompt(`SYSTEM`)和工具 schema(`TOOLS`)、在导入时仅加载一次的 `data/*.json` 固定数据(fixtures),以及 `chat_panel()` 本身 —— session 下拉菜单(`sessions.list()`)、为恢复 session 而进行的历史记录重放(`sessions.events.list()`,折叠连续的 `agent.message` 增量并内联渲染工具调用),以及上面描述的实时流式传输渲染循环。 除了当前浏览器标签页的 `st.session_state` 之外,聊天状态被刻意不保存在任何本地位置 —— session 选择器通过从 Managed Agents API 重放 `events.list()` 来重新加载对话,因此关闭标签页不会丢失任何内容。
标签:AIOps, Claude, CVE检测, Kubernetes, LLM Agent, SRE, 偏差过滤, 根因分析, 运维监控, 逆向工具