cameronqj/incident-response-agent
GitHub: cameronqj/incident-response-agent
一个人工审批驱动的受限事件响应实验项目,用于在一次性沙箱中安全地验证 remediation 工作流。
Stars: 0 | Forks: 0
# 事件响应 agent
`incident-response-agent` 是一个受限的 incident-response 实验。它接收本地事件,收集受限的证据,生成结构化的 remediation 提案,等待明确的人工决策,并仅在一次性环境内执行与场景和证据类型兼容的 allowlisted 操作。
## 它的功能
- 使用合成的 marker fixtures 演示磁盘耗尽、CPU 压力、内存压力、restart-loop 和 log-storm 工作流。
- 提供一个可选的实验室,用于检测真实且不健康的一次性 container 服务,使用 demo 或 live 推理,并仅在批准后重启该特定服务。
- 在一次性 containers 中分别验证真实的受限 ENOSPC 和 OOM 行为。
- 强制执行幂等接收、不可变的 proposal/action-digest 批准、原子性 SQLite 状态声明、执行过期以及 expire-and-retain 语义。
- 记录已脱敏的 state、model、approval、execution、retry、failure 和 actor 观察结果;赋值式和 JSON 格式的凭据在事件持久化之前会被脱敏。
- 支持确定性的离线分析和可选的、通用的、兼容 OpenAI 的 live-inference 适配器。
## 它不能做什么
这不是生产级别的 incident response。它不会检查或 remediate 宿主机或生产进程和服务,不对生产 webhooks 进行身份验证,不提供生产身份或 RBAC,不执行模型生成的命令,也不提供自主 remediation。Marker 移除测试主要针对工作流、策略、批准、持久化和审计行为;只有明确启用的 container-service 实验室会执行真实的重启,并且仅针对它创建并拥有的服务。
## 快速开始
为每个 Python 命令使用项目虚拟环境:
```
./scripts/bootstrap.sh
.venv/bin/python -m incident_response_agent.cli demo
```
引导脚本会创建 `.venv`,仅安装到该环境中,创建或迁移 `.data/incident-response.sqlite3`,并运行离线测试套件。它不会创建、复制、打印或修改 `.env`。`SQLiteStore` 也会在正常启动时初始化和迁移 schema,因此此 POC 不需要单独的迁移服务。要在不启动 API 的情况下初始化不同的路径:
```
.venv/bin/python -m incident_response_agent.cli init-db --database-path .data/incident-response.sqlite3
```
CLI 演示使用进程拥有的一次性 sandbox 和确定性 fake model。它不需要 bearer token、container engine、网络或 API key。
如需真实的 disposable-service 恢复周期,请使用 bearer token 和正常工作的 Podman/Docker engine。该命令会显示不可变的 proposal,并在重启任何内容之前等待 `approve`:
```
export INCIDENT_AGENT_BEARER_TOKEN='replace-with-a-local-random-token'
APP_MODE=demo EXECUTION_ENGINE=container \
.venv/bin/python -m incident_response_agent.cli container-service-demo
```
在相同的周期中设置 `APP_MODE=live` 以使用配置的通用 inference 适配器。Live 模式需要其 API-key 环境变量,并且永远不会回退到 demo 推理。
运行离线测试套件:
```
.venv/bin/python -m pytest -m 'not integration and not live'
```
## 本地 API 访问
HTTP API 默认绑定到 `127.0.0.1`。所有 mutating endpoints 都需要一个环境配置的 POC bearer token。如果没有 token,mutations 将被禁用;环回地址的 `GET /runs/{run_id}` 检查仍然可用。非环回地址绑定要求对每个 endpoint 进行身份验证。
```
export INCIDENT_AGENT_BEARER_TOKEN='replace-with-a-local-random-token'
HOST=127.0.0.1 EXECUTION_ENABLED=0 APP_MODE=demo \
.venv/bin/python -m incident_response_agent.cli serve
```
本地模拟示例:
```
curl -X POST http://127.0.0.1:8000/events \
-H "Authorization: Bearer ${INCIDENT_AGENT_BEARER_TOKEN}" \
-H 'Content-Type: application/json' \
-d '{"idempotency_key":"demo-001","source":"local_simulation","observed_at":"2026-07-19T12:00:00Z","payload":{"scenario":"disk-exhaustion","summary":"synthetic fixture","log_lines":[],"context":[]}}'
```
这个单一的 bearer token 仅用于 POC 级别的访问控制。它不提供用户、角色、身份联合,或者批准与执行权限之间的分离。Tokens 仅通过 `Authorization` header 接受。
Remediation 执行默认被禁用。启用它需要 bearer token 和 Podman/Docker 执行器:
```
EXECUTION_ENABLED=1 EXECUTION_ENGINE=container \
.venv/bin/python -m incident_response_agent.cli serve
```
HTTP 服务永远不会启用文件系统执行器。Runtime 执行会创建自己的一次性 sandbox,并使用 digest-pinned、非 root、网络隔离且只读的 container,并具有 CPU、内存、PID、临时文件系统和超时限制。
要通过相同的本地 HTTP endpoints 运行真实的服务场景,请显式选择实验室模式:
```
INCIDENT_AGENT_BEARER_TOKEN='replace-with-a-local-random-token' \
EXECUTION_ENABLED=1 LAB_MODE=container-service APP_MODE=demo \
.venv/bin/python -m incident_response_agent.cli serve
```
在此模式下,服务会在内部创建一个目标 container,等待其受限的健康检查报告为 `unhealthy`,并且仅接受 `restarting-service` 场景。事件接收、inference、提案修订、批准、过期、执行声明和审计使用现有的 API 和 SQLite 工作流。无论是请求还是模型,都无法提供目标、image、挂载、路径或命令。
## Container 故障实验室
如果需要,请先初始化 Podman 一次,然后运行集成测试套件:
```
podman machine init --rootful podman-machine-default
podman machine start podman-machine-default
RUN_CONTAINER_TESTS=1 .venv/bin/python -m pytest -m 'integration and not live'
```
当 Podman 不可用时,会自动使用 Docker。缺失的固定多架构 image 可能会通过 digest 获取。ENOSPC 和 OOM 测试是真实的、受限的 `container_fault` 检查,但仍然独立于 agent 流程。Container-service 集成也是 `container_fault` 证据:真实的服务返回 HTTP 503,变为 OCI-unhealthy,在批准后重启,并最终变为 healthy。其他 agent 场景仍然是 `synthetic_marker` fixtures。
## 通用 live inference
可选的 live 测试执行配置的兼容 OpenAI 的 chat-completions 契约。它不是 OpenCode 集成或通用的提供商兼容性声明。
```
RUN_LIVE_TESTS=1 .venv/bin/python -m pytest -m live
```
默认值为 base URL `https://opencode.ai/zen/go/v1`、model `deepseek-v4-flash` 和 API-key 环境变量 `OPENCODE_KEY`。它们可以通过 `MODEL_BASE_URL`、`MODEL_NAME` 和 `MODEL_API_KEY_ENV` 进行配置。Live 模式在其 key 缺失时会明确失败,并且永远不会回退到 fake inference。
在解析之前,会通过 65,536 字节的硬限制来读取 live 提供商的响应。结构化评估摘要限制为 2,000 个字符,`evidence_refs` 最多 20 项且每项不超过 500 个字符,并且未知字段会被拒绝。
组合的 real-model/real-service 周期需单独选择启用:
```
RUN_CONTAINER_TESTS=1 RUN_LIVE_TESTS=1 .venv/bin/python -m pytest -m live
```
## 可选的 OpenTelemetry
OpenTelemetry traces 和 metrics 默认被禁用。SQLite 审计历史记录仍然是持久化的单一事实来源。要导出 OTLP/HTTP 到本地 collector:
```
OTEL_ENABLED=1 \
OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:4318 \
OTEL_SERVICE_NAME=incident-response-agent \
.venv/bin/python -m incident_response_agent.cli serve
```
手动 spans 涵盖事件接收、telemetry 收集、model 分析、proposal 创建与决策、remediation 执行/工具调用以及过期。Metrics 涵盖事件到 proposal 的时间、model 延迟/tokens/重试、批准等待、执行结果和过期。FastAPI 请求 spans 和标准 HTTP metrics 也会被启用。
导出器属性被刻意限制得很窄:生成的 workflow ID、proposal 修订版本、场景/类型、allowlisted 操作 ID、决策、结果、原因代码、计数和持续时间。不会导出 Authorization headers、事件体、prompts、证据或模型文本、logs、路径、API keys、tokens 以及任意的模型输出。HTTP 导出器只能指向环回地址;远程 collectors 需要 HTTPS。此 POC 不配置生产环境的 collector、身份验证、采样策略、仪表板、警报或 telemetry 保留策略。
collector 集成测试使用 digest-pinned 的一次性 OpenTelemetry Collector,并需与其他 container 证据一起选择启用:
```
RUN_CONTAINER_TESTS=1 .venv/bin/python -m pytest tests/test_otel_collector_integration.py
```
## 证据等级
离线测试为 schemas、身份验证、脱敏、幂等性、批准网关、原子声明、过期、场景/操作类型兼容性、sandbox 验证、持久化、审计行为以及内存中的 OpenTelemetry 导出提供确定性证据。Container 测试为受限故障、一次真实的一次性服务重启以及向一次性 collector 的 OTLP 传递提供单独标记的证据。Live model 行为属于可变的集成证据,而不是确定性测试证据。请参阅 `docs/evidence.md` 和 `SECURITY.md`。
标签:AIOps, Python, 无后门, 用户代理, 自动化故障修复, 请求拦截, 运维, 逆向工具