Files
Arcrun/registry/skills/write_recipe.md
T
uncle6me-web 7e87a3336b 3.8 新增 write_recipe skill——recipe 指路終於有目的地
📋 SDD:workflow-discovery task 3.8(3.7 的 suggestion 指 skill write_recipe,
之前是空地——指路會指到不存在的 skill)。

- registry/skills/write_recipe.md:從真 code 反推,不是憑空教學——
  schema=routes/recipes.ts RecipeDefinition(canonical_id/endpoint/method/auth_service…);
  真範例=api-recipe-seeds.ts 的 telegram_send(URL path 注入)+gmail_send(service account);
  auth recipe 必填欄位(required_secrets 的 help_url 必填)照 POST /auth-recipes 驗證邏輯;
  常犯錯收錄實錄(sheets append PUT→POST、telegram auth recipe 漏種、金鑰只准名字 D36)
- INDEX.md 補 write_recipe 入口;「/cypher/search 假 found」坑改標已修(2026-07-31)
- write_intent_workflow.md §6 status 表改 not_found 契約+suggestion/similar_* 欄說明

安裝器 seed:registry/skills/*.md 由 sync-registry-to-kbdb.py 自動收,新檔即納入。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-31 11:56:30 +08:00

138 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Skill: Write Recipe(寫 recipe
## 何時用這個 skill
**`/cypher/search``not_found``suggestion` 指「寫 recipe」時,讀這支。**
- 要打某個外部 APIGoogle Slides / Slack / 任何有 HTTP API 的服務),但 `arcrun_recipe_list()` 沒有
- `acr recipe search <關鍵字>` 落空,回「公庫無符合的 recipe」
- 你想把一條常用的 API 呼叫封裝成可重用、可投稿的配方
> 🔴 **不要因為沒有 recipe 就改寫成 `code` 節點**——那是「腹語術」。
> recipe 不用改平台、不用部署 Worker、不用寫程式,**幾行 YAML 就能自己補上**。
## recipe 是什麼
**「http_request + 參數模板」的具名封裝**(真身存在 cypher-executor 的 RECIPES KV)。
執行時 cypher-executor 直接 fetch 該 endpoint——不 deploy Worker、不寫 WASM。
| 你缺的是… | 走哪條路 |
|---|---|
| 打**外部 API**(服務有 HTTP API | **recipe(本 skill** |
| **計算能力**(加解密/壓縮這類純運算) | 零件 PR → `arcrun_get_skill('add_new_wasm_component')` |
## 1. Recipe 的欄位(schema
```yaml
canonical_id: google_slides_create # 必填。小寫底線,全庫唯一的可讀名
endpoint: https://slides.googleapis.com/v1/presentations # 必填。要打的 URL
method: POST # 選填,預設 POSTGET/PUT/PATCH/DELETE 皆可)
display_name: Google Slides Create # 選填,人看的名字
description: 建立一份新簡報。POST presentationsbody 帶 title。auth: google service_account。
auth_service: google_slides_sa # 選填。指向 auth recipe(見第 3 節)
headers: {} # 選填。額外固定 header
body: {} # 選填。固定 body 欄位(會與節點 payload 合併)
```
- `hash_id``rec_xxxxxxxx`)與 `uuid` 由系統自動生成,不用寫。
- **description 認真寫**:AI(包括未來的你)靠它決定要不要用這個 recipe。
照庫裡的慣例寫「做什麼。怎麼打。auth 用什麼。」三段。
## 2. 真範例(從實際 seed 且實跑過的 recipe 照抄)
### A. token 在 URL path`telegram_send`
```yaml
canonical_id: telegram_send
display_name: Telegram Send
description: Telegram sendMessage。token 在 URL path{{auth.bot_token}}),body 帶 chat_id+text。auth: static_key path 注入。
endpoint: https://api.telegram.org/bot{{auth.bot_token}}/sendMessage
method: POST
auth_service: telegram
```
### B. Bearerservice account`gmail_send`
```yaml
canonical_id: gmail_send
display_name: Gmail Send
description: 寄 Gmail。POST messages/sendbody 帶 rawbase64url MIME)。auth: google service_account。
endpoint: https://gmail.googleapis.com/gmail/v1/users/me/messages/send
method: POST
auth_service: google_gmail_sa
```
### 模板變數(endpoint 裡可用)
| 變數 | 來源 | 例 |
|---|---|---|
| `{{auth.X}}` | auth recipe 的 `inject.path` 注入 | `bot{{auth.bot_token}}/sendMessage` |
| `{{_path}}` | 節點 payload 的 `_path` 欄位(路徑由工作流決定時用) | `https://sheets.googleapis.com{{_path}}` |
🔴 **金鑰只准名字,不准真身**endpointheaders 裡**絕不**寫死 token。
真值走 credential 中心(`acr creds push`),recipe 只留 `{{auth.X}}` 這種名字引用。
## 3. auth 怎麼接(多數 recipe 需要)
`auth_service: telegram` 表示執行時去拿 `auth_recipe:telegram` 做認證注入。
先查有沒有:`acr auth-recipe list``GET /auth-recipes/<service>`
**沒有就要一併建**`POST /auth-recipes`,缺這步 recipe 會注入空值打不通):
```yaml
service: telegram # 必填
primitive: static_key # 必填:static_key | oauth2 | service_account
base_url: https://api.telegram.org # 必填
required_secrets: # 必填,每個 secret 的 help_url 也必填(官方文件連結)
- key: telegram_bot_token
label: Bot Token(從 @BotFather 取得)
help_url: https://core.telegram.org/bots/features#botfather
inject: # 必填:secret 注入到哪(header / query / body / path
path:
bot_token: "{{secret.telegram_bot_token}}"
```
然後用戶端上傳真值:`acr creds push`(存進 credential 中心,AI 拿不到真身)。
## 4. 裝上(三個介面同一個 API)
```bash
acr recipe push my_recipe.yaml # CLIpush 時會實打 endpoint 做打通檢查
```
- MCP`arcrun_recipe_push(...)`
- HTTP`POST /recipes`JSON,欄位同上)
裝好後 workflow 直接引用(節點名=canonical_id,或 config 指定):
```yaml
config:
notify:
component: telegram_send # 或穩定引用 rec_xxxxxxxx
```
payload(如 `chat_id``text`)由上游節點或 context 給——這正是「AI 只填 payload」。
## 5. 驗收(誠實原則)
1. push 時的**打通檢查**只是提醒級——真驗收=**跑一次 workflow、`verdict=success`2xx**
2. 缺 credential 打不到 2xx → 誠實標「未驗收:缺 X」,**不 mock 充綠燈**
3. 打通後可投稿公庫讓別人用:`acr recipe submit-p <canonical_id>`(成為該 recipe 的作者版本)
## 6. 常犯的錯
1. **token 寫死在 endpointheaders** → 金鑰鐵律違規。只准 `{{auth.X}}` 名字引用
2. **method 用猜的** → 查官方文件。實錄:Sheets append 被猜成 PUT(官方是 POST `:append`),
seed 到壞 recipe 每個新用戶都打 400
3. **只建 recipe 忘了 auth recipe**`{{auth.X}}` 注入空值打不通。實錄:telegram auth recipe
漏進種子,所有新實例的 telegram 發訊全斷
4. **落空就寫 code 節點** → 腹語術。recipe 是正路,且寫好可投稿讓全生態重用
5. **canonical_id 用大寫/空白** → 一律小寫底線(系統會 trim+lowercase,但別靠它救)
## 7. 相關
- 寫意圖工作流(上游,先寫意圖再查缺什麼):`arcrun_get_skill('write_intent_workflow')`
- 缺的是計算零件不是 API`arcrun_get_skill('add_new_wasm_component')`
- 查公庫現貨:`acr recipe search <關鍵字>` `arcrun_recipe_search(...)`
- 拉別人寫好的:`acr recipe pull <canonical_id> [--author=<name>]`