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, 无后门, 用户代理, 自动化故障修复, 请求拦截, 运维, 逆向工具