diff --git a/docs/openclaw/openclaw-orchestration-flow.md b/docs/openclaw/openclaw-orchestration-flow.md new file mode 100644 index 0000000..037c8bb --- /dev/null +++ b/docs/openclaw/openclaw-orchestration-flow.md @@ -0,0 +1,307 @@ +# OpenClaw → reader MCP 标准编排流程 + +## 1. 文档目的 + +本文档定义 OpenClaw 在正式环境中如何调用 reader 作为上游 MCP workflow service。 + +目标不是描述 reader 内部实现,而是明确 OpenClaw 的编排动作: + +- 什么时候启动新 run +- 什么时候查询状态 +- 什么时候读取结果 +- 什么时候尝试恢复 +- 什么时候直接新开 run +- 什么时候需要人工介入 + +本文档基于 reader 当前**已真实落地**的能力编写,不描述尚未实现的未来接口。 + +--- + +## 2. 当前 reader 已正式支持的 MCP 能力 + +当前可用能力: + +- `run_freshrss_openclaw_pipeline` +- `get_run_status` +- `list_runs` +- `list_run_artifacts` +- `get_delivery_payload` +- `get_run_report` +- `resume_run` + +其中: + +- `run_freshrss_openclaw_pipeline` 是当前正式启动入口 +- `get_run_status` / `list_runs` / `list_run_artifacts` 用于观测 +- `get_delivery_payload` / `get_run_report` 用于读取正式结果 +- `resume_run` 用于最小恢复能力 + +--- + +## 3. 编排基本原则 + +### 3.1 OpenClaw 不再手拼路径 + +OpenClaw 不应再自己拼 reader 输出路径来判断运行状态或读取核心结果。 + +优先使用 MCP: + +- 查状态 → `get_run_status` +- 读 payload → `get_delivery_payload` +- 读 report → `get_run_report` +- 做恢复 → `resume_run` + +只有在排障/人工核查时,才回退到直接看 reader run 目录。 + +### 3.2 reader 是上游 workflow engine + +reader 负责: + +- FreshRSS 拉取 +- 内容提取 +- 摘要 +- 过滤 +- payload 生成 +- run 状态记录 +- 最小恢复 + +OpenClaw 负责: + +- 触发执行 +- 轮询状态 +- 读取结果 +- 生成 digest markdown +- Hugo 发布 +- 聊天汇报 +- 用户确认精选 +- IMA 编排 + +### 3.3 默认生产语义 + +正式生产运行默认: + +- `mark_read=true` +- `debug_artifacts=false` +- 只在 debug/test/validation 时显式放宽 + +--- + +## 4. 标准 Happy Path + +### Step 1: 启动新 run + +调用: + +- `run_freshrss_openclaw_pipeline` + +推荐参数示例: + +```json +{ + "limit": 5, + "mark_read": true, + "include_read": false, + "debug_artifacts": false, + "timeout_seconds": 60, + "max_retries": 2 +} +``` + +期望: + +- 获得 `run_id` +- 获得 `output_dir` +- 获得初始结果摘要 + +如果启动阶段直接抛错: + +- 直接判为启动失败 +- 不进入后续查询 + +### Step 2: 查询运行状态 + +调用: + +- `get_run_status(run_id=...)` + +根据返回: + +- `status=running` → 继续轮询 +- `status=success` → 进入结果读取 +- `status=failed` → 进入失败处理 +- `status=partial` → 视为未完成,优先看 `recovery` 和当前阶段 + +### Step 3: 读取正式结果 + +成功后读取: + +- `get_delivery_payload(run_id=...)` +- `get_run_report(run_id=...)` + +后续 OpenClaw 编排应以这两个接口为正式结果源,而不是自己拼路径读取 JSON。 + +### Step 4: 进入下游编排 + +OpenClaw 在拿到正式 payload / report 后,继续执行: + +- public/internal digest 生成 +- Hugo 发布 +- 聊天汇报 +- 用户确认精选 +- IMA 沉淀 + +--- + +## 5. 状态 → 动作映射 + +| reader 状态 | OpenClaw 动作 | +|---|---| +| `running` | 继续轮询 `get_run_status` | +| `success` | 读取 `get_delivery_payload` 和 `get_run_report` | +| `failed` 且 `recovery.resumable=true` | 评估是否调用 `resume_run` | +| `failed` 且 `recovery.resumable=false` | 直接判失败,通常新开 run 或人工介入 | +| `partial` | 先读状态详情和 recovery,再决定继续等 / 恢复 / 人工介入 | + +--- + +## 6. 失败处理与恢复决策 + +### 6.1 什么时候优先尝试 `resume_run` + +满足以下条件时,优先考虑恢复而不是新开 run: + +- `get_run_status` 返回 `failed` +- `recovery.resumable=true` +- 当前 run 对应的是 freshrss workflow +- 当前失败点在 reader 第一版支持的恢复范围内 + +### 6.2 `resume_run` 当前支持范围 + +当前最小实现仅支持: + +- 仅对带 `run-state.json` 的 freshrss run +- 仅从最近可恢复点继续 +- 支持的恢复点: + - `generate_summaries` + - `apply_filters` + - `build_delivery_payload` + - `write_run_report` + +明确不支持: + +- `fetch_feed` +- `extract_articles` + +### 6.3 什么时候不要恢复,直接新开 run + +以下情况不建议 `resume_run`: + +- `recovery.resumable=false` +- run 没有 `run-state.json` +- 失败点是 `fetch_feed` 或 `extract_articles` +- 恢复所需关键产物缺失 +- 恢复点语义不明确或结果存在明显漂移风险 + +这时更合理的动作通常是: + +- 直接新开 run +- 或人工介入排查 + +### 6.4 什么时候需要人工介入 + +出现以下任一情况时,建议人工介入: + +- 连续恢复失败 +- `get_run_status` 与实际产物明显不一致 +- payload/report 结构不符合预期 +- 恢复依赖的关键文件缺失且原因不明 +- FreshRSS / LLM / 外部环境异常 + +--- + +## 7. 读取结果的标准动作 + +### 7.1 `get_delivery_payload` + +用途: + +- 获取正式交付给 OpenClaw 的 payload +- 后续 digest 生成应以该返回为准 + +OpenClaw 应做: + +- 读取后直接进入 digest 生成 +- 不再自己拼 `candidates/openclaw-delivery-payload.json` + +### 7.2 `get_run_report` + +用途: + +- 获取 run 的结果摘要与关键元信息 +- 用于状态判断、排障、补充上下文 + +OpenClaw 应做: + +- 作为诊断与编排辅助信息读取 +- 不把 raw file path 解析逻辑继续散落到 skill 里 + +--- + +## 8. 最小编排动作表 + +### 8.1 标准生产执行 + +1. 调 `run_freshrss_openclaw_pipeline` +2. 拿 `run_id` +3. 轮询 `get_run_status` +4. 若 `success`: + - 调 `get_delivery_payload` + - 调 `get_run_report` +5. 进入 digest / Hugo / chat / IMA 下游编排 + +### 8.2 失败恢复执行 + +1. 调 `get_run_status` +2. 若 `failed && recovery.resumable=true`: + - 调 `resume_run` +3. 恢复后再次: + - 调 `get_run_status` + - 若成功,再读 payload / report +4. 若恢复失败或明确不可恢复: + - 新开 run 或人工介入 + +--- + +## 9. 不推荐做法 + +以下做法不应再作为正式主路径: + +- 让 OpenClaw 直接长时间 `exec` reader CLI 作为主要生产入口 +- 让 OpenClaw 自己拼 reader 输出路径来判断成功/失败 +- 让 OpenClaw 自己读取 `outputs/.../*.json` 作为正式结果源 +- 在未确认 `resume_run` 支持范围外的失败点上强行恢复 + +CLI 现在的定位是: + +- debug +- fallback +- 人工排障 + +而不是正式生产主入口。 + +--- + +## 10. 当前已知局限 + +- `resume_run` 仍是最小实现,不支持任意 stage 任意重入 +- 历史无 `run-state.json` 的 run 不支持正式恢复 +- 极旧 run 的结果读取仍可能依赖保守目录扫描 +- `write_run_report` 若涉及重新 `mark_read`,仍依赖 FreshRSS 环境和可用凭据 + +--- + +## 11. 一句话结论 + +OpenClaw 当前应把 reader 当作正式 MCP workflow service 使用: + +**启动用 `run_freshrss_openclaw_pipeline`,观测用 `get_run_status`,结果读取用 `get_delivery_payload` / `get_run_report`,恢复仅在 `resume_run` 最小支持范围内启用;不要再把 reader 当成长 CLI 任务和路径拼接仓库来驱动。**