BasitS-hash/incident-response-agent

GitHub: BasitS-hash/incident-response-agent

基于 LangGraph 多 Agent 架构的 AI 事件响应自动化系统,自动完成告警分诊、根因分析并设有人工审批关卡,帮助 SRE 团队加速线上故障排查与通知流程。

Stars: 0 | Forks: 0

事件响应 Agent

一个 AI 多 agent 系统,可自动执行事件分流、根因分析和待命通知——在发送任何内容之前,设有强制的人工介入(human-in-the-loop)审批关卡。

使用 LangGraph、MCP、Mem0、Langfuse、FastAPI 和 React 19 构建。

CI CodeQL Security Coverage Python License: MIT

## 它的功能 当事件触发时,SRE 通常需要手动: - 拉取日志和指标 - 找出发生了什么变化(部署、配置) - 撰写根因分析 - 通知待命团队 这个 agent 会自动完成所有这些工作——并在发送任何通知之前暂停以等待人工审批。 **告警触发 → Agent 调查 → 人工审批 → 团队通知** ## 5-Agent 工作流 ``` Intake → Triage → RCA → Approval (HITL pause) → Notify ``` | Agent | 它的功能 | |-------|-------------| | **Intake** | 从 Jira 获取事件详情(标题、描述、报告人、优先级) | | **Triage** | 分配严重程度(P1–P4),识别受影响的系统,查询 Mem0 以获取类似的过往事件 | | **RCA** | 查询日志、指标和部署历史——LLM 识别根因并推荐修复方案 | | **Approval** | 人工介入中断——工作流暂停,直到授权审批者接受或拒绝 | | **Notify** | 向待命团队发送包含完整 RCA 摘要的电子邮件通知 | ## 架构 ``` flowchart LR subgraph Browser["React 19 + Vite frontend"] UI["Workflow stepper · Chat log · HITL approval modal · Run history"] end subgraph API["FastAPI backend"] direction TB AUTH["X-API-Key auth · rate limiting · input validation · security headers"] GRAPH["LangGraph state machine (MemorySaver checkpoint)"] AUDIT[("SQLite audit log")] end subgraph Agents["Agent graph"] direction LR I["Intake"] --> T["Triage"] --> R["RCA"] --> A{"Approval
(interrupt)"} A -- approved --> N["Notify"] A -- rejected --> R end subgraph Tools["MCP tool server"] JIRA["Jira"] LOGS["Logs / Metrics / Deploys"] MAIL["Email"] end EXT["LLM (Gemini / OpenAI) · Mem0 memory · Langfuse tracing"] UI -- "POST /incident" --> AUTH UI <-. "SSE /stream" .-> AUTH AUTH --> GRAPH --> Agents Agents --> Tools Agents --> EXT GRAPH --> AUDIT ``` 图在 **`approval` 节点之前中断**。状态会被 checkpoint,因此工作流 可以无限期地暂停等待人工操作,并从它暂停的位置准确恢复——这正是 让人工介入关卡变得可靠而非竞争条件的原因。 ## 截图 ## 技术栈 | 层级 | 技术 | |-------|-----------| | **编排** | [LangGraph](https://langchain-ai.github.io/langgraph/) — 带有 MemorySaver checkpoint 以实现 HITL 持久化的有状态多 agent 工作流 | | **LLM** | 通过 `langchain-google-genai` 使用 Google Gemini 2.5 Flash(通过 `LLM_PROVIDER=openai` 切换至 OpenAI) | | **工具** | [MCP](https://modelcontextprotocol.io/) — 模块化工具服务器(Jira、日志、指标、电子邮件) | | **记忆** | [Mem0](https://mem0.ai/) — 跨运行记住过往事件和解决方案 | | **可观测性** | [Langfuse](https://langfuse.com/) — 完整的 LLM 追踪、token 使用情况、每个 agent 的延迟 | | **流式传输** | [AG-UI](https://github.com/ag-ui-protocol/ag-ui) — 用于实时前端更新的 SSE 协议 | | **后端** | FastAPI + uvicorn | | **前端** | React 19 + TypeScript + Vite | | **审计日志** | SQLite — 持久化记录每次运行及其 agent 输出、审批决策和时间戳 | | **速率限制** | slowapi — POST /incident 限制为 10 req/min,POST /approve 限制为 20 req/min | ## 演示事件 | ID | 服务 | 问题 | 严重程度 | |----|---------|-------|----------| | `INC-101` | Auth 服务 | 部署导致 Redis 连接池减少 → 97% 缓存未命中率 → OOMKill | P1 | | `INC-205` | 支付服务 | ORM 迁移未迁移连接池配置 → PostgreSQL 连接耗尽 | P2 | | `INC-312` | 通知服务 | 营销部署意外将取消订阅逻辑应用于事务性电子邮件 → AWS SES 被暂停 | P2 | ## 项目结构 ``` incident-response-agent/ ├── backend/ │ ├── agents/ │ │ ├── intake_agent.py # Fetches incident from Jira │ │ ├── triage_agent.py # Assigns severity and affected systems │ │ ├── rca_agent.py # Root cause analysis via logs + LLM │ │ ├── notify_agent.py # Sends email notification │ │ └── llm_factory.py # Gemini / OpenAI provider switch │ ├── api/ │ │ └── main.py # FastAPI routes + SSE streaming + rate limiting │ ├── audit/ │ │ └── log.py # SQLite audit log — persists every run │ ├── data/ # Runtime SQLite DB (gitignored) │ ├── graph/ │ │ ├── workflow.py # LangGraph graph definition │ │ ├── nodes.py # Node wrappers + routing logic │ │ └── state.py # IncidentState schema │ ├── mcp_server/ │ │ └── tools/ │ │ ├── jira_tools.py # Jira integration (mock → real via API token) │ │ ├── log_tools.py # Log/metrics/deployment data (mock → Splunk/Loki) │ │ └── email_tools.py # Email sending (mock → SMTP/SendGrid) │ ├── memory/ │ │ └── mem0_client.py # Mem0 for cross-run incident memory │ ├── observability/ │ │ └── langfuse_client.py # Langfuse tracing │ ├── config.py # Env var loading │ └── requirements.txt ├── frontend/ │ └── src/ │ ├── components/ │ │ ├── ChatUI.tsx # Real-time chat event log │ │ ├── WorkflowStepper.tsx # Visual 5-step progress indicator │ │ ├── IncidentDetails.tsx # Live state panel │ │ ├── HITLApprovalModal.tsx # Human review modal │ │ └── RunHistory.tsx # Audit log table with search/filter │ ├── hooks/ │ │ └── useAgentStream.ts # SSE event consumer │ └── api/ │ └── client.ts # Axios API client ├── tests/ # 146 tests, 87% coverage, no network/creds needed │ ├── conftest.py # Shared FakeLLM fixture + mocks │ ├── test_agents.py # Agent helper functions │ ├── test_agent_pipeline.py # Full agent run_* functions with mocked LLM │ ├── test_api.py # Input validators + safe-state allowlist │ ├── test_api_endpoints.py # HTTP-level auth / validation / response shape │ ├── test_audit_log.py # SQLite audit log store │ ├── test_clients.py # Mem0 / Langfuse graceful degradation │ ├── test_config.py # Startup config validation │ ├── test_graph.py # Graph routing + node wiring │ ├── test_mcp_server.py # MCP tool registrations │ └── test_tools.py # Enrichment tools (logs/metrics/jira/email) ├── .github/ │ ├── workflows/ │ │ ├── ci.yml # Lint (ruff) + type-check (mypy) + pytest + frontend build │ │ ├── security.yml # bandit + pip-audit + gitleaks + Trivy image scan │ │ └── codeql.yml # CodeQL (python + js/ts), security-extended │ └── dependabot.yml # Weekly pip / npm / docker / actions updates ├── backend/Dockerfile # Non-root, healthcheck'd backend image ├── docker-compose.yml # Local Langfuse + Postgres observability stack ├── pyproject.toml # ruff / pytest / coverage / mypy config ├── start.sh # macOS one-click startup ├── start.ps1 # Windows one-click startup └── .env # Secrets — never committed ``` ## 在本地运行 ### 前置条件 - Python 3.11+ - Node.js 18+ - 项目根目录下的 `.env` 文件(见下文) ### 快速开始 (macOS) ``` ./start.sh ``` 自动在单独的终端窗口中打开两个服务器。 ### 快速开始 (Windows) ``` .\start.ps1 ``` ### 手动启动 **后端**(从项目根目录运行): ``` python -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\Activate.ps1 pip install -r backend/requirements.txt uvicorn backend.api.main:api --reload --port 8000 ``` **前端:** ``` cd frontend npm install npm run dev ``` 打开 **http://localhost:5173**(如果 5173 被占用,则为 5174)。 ### 运行测试 ``` source .venv/bin/activate pip install -r backend/requirements.txt -r backend/requirements-dev.txt pytest tests --cov=backend --cov-report=term-missing ``` **146 个测试,87% 的覆盖率** — 无需网络、LLM 密钥或外部服务。LLM 和 所有外部调用(Mem0、Jira、SMTP)均通过 `tests/conftest.py` 中的 fixtures 进行 mock。 ### 代码检查与安全扫描(运行 CI 所执行的操作) ``` ruff check backend tests # lint mypy backend # type-check bandit -r backend -ll # static security analysis pip-audit -r backend/requirements.txt # dependency CVE audit ``` ### Docker ``` docker build -f backend/Dockerfile -t ir-agent-backend . docker run -p 8000:8000 --env-file .env ir-agent-backend ``` ## 环境变量(项目根目录下的 `.env`) ``` # LLM — 必需 GEMINI_API_KEY=your_gemini_key # LLM provider — "gemini"(默认)或 "openai" LLM_PROVIDER=gemini OPENAI_API_KEY= # required if LLM_PROVIDER=openai # API auth — 留空以在 dev mode 下运行(无需 key) API_KEY= # Jira(可选 — 未设置则使用 mocked) JIRA_URL=https://yourorg.atlassian.net JIRA_EMAIL=you@yourorg.com JIRA_TOKEN=your_jira_api_token # Email / SMTP(可选 — 未设置则使用 mocked) SMTP_HOST=smtp.gmail.com SMTP_PORT=587 SMTP_USER=you@gmail.com SMTP_PASSWORD=your_app_password # Observability(可选 — 未设置则优雅降级) MEM0_API_KEY=your_mem0_key LANGFUSE_PUBLIC_KEY=your_public_key LANGFUSE_SECRET_KEY=your_secret_key LANGFUSE_HOST=http://localhost:3001 # local Docker instance ``` ## API 端点 | 方法 | 路径 | 认证 | 描述 | |--------|------|------|-------------| | `POST` | `/incident` | API key | 启动新的事件工作流 | | `GET` | `/stream/{run_id}` | — | AG-UI 事件的 SSE 流 | | `POST` | `/approve/{run_id}` | API key | 提交批准 / 拒绝 | | `GET` | `/runs` | API key | 列出所有过往运行(审计日志) | | `GET` | `/runs/{run_id}` | API key | 单次运行的完整详情 | | `GET` | `/incidents/search` | API key | 对 Mem0 记忆进行语义搜索 | | `GET` | `/health` | — | 健康检查 | ## 将 Mock 替换为真实集成 所有组件都设有明确的替换点——agent 逻辑不变,仅数据源改变。 | Mock | 真实集成 | 需更改的内容 | |------|-----------------|----------------| | Jira mock | Jira REST API | 在 `.env` 中设置 `JIRA_URL`、`JIRA_EMAIL`、`JIRA_TOKEN` | | 日志 mock | Splunk / Loki / Datadog | 替换 `log_tools.py` 中的 `query_system_logs()` | | 电子邮件 mock | Gmail / SendGrid / SES | 在 `.env` 中设置 `SMTP_*` 变量 | | SQLite checkpointer | PostgreSQL | 在 `workflow.py` 中将 `MemorySaver` 换成 `PostgresSaver` | ## 安全性 - **认证** — POST 端点和审计日志由 `X-API-Key` 请求头保护;空白的 `API_KEY` 会启用开发模式 - **速率限制** — `POST /incident` 限制为 10 req/min,`POST /approve` 限制为 20 req/min - **输入验证** — 强制执行事件 ID 格式(`INC-NNNN`),审批人姓名和备注经过清理以防止提示词注入(去除控制字符,强制限制最大长度) - **状态白名单** — 内部字段(`notification_recipients`、`messages`、`similar_incidents`)永远不会发送到浏览器 - **记忆注入上限** — Mem0 上下文被截断为每条记录 500 个字符,以防止 RAG 数据投毒 - **安全标头** — 每个响应都包含 `X-Content-Type-Options`、`X-Frame-Options`、`Referrer-Policy` - **Langfuse TLS** — 如果 `LANGFUSE_HOST` 指向通过普通 HTTP 连接的远程主机,则会发出警告 - **启动验证** — `validate_config()` 在缺少 LLM 密钥时会快速失败,并在禁用身份验证时发出强烈警告 - **无提交的密钥** — 所有凭证均来自环境变量;参见 [`SECURITY.md`](./SECURITY.md) 有关漏洞报告和完整的安全态势,请参见 [`SECURITY.md`](./SECURITY.md)。 ## 工程实践 | 领域 | 工具 | |------|---------| | **CI** | GitHub Actions — ruff lint、mypy 类型检查、pytest(Python 3.11 和 3.12 矩阵)、前端构建 | | **覆盖率门禁** | CI 中强制执行 `--cov-fail-under=80` | | **SAST** | 每次推送/PR 时运行 Bandit | | **依赖审计** | pip-audit(每周及 PR 时) | | **密钥扫描** | 对完整历史记录运行 gitleaks | | **容器扫描** | 对构建的后端镜像 + 文件系统运行 Trivy(SARIF → GitHub Security 选项卡) | | **代码扫描** | 针对对 Python 和 TypeScript 运行 CodeQL(`security-extended`) | | **依赖更新** | Dependabot — pip、npm、Docker、GitHub Actions | | **可复现性** | 完全锁定的 `requirements.txt` | ## 路线图 - [ ] PagerDuty / Prometheus webhook 触发器(零接触事件创建) - [ ] Slack / Teams 通知渠道 - [ ] 审批模态框上的 SSO(限制为授权的 SRE) - [ ] 拒绝流程结合审批人反馈重新运行 RCA - [ ] 真实的 Jira、电子邮件和日志集成(凭证待定) ## 许可证 在 [MIT 许可证](./LICENSE)下发布。 ## 作者 **Basit Sherazi** — 网络安全与 AI 工程
标签:LangGraph, SRE, 偏差过滤, 多智能体, 库, 应急响应, 网络调试, 自动化, 请求拦截, 运维, 逆向工具