运维指挥Ops Commander
可恢复的事故 CopilotA resumable incident copilot
项目计时Project clock
能专注时再开始。计时与截止保存在本机浏览器;离开时记得暂停。Start when you can focus. The clock and deadline persist in this browser; pause whenever you leave.
项目简报Brief
值班工程师凌晨收到 P1 告警。Agent 必须通过 MCP 读取 runbook、收集诊断证据、给出缓解方案;执行破坏性操作前必须请求人工审批;如果进程重启,能够从同一会话恢复并继续,而不是重新开始。
An on-call engineer gets a P1 alert at 3 a.m. The agent must read runbooks over MCP, collect diagnostic evidence and propose mitigation; destructive actions require human approval; if the process restarts, it resumes the same session instead of starting over.
可恢复的事故 Copilot:MCP 工具接入、审批闸门、状态持久化、结构化 trace 与 3 次演练评测,最终产出带引用的 postmortem。
A resumable incident copilot: MCP tooling, an approval gate, state persistence, structured traces and three incident drills, ending in a cited postmortem.
产物契约Artifact contract
先冻结产物形状,再写 Agent。后续里程碑与评测都读取这份契约。Freeze the shape before writing the agent. Every later milestone and evaluation reads this contract.
{
"incident_id": "INC-2401",
"stage": "mitigation_pending_approval",
"evidence": ["runbook:db-pool#step-3", "metric:pool_wait_p99"],
"proposed_action": "raise pool size to 40",
"approval": {"status": "pending", "approver": null},
"idempotency_key": "INC-2401:pool:40",
"resume_token": "sess-ops-2401"
}
里程碑Milestones
每条验收成立后再勾选里程碑。小时数是预算,不是秒表目标。Check each milestone only when its acceptance holds. Hours are a budget, not a stopwatch target.
-
通过 stdio 启动 runbook 服务;完成发现、调用、超时与关闭;工具输出按不可信数据处理。
Start the runbook service over stdio; discover, call, time out and close; treat tool output as untrusted data.
验收Acceptance工具列表与 runbook 服务一致;超时可控;
finally关闭无残留子进程。The tool list matches the server; timeouts are bounded; finally closes with no orphan processes.
-
分诊 → 证据 → 缓解方案 → 人工审批 → 执行;破坏性动作必须有审批记录;verifier 决定是否继续。
Triage → evidence → mitigation → human approval → execute; destructive actions need an approval record; a verifier decides whether to continue.
验收Acceptance演练中所有破坏性动作都有 pending/approved 记录;未批准时不会执行。
In drills, every destructive action has a pending/approved record; nothing executes before approval.
-
每个阶段后持久化 AgentState;重启后用同一 session id 恢复;已执行动作靠幂等键去重。
Persist AgentState after each stage; resume with the same session id after a restart; dedupe executed actions with idempotency keys.
验收Acceptance中途杀掉进程再恢复,流程从原阶段继续;同一缓解动作不会执行两次。
Kill the process mid-flow and resume from the same stage; the same mitigation does not run twice.
-
结构化 trace + 指标;跑 3 个演练(数据库连接池、缓存击穿、发布回滚);统计安全闸门与恢复成功率。
Structured traces and metrics; run three drills (DB pool, cache stampede, release rollback); measure safety gates and resume success.
验收Acceptance3 个演练全部通过审批闸门;至少 1 次重启恢复;指标可复算。
All three drills pass the approval gate; at least one restart-resume; metrics are recomputable.
-
写 postmortem:时间线、根因、行动、引用、回滚与未解问题;用费曼方式解释“为什么要保存阶段与幂等键”。
Write the postmortem: timeline, root cause, actions, citations, rollback and open questions; explain in Feynman style why stage and idempotency keys must persist.
验收Acceptance每条行动可定位到 runbook/指标;README 能让同事复现一次演练。
Every action maps to a runbook section or metric; a colleague can reproduce one drill from the README.
交付物Deliverables
每项交付物必须真实存在且可复现。完成门槛会检查全部勾选,再要求复盘。Every deliverable must exist on disk and be reproducible. The finish gate checks all boxes, then asks for a reflection.
-
阶段、工具调用、证据、审批状态与恢复点;每行可独立解析。
Stage, tool calls, evidence, approval state and resume point; each line parses independently.
-
时间线、根因、缓解、引用、未解问题与回滚方案;每条行动带证据。
Timeline, root cause, mitigation, citations, open questions and rollback; every action is backed by evidence.
-
会话 id、上下文、阶段、已执行动作与幂等键;重启后可继续。
Session id, context, stage, executed actions and idempotency keys; survives a restart.
-
每阶段耗时、token、工具调用次数、审批等待与错误;可按事故聚合。
Per-stage latency, tokens, tool calls, approval wait and errors; aggregate by incident.
-
3 个事故演练:全部完成审批闸门;重启恢复至少 1 次;无重复副作用。
Three drills: all pass the approval gate, at least one restart-resume, and no duplicated side effects.
-
MCP 启动方式、环境变量、恢复与审批流程、安全边界。
MCP launch, environment variables, resume and approval flow, and safety boundaries.
评分表Rubric
宣告完成前诚实自评。低于 80 分意味着该迭代,而不是该交付。Grade yourself honestly before calling it done. Anything below 80 is a signal to iterate, not to ship.
| 评分项Criterion | 分值Points | 达标标准What good looks like |
|---|---|---|
| 安全与审批Safety and approval | 30 | 破坏性动作全部经过审批;未批准不执行;拒绝有记录。 All destructive actions are approved first; nothing runs before approval; refusals are recorded. |
| 状态与恢复State and resume | 25 | 阶段、上下文、幂等键持久化;重启可继续;无重复副作用。 Stage, context and idempotency keys persist; restart resumes; no duplicated side effects. |
| MCP 与工具MCP and tools | 20 | 发现、调用、超时、关闭完整;不可信输出被隔离与限长。 Discovery, calls, timeouts and close are complete; untrusted output is isolated and length-limited. |
| 可观测与演练Observability and drills | 15 | trace 结构化、指标可聚合;3 个演练结果可复算。 Structured traces and aggregatable metrics; three drill results are recomputable. |
| 复盘与文档Postmortem and docs | 10 | postmortem 有引用、有回滚、有未解问题;README 可复现。 The postmortem has citations, rollback and open questions; the README reproduces. |
| 合计Total | 100 |
双轨实现Build on your track
交付物不绑定语言。按团队需要选择轨道;完成记录会保存你交付所用的轨道。The deliverable is language-agnostic. Follow the track that fits the team; the finish record stores the track you shipped on.
用 MCPClient + StdioMCPConfig 接入 runbook,用 AgentState 持久化阶段与上下文;审批与幂等键是业务状态,不是提示词。
Use MCPClient + StdioMCPConfig for the runbook and AgentState to persist stage and context; approval and idempotency keys are business state, not prompts.
MCP 生命周期MCP lifecycle
stdio 配置命令、参数、cwd 与环境;finally 关闭客户端;工具输出限长并当数据。
Configure command, args, cwd and env for stdio; close the client in finally; cap tool output and treat it as data.
审批闸门Approval gate
执行类工具先查审批记录;pending 时返回等待,不执行;批准后带幂等键执行。
Execution tools check the approval record first; pending returns a wait without executing; approved runs with an idempotency key.
恢复Resume
每阶段后 state.model_dump_json() 落盘;重启加载同一 AgentState 和 session id;已执行动作查幂等键。
Dump state.model_dump_json() after each stage; reload the same AgentState and session id on restart; check idempotency keys for executed actions.
client = MCPClient(StdioMCPConfig(
command=sys.executable,
args=["-m", "runbook_server"],
cwd=str(runbook_root),
))
try:
tools = await client.list_tools()
assert "lookup_runbook" in [tool.name for tool in tools]
# approval first, execute second, persist after every stage
state_path.write_text(agent.state.model_dump_json(indent=2), encoding="utf-8")
finally:
await client.close()
agentscope.mcp.MCPClientagentscope.mcp.StdioMCPConfigagentscope.state.AgentStateagentscope.agent.Agentagentscope.tool.FunctionTool恢复只保存聊天记录、不保存阶段与已执行动作:重启后会把同一缓解动作再执行一遍。状态必须包含阶段、审批与幂等键。
Persisting only chat history, not stage or executed actions, replays the same mitigation after restart. State must include stage, approval and idempotency keys.
McpClientBuilder 接入 stdio 服务,JsonFileAgentStateStore 按 session 持久化;注意 Java 工具名不带 Python 的 mcp__ 前缀。
Use McpClientBuilder for the stdio server and JsonFileAgentStateStore per session; Java MCP tool names omit Python's mcp__ prefix.
MCP 客户端MCP client
构建客户端后先列工具再启用;调用超时与关闭成对;Java 暴露 lookup_runbook,Python 是 mcp__runbook__lookup_runbook。
List tools before enabling; pair timeouts with close; Java exposes lookup_runbook while Python uses mcp__runbook__lookup_runbook.
审批与执行Approval and execution
用 record 表示审批状态;执行工具校验幂等键;未批准直接返回 blocked。
Represent approval with a record; execution tools check the idempotency key; unapproved calls return blocked.
状态存储State store
JsonFileAgentStateStore + 固定 defaultSessionId;重启用同一 store/session 恢复;流式事件用于 trace。
JsonFileAgentStateStore with a fixed defaultSessionId; resume with the same store/session; use stream events for traces.
AgentStateStore store = new JsonFileAgentStateStore(
work.resolve("state-store"));
try (McpClient client = McpClientBuilder.builder()
.stdio(serverCommand)
.build()) {
ReActAgent agent = ReActAgent.builder()
.name("ops").model(model).toolkit(toolkit)
.stateStore(store).defaultSessionId("INC-2401")
.build();
agent.streamEvents(List.of(Msg.user(alert)), ctx)
.doOnNext(event -> trace(event.getType()))
.blockLast();
}
io.agentscope.core.tool.mcp.McpClientBuilderio.agentscope.core.state.JsonFileAgentStateStoreio.agentscope.core.ReActAgentio.agentscope.core.event.AgentEventType用工具名做审批判断,跨语言就失效:Python 与 Java 的 MCP 工具名不同。审批应绑定业务动作与幂等键,而不是工具名字符串。
Binding approval to tool-name strings breaks across languages: Python and Java MCP names differ. Bind approval to a business action and idempotency key.
进阶与资源Stretch goals and resources
加入“审批拒绝”演练:拒绝后不执行,Agent 给出替代方案并复述风险。
Add an approval-rejection drill: nothing executes, and the agent offers an alternative and restates the risk.
把指标接入真实 tracing(OpenTelemetry),按事故生成火焰图式时间线。
Wire metrics into real tracing (OpenTelemetry) and render a flame-style incident timeline.