--- name: arcrun-mindset description: >- 在 Arcrun 上做任何事時使用(用戶說「幫我用 Arcrun 做 X」「用 arcrun 寫一個工作流」「把 X 自動化」)。 Arcrun 是跑在 Cloudflare 上的工作流引擎——你用 `>>` 寫「意圖」,系統告訴你有哪些現成零件與 recipe, 你只填 payload,不必自己寫程式。**不要上網搜 Arcrun 文件**(網路上沒有),也不要自己猜 YAML 格式: 先讀本 skill,再用 `acr` 指令(或 MCP 工具)查現成零件。 涵蓋:意圖工作流語法、四份實跑過的範本、零件 vs recipe 的分別、缺件的兩條路、已知的坑。 --- # Arcrun:怎麼寫意圖工作流 > **你已經配備 Arcrun**(此專案裝了 `acr` CLI,可能另有 `arcrun_*` MCP 工具)。 > **別上網找文件**——網路上沒有 Arcrun 的文件,找到的都是錯的。答案都在本 skill 與 `acr` 指令裡。 ## 先做這三件(照順序) 1. `acr whoami` — 確認連到哪個帳號(**勿自行 curl 猜帳號 URL**) 2. 讀本 skill 下面的語法與範本 → 寫出 `>>` 意圖 3. `acr parts`/`acr recipe list`(或 `acr search <關鍵字>` 一次掃全部)— 確認零件與 recipe 真的存在 **卡住時**:`acr search <關鍵字>` 跨類搜尋;有 MCP 就 `arcrun_get_skill('INDEX')` 拿全館導航。 --- ## 0. 一句話世界觀 **Arcrun 裡幾乎所有東西都是工作流(workflow)。** 工作流 = 一張紙,寫「用哪些零件、什麼順序、什麼條件」。 你大部分時間在**寫紙、改紙**,不是在造新零件、也不是自己寫腳本。 **Arcrun 只有三種東西,先分清楚就不會做歪:** | 東西 | 是什麼 | 你能做的 | |---|---|---| | **工作流(workflow)** | 把零件/recipe 串起來的純文字流程 | **預設就寫這個**,自由寫 | | **recipe** | 打「一個固定外部 API」的設定(endpoint/header/body 模板) | 自由寫、**而且該投稿**(缺就自己補) | | **零件(component)** | WASM 程式(流程控制/資料處理/`http_request`/auth),固定一小套 | **你不自製**,走 PR 由維護者管 | > **一句話判準**:打一個固定外部 endpoint → 寫 **recipe**;流程控制/資料處理/通用 HTTP → 用既有**零件**;其他 → 寫**工作流**串起來。 --- ## 1. 意圖工作流的語法 一串「誰接誰」,每行一個關係: ``` <節點A> >> <邊> >> <節點B> ``` - **節點**=一個步驟。用你想得到的名字(中文可以),**不必是真實零件名** - **邊**=什麼情況下往下走 ## 2. 邊有這些 | 邊 | 意思 | 真例 | |---|---|---| | `ON_SUCCESS` | 上一步成功就往下 | `input >> ON_SUCCESS >> prep` | | `對每個 <變數>` | 上一步產出清單,逐項處理(FOREACH)| `parse_card >> 對每個 block >> post_block` | | `ON_TRUE` / `ON_FALSE` | 條件成立/不成立各走一條(配 `if_control`)| `判斷有沒有新資料 >> ON_TRUE >> 傳到 telegram` | | `ON_BRANCH`+`branch:` | 依標籤選路(配 `switch` 每個 case、`try_catch` 的 try/catch)| `my_switch >> ON_BRANCH(branch_active) >> 處理啟用` | ### 2.1 條件分支怎麼寫(2026-08-01 起引擎支援) **需要判斷時,用分支邊,不要寫 `code` 判斷。** 三顆流程控制零件都輸出 `data.branch` 標籤,引擎依標籤選路: | 零件 | 輸出的標籤 | 接法 | |---|---|---| | `if_control` | `"true"` / `"false"` | `ON_TRUE`/`ON_FALSE` 各一條 | | `switch` | 你在 `cases[].branch` 取的名字(沒中則 `default_branch`)| 每條路一條 `ON_BRANCH`,邊上標 `branch` | | `try_catch` | `"try"`(沒錯)/`"catch"`(有錯)| 兩條 `ON_BRANCH`,標 `try` 與 `catch` | ``` 判斷有沒有新資料 >> ON_TRUE >> 傳到 telegram 判斷有沒有新資料 >> ON_FALSE >> 結束 ``` 中文語意詞亦可:「成立時」=`ON_TRUE`、「否則」=`ON_FALSE`。 💡 **不必背**:查零件時回應會附 `branch_hint`(有哪些標籤、用哪些邊型、可照抄的範例), 照著接就對了。 ⚠️ 仍然**不要寫 `ON_FAILURE`**(沒有這種邊;要處理失敗用 `try_catch` + `ON_BRANCH(catch)`)。 ### 2.2 怎麼確認分支真的走對了(**別看不懂就以為壞掉**) 分支工作流「有沒有成功」看兩件事,**不是看某條沒走的路沒有輸出**: 1. **`verdict`**:`GET /workflows//executions?limit=1` → `data.executions[0].verdict === "success"` 就是成功了。 2. **`trace` 裡有沒有出現該走的節點**:走 TRUE 路時 FALSE 路的節點**本來就不該出現** ——**那是正確行為,不是失敗**。 ``` # 條件成立 → 只有 true 那條的節點在 trace {"amount": 5000} → if_control 回 branch="true" → 走 ON_TRUE 那條 {"amount": 100} → if_control 回 branch="false" → 走 ON_FALSE 那條 ``` 🔴 **實撞(2026-08-01 考試)**:有考生的分支工作流**其實完全正常** (`amount=5000`→true、`amount=100`→false 都對),但它以為「跑不通」而放棄改寫成 code。 **看到只有一條路有輸出=分支正在正確運作**,不要因此判定失敗。 ## 3. 第一個節點固定是 `input` 所有真範本都以 `input` 起頭——那是「觸發時帶進來的資料」。 --- ## 4. 真範本(照抄結構、改內容) > 以下四份**全部是實際部署且 `verdict=success` 的 workflow**,不是簡化示範。 > 用 `acr logs `(有 MCP 則 `arcrun_get_workflow()`) 可以拿完整定義。 ### A. 最短:取資料 → 處理 (`graph_neighbors`) ``` input >> ON_SUCCESS >> fetch_triplets fetch_triplets >> ON_SUCCESS >> bfs_neighbors ``` ### B. 長鏈:多次查詢 → 組裝 → 問 AI → 收尾 (`rag_chat`) ``` input >> ON_SUCCESS >> prep prep >> ON_SUCCESS >> kw_search kw_search >> ON_SUCCESS >> sem_search sem_search >> ON_SUCCESS >> fetch_triplets fetch_triplets >> ON_SUCCESS >> fetch_blocks_a fetch_blocks_a >> ON_SUCCESS >> assemble assemble >> ON_SUCCESS >> ask_llm ask_llm >> ON_SUCCESS >> finalize ``` `prep` 前處理/`assemble` 組 prompt/`finalize` 收拾回應——三個常見的整形節點。 ### C. 一節點分岔兩條 FOREACH (`rag_ingest_card`) ``` input >> ON_SUCCESS >> parse_card parse_card >> 對每個 block >> post_block parse_card >> 對每個 rel >> post_triplet ``` 同一節點可有多條出邊,各自處理不同清單。 ### D. 混合:直線 + 兩段 FOREACH (`rag_takedown_direct`) ``` input >> ON_SUCCESS >> prep prep >> ON_SUCCESS >> list_dead_blocks list_dead_blocks >> ON_SUCCESS >> build_deprecations build_deprecations >> 對每個 dead_entry >> deprecate_entry build_deprecations >> ON_SUCCESS >> list_triplets list_triplets >> ON_SUCCESS >> pick_dead_triplets pick_dead_triplets >> 對每個 dead_record >> deprecate_triplet ``` `build_deprecations` 同時有 FOREACH 出邊與 `ON_SUCCESS` 出邊—— 前者處理清單、後者繼續主線。 --- ## 5. 節點怎麼命名(照真範本的模式,查詢較容易媒合) | 意圖 | 模式 | 真例 | |---|---|---| | 前處理/正規化 | `prep` | `rag_chat.prep` | | 取一批資料 | `fetch_*`/`list_*` | `fetch_triplets`/`list_dead_blocks` | | 搜尋 | `*_search` | `kw_search`/`sem_search` | | 解析/切塊 | `parse_*` | `parse_card` | | 寫入 | `post_*` | `post_block`/`post_triplet` | | 組裝 | `assemble`/`build_*` | `assemble`/`build_deprecations` | | 問 AI | `ask_llm` | `rag_chat.ask_llm` | | 收尾整形 | `finalize` | `rag_chat.finalize` | --- ## 6. 寫完一定要查(**不要直接部署**) ```bash curl -s -X POST https://arcrun-cypher-executor..workers.dev/cypher/search \ -H 'content-type: application/json' -H 'X-Arcrun-API-Key: ' \ -d '{"triplets":["input >> ON_SUCCESS >> fetch_data","fetch_data >> ON_SUCCESS >> notify"]}' ``` 回應的每個節點會有: | status | 意思 | 你該做什麼 | |---|---|---| | `found` | 有這個節點。`source: component` 附 `input_schema`(怎麼填 payload)與 `success_rate`;`source: recipe` 附 description/endpoint | **只填 payload** | | `not_found` | **兩庫(零件 registry+recipe 庫)都查過,確定沒有** | 照 `suggestion` 欄走:缺 API → 寫 recipe(skill `write_recipe`);缺計算能力 → 投稿零件 PR(skill `add_new_wasm_component`)。`similar_components`/`similar_recipes` 是相近候選——先看有沒有現成的能直接用 | | `unknown` | 查不到 registry | **不代表不存在**,別據此改寫成 code | > 註(2026-07-31):`/cypher/search` 曾對任何節點名都回假 `found`,已修為真查兩庫。 > 舊實例(未更新部署)仍可能假 found——status 可信度以該實例部署版本為準。 --- ## 7. 常犯的錯 1. **用不存在的邊**(`ON_FAILURE`)→ 沒有這種邊;要處理失敗用 `try_catch` + `ON_BRANCH(catch)` ⚠️ `ON_TRUE`/`ON_FALSE`/`ON_BRANCH` **是存在的**(2026-08-01 起),見 §2.1—— 本行以前寫「ON_TRUE 不存在」是舊世代,已更正 2. **第一個節點不是 `input`** 3. **把 recipe 當零件寫**——`telegram_send`/`gmail`/`kbdb_get` 是 **recipe** 不是零件 → 寫成 `http_request` + 該 recipe 4. 🔴 **查詢回 `not_found` 就改寫成 `code` 節點** → 那叫「腹語術」(表面用 Arcrun、實際全寫 JS)。正解:缺 API 寫 recipe、缺能力投稿零件。 `code` 只用在**局部整形**(例:剝掉 LLM 回應的雜訊),不用來取代零件與流程控制。 --- ## 8. 相關 - 完整版指引與十題考卷(含 haiku 實測 10/10): 頂層 repo `system-dev/docs/3-specs/arcrun-usable/` - 下一步該讀哪支 skill(需 MCP):`arcrun_list_skills()` - 定期掃資料 → `build_watcher_workflow` - RAG 檢索問答 → `rag_with_arcrun` - workflow 卡住不動 → `debug_paused_workflow` --- ## 9. 資源去哪取(不要自己重造 Arcrun 已有的) | 你想知道 | 跑這個 | |---|---| | 有哪些零件可用 | `acr parts` | | 某零件的設定範本 | `acr parts scaffold ` | | 有哪些 recipe | `acr recipe list`/`acr recipe search <關鍵字>` | | 支援哪些服務的認證 | `acr auth-recipe list` | | 某服務認證要哪些 credential + 範例 | `acr auth-recipe scaffold ` | | **一次掃全部**(零件/recipe/auth-recipe/workflow) | `acr search <關鍵字>` | | 已部署的 workflow | `acr list` | | 某次執行為什麼失敗 | `acr logs ` | | 工作流語法、指令 | `acr --help` | **先查再動手**——Arcrun 多半已經有你要的零件/recipe/認證,不要自刻。 ## 10. 做出來以後:驗證 → 部署 ```bash acr validate .yaml # 先驗,別直接部署 acr push .yaml # 部署(暴露動作,見 §12) acr run # 觸發一次,看實際結果 acr logs # 看執行紀錄/失敗原因 ``` 需要 credential(API key/token)時:`acr auth-recipe scaffold ` 看要哪些, 明確告訴使用者去哪取得、怎麼 `acr creds push`。 🔑 **金鑰只拿名字**:workflow/recipe 裡只寫 `{{credential.<名字>}}`, **真身絕不寫進定義檔**(執行前才由系統回填)。 ## 11. Arcrun 是你(AI)用的工具,不是工具回頭呼叫 AI 需要智慧判斷/自然語言轉換時,**你自己做**,再呼叫工作流執行確定性的下一步。 **不要在工作流中間放零件回頭呼叫 LLM**——Arcrun 的大腦就是操盤的你。 (唯一例外:`ask_llm` 這種「內容生成本身就是流程的一步」,見範本 B。) ## 12. 把東西開放給別人用 = 要使用者明示同意 `acr push`(部署 workflow)與 `acr recipe push`(投稿 recipe)會讓資料/能力**可被外部呼叫**: - 停下來,明確告訴使用者「這會讓 X 可被外部呼叫」,要他同意。**不替他決定公開。** - 非互動環境(你直跑)遇到 → 停,把完整指令印給使用者自己貼上跑,絕不自己塞 confirm 假裝同意。 - Arcrun 可提供保護(要求呼叫者帶 key/限流)——提醒使用者。 ## 13. Arcrun 不替你做授權判斷 API 打不打得通由發 key 的服務決定。401/403 是對方服務在行使授權,**不是 Arcrun 的 bug、不是你做錯**。 不要在 Arcrun 裡建「允許/禁止某 endpoint」的二次授權清單。 ## 14. 誠實(最重要) - **不假綠**:沒打通就誠實說。缺 credential 打不到 2xx → 標「未驗收:缺 X」,不 mock 充綠燈。 - **不假裝防偽/不代替人類確認**有風險的動作(暴露資料)。 - **完成 = 客觀證據**(HTTP 2xx + trace),不是口頭「做好了」。 --- ## 動手前的自檢清單 1. 我把意圖寫成 `>>` 串了嗎?(還是直接跳去寫 YAML/寫程式) 2. 我查過 `acr search` / `acr parts` / `acr recipe list` 了嗎? 3. 查詢回 `not_found` 時,我走的是 recipe/零件 PR 兩條路,**還是偷偷改寫成 `code`**?(後者=腹語術) 4. 我是不是讓工作流回頭呼叫 AI 做判斷?(是 → 改成我自己做) 5. 這動作會把資料開放給別人嗎?(會 → 要使用者明示同意) 6. 我有沒有假裝(假綠/假防偽/代替人類確認)?(有 → 停,誠實標明)