feat: complete production workflow migration
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
---
|
||||
name: data-collector-guardrail
|
||||
description: "Guardrail for collector: collect + heartbeat only."
|
||||
metadata:
|
||||
hermes:
|
||||
skillKey: data-collector-guardrail
|
||||
profile: data-collector
|
||||
os: ["win32"]
|
||||
---
|
||||
|
||||
Collector Guardrail
|
||||
|
||||
You are the collector endpoint.
|
||||
|
||||
Do:
|
||||
- Run collection scripts.
|
||||
- Publish fresh artifacts to shared-data.
|
||||
- (Heartbeat is now sent automatically by `orchestrator/mcp_workflow.py` as a Schema 2.0 interactive card to `ou_8ee224968aa26a74c7d30ba27fed5eeb`. Do NOT call send_message / curl / any Feishu API to relay heartbeats.)
|
||||
- For **manual** ad-hoc heartbeat relay (operator asks in chat to forward a workflow report to the admin), reply directly with the same fields described in `Collector Heartbeat Notification Format` below — the gateway binding delivers the reply.
|
||||
|
||||
Do not:
|
||||
- Send final business notifications.
|
||||
- Run analyzer-stage actions.
|
||||
- Mix analyzer app credentials (analyzer app: cli_aa8c4fc918b85cce, analyzer owner: ou_7ad5fc8012e2f741afc5346e05ffd447).
|
||||
- Try to call send_message, curl, or external APIs to relay **automated** collector heartbeats — orchestrator already sends them as cards.
|
||||
|
||||
Credential path: The collector app secret (`2lAvcKK4gX2Qa6uCrhxgZedTzbc70a7U`) lives in two places:
|
||||
- Hermes profile `.env`: `${HERMES_STATE_ROOT}\profiles\data-collector\.env` under `FEISHU_APP_SECRET` (for cron / LLM-direct paths).
|
||||
- `orchestrator/config.py` → `FEISHU_CONFIG.apps.collector.app_secret` (env override `AUTOFLOW_COLLECTOR_APP_SECRET`). Used by `mcp_workflow.py:_send_collector_heartbeat` for the new automated card-based heartbeats.
|
||||
|
||||
It is NOT in `orchestrator/scripts/config.json` → `feishu.app_secret` / `feishu_analyzer.app_secret` (those are analyzer app credentials). Scripts like `send_collector_notify.py` that fall back to that file will fail with `code: 10014, app secret invalid`.
|
||||
|
||||
**Automated heartbeat (post-2026-06-27):** The orchestrator sends Schema 2.0 interactive cards via `mcp_workflow.py:_send_collector_heartbeat` → `requests.post(/open-apis/im/v1/messages)` with the collector app credentials, target `ou_8ee224968aa26a74c7d30ba27fed5eeb`. Phases: `start` (blue), `progress` (blue, every `HEARTBEAT_INTERVAL_SECONDS`=180s), `final` (green on success / red on failure). The collector LLM is NOT involved — do not duplicate.
|
||||
|
||||
**Manual relay (operator asks in chat to forward a report):** Reply directly with the format below. The gateway binding delivers it. No tool calls needed.
|
||||
|
||||
Pitfalls:
|
||||
| Collector app owner open_id | `ou_8ee224968aa26a74c7d30ba27fed5eeb` — the admin/reporter who receives collector heartbeat notifications via collector Feishu app |
|
||||
| Notification target (admin/reporter) | `ou_8ee224968aa26a74c7d30ba27fed5eeb` — this profile receives workflow heartbeat reports (NOT the analyzer app owner) |
|
||||
| Analyzer app owner open_id | `ou_7ad5fc8012e2f741afc5346e05ffd447` — NOT the collector heartbeat target; this belongs to the analyzer app scope (`cli_aa8c4fc918b85cce`) |
|
||||
- UTF-8 BOM manifest error: If a workflow fails with `Invalid run manifest: Unexpected UTF-8 BOM (decode using utf-8-sig): line 1 column 1`, the manifest JSON file was saved with a BOM (common on Windows editors like Notepad). Fix: resave the manifest as UTF-8 without BOM, or strip the BOM (`\ufeff`) from the file's first bytes.
|
||||
- batch_process.py scripts must be saved as UTF-8 encoding. GBK/CP936 encoding corrupts Chinese string literals and causes "unterminated string literal" SyntaxError on line 41.
|
||||
- Yuanbao toolsets are listed in platform_toolsets.cli but the `yb` CLI binary and `yb_send_dm`/`yb_query_group_members` functions are NOT available on data-collector — `yb_send_dm: command not found` is the expected result. Do not search for the `yb` binary, attempt `hermes tools enable yuanbao` (it will succeed but expose nothing usable), or try to curl localhost:8123/yuanbao/send_dm. Yuanbao adapter is also absent from channel_directory.json (yuanbao: []). Always fall back to direct reply immediately — the API server delivers collector heartbeat reports without any Yuanbao integration.
|
||||
- Cron jobs running collector workflows (deliver: local): output IS the notification — do NOT try to call Feishu REST APIs from cron. The cron output goes to the gateway chat; the gateway relays to Feishu. If you need to send Feishu from cron, you need the app_secret accessible in the cron env (`FEISHU_APP_SECRET`) — collector app secrets are often gateway-runtime-injected and NOT stored in the codebase. Use `FEISHU_APP_SECRET` (not `COLLECTOR_FEISHU_APP_SECRET`).
|
||||
- **`execute_code` filesystem access is limited to the sandbox directory.** `execute_code` runs in an isolated sandbox — it cannot access host paths like `${GYXX_PROJECT_ROOT}\shared-data\` or `${HERMES_STATE_ROOT}\...`. Attempting to open host paths via `Path()` or `read_bytes()` will raise `FileNotFoundError`. Use `terminal` (which inherits the MSYS/Git-Bash environment with proper path mapping) for all file operations on host paths. The `execute_code` sandbox is only suitable for pure in-memory computation or accessing paths that the sandbox itself creates.
|
||||
- **`execute_code` can make outbound HTTP calls** — the "cannot call Feishu REST APIs" restriction is outdated. `requests` + `FEISHU_APP_SECRET` works fine from `execute_code` in the agent process. The failure scenario is cron job scripts running in a subprocess (where `FEISHU_APP_SECRET` is not injected). Always check `os.environ.get("FEISHU_APP_SECRET")` before assuming it works or fails.
|
||||
- **`terminal` + inline Python script** is the most reliable pattern for Feishu REST calls. `python -c "..."` via terminal inherits the shell env, works in both agent and cron contexts.
|
||||
- **Manual relay only (operator asks in chat to forward a report) — reply DIRECTLY with no tool calls.** Your reply text IS the notification. Do NOT query channel_directory, search for yuanbao group codes, call send_message, or look up credentials. This is for **manual / ad-hoc** forwarding only — automated heartbeats are sent by the orchestrator as cards.
|
||||
- Common mistake: trying to relay an automated heartbeat (orchestrator already sent it) or calling send_message for manual relay. Both are unnecessary.
|
||||
- Cron jobs with **gateway Feishu binding** (deliver: origin/local): reply directly — the gateway's own Feishu binding delivers the reply. (For automated heartbeats the orchestrator sends the card itself, so this is now mostly relevant for operator-side messages, not workflow status.)
|
||||
- Scripts run via **terminal** without gateway binding: use `python -c "..."` to call Feishu REST APIs with `FEISHU_APP_SECRET`. (Same caveat — only relevant for paths outside the orchestrator's automated heartbeat flow.)
|
||||
**Cron job skills that don't exist cause a skip warning but don't fail the job.** When a cron job's `skills` list contains a nonexistent skill, the scheduler logs `WARNING Cron job 'X': skill not found, skipping — Skill 'feishu_doc' not found.` The job still runs with the remaining skills or no skills. If the cron job silently does nothing or hits an unexpected code path, check `logs/errors.log` for this warning — the missing skill is the likely cause. To fix: remove the nonexistent skill from the cron job's `skills` list, or create the skill.
|
||||
- Example: A `purchase-confirmation` workflow monitor cron job listed `feishu_doc` in skills but the skill was deleted. The job's `feishu_doc_read` tool call failed because the skill wasn't loaded, producing a partial/incomplete result with no error surfaced to the user.
|
||||
|
||||
## Collector Heartbeat Notification Format
|
||||
|
||||
**Automated heartbeats are sent by the orchestrator as Schema 2.0 cards** (see "Automated heartbeat" under Credential path). The LLM does not need to format or send them.
|
||||
|
||||
**Manual relay only** (operator asks in chat to forward a workflow report) — include all key fields:
|
||||
|
||||
```
|
||||
[采集端心跳] <工作流名称>
|
||||
|
||||
Workflow ID: <id>
|
||||
运行 ID: <run_id>
|
||||
状态: <status>
|
||||
当前阶段: <phase>
|
||||
采集尝试次数: <n>
|
||||
分析尝试次数: <n>
|
||||
执行结论: <conclusion>
|
||||
```
|
||||
|
||||
Manual relay pattern (for owner-only reports):
|
||||
- User asks: "notify me only, not business targets" → reply directly as your response text (API server delivers it).
|
||||
- The reply content IS the notification — no extra tools needed.
|
||||
- Include all key fields: workflow ID, run ID, phase, status, attempts, error details, collection summary.
|
||||
- Do NOT also call send_message / lark-cli / lark-cli / Feishu REST API — that would double-send.
|
||||
|
||||
Reference: `references/feishu-open-id-cross-app.md` — Feishu open_id cross-app failure and correct routing. Collector heartbeat target is `ou_8ee224968aa26a74c7d30ba27fed5eeb` via collector app (`cli_aa8c4fb4c4f81cd3`). `ou_7ad5fc8012e2f741afc5346e05ffd447` is the analyzer app owner — NOT the collector heartbeat target. Full REST call pattern included.
|
||||
Reference: `references/collector-notification-credentials.md` — Collector Feishu notification credential sources: direct-reply pattern vs REST API pattern, and the known bug where `send_collector_notify.py` reads the wrong app secret from `config.json`.
|
||||
Reference: `references/workflow-state-querying.md` — How to query collector workflow state. **Primary source: `shared-data/` artifacts + agent logs.** The orchestrator's `state.db` (LangChain checkpoints) only stores `replenishment-alert` runs — NOT collector runs. See the reference file for the full state querying strategy.
|
||||
|
||||
**Reusable monitoring script:** `scripts/monitor_purchase_confirmation.py` — drop-in script that queries collector session DB + shared-data, then sends Feishu admin notification. Run with `python scripts/monitor_purchase_confirmation.py <RUN_ID>`. Handles `orchestrator/state.db` ≠ collector workflow source correctly.
|
||||
|
||||
Final check:
|
||||
- Collection only.
|
||||
- No business-user final notify.
|
||||
- Shared-data contains only this run outputs.
|
||||
Reference in New Issue
Block a user