Community程式設計與開發github.com

DartenZie/247-agent-model-actions

設計與撰寫 247-agent 工作流程中模型支援的步驟:`decide` 動作(透過 OpenRouter 的 Decisions API 向 TypeSafe 的 Jev 分類器提出型別化問題,僅回傳機率,無文字)、`llm` 動作(使用 JSON 輸出綱要的單次 Claude 呼叫)以及 `agent` 動作(在全新的 git worktree 中,於 ACP 代理器如 claude-agent-acp 上進行一次會話,配備工具種類與命令允許清單、工具呼叫上限、預算、包含 `status: done | blocked` 與確定性 `post` 閘門的 RESULT.json 合約)。

247-agent-model-actions 是什麼?

這項技能專注於在 247-agent 工作流程中撰寫三種模型支援的動作:`decide`、`llm` 與 `agent`,並遵循守護程式的核心設計原則——控制流中不應有 LLM。 * **`decide` 動作**:用於分類、路由、分級與閘門判斷。它使用 TypeSafe 的 Jev 分類器(透過 OpenRouter 的 Decisions API),逐一提出型別化問題,並僅回傳機率分數(無文字生成),成本約為 `llm` 呼叫的百分之一。 * **`llm` 動作**:用於單次判斷,需要產生固定形狀的結構化輸出(例如摘要或欄位提取)。它使用標準的 LLM 呼叫,並搭配 JSON 輸出綱要,系統提示應置於靜態檔案中以啟用提示快取。 * **`agent` 動作**:用於需要讀取檔案、執行命令與疊代處理的複雜任務。它在 ACP 代理器上執行一次隔離的會話,使用全新的 git worktree,並透過嚴格的工具與命令允許清單、工具呼叫上限與預算來確保安全。其結果以 RESULT.json 合約的形式呈現,包含 `status: done` 或 `blocked`,後續的確定性 `post` 閘門(如建置與提交)確保部署前的驗證。 此技能支援 Anthropic 的 Claude 模型(Haiku、Sonnet、Opus)與 OpenAI / OpenRouter 模型,所有動作均透過 `ctx.llm` 連接埠進行,以強制執行預算與分類帳記錄。 這項技能在 Claude Code、Cursor 與其他 AI 代理器工具上使用,每當任務需要分類、路由、提取、摘要、決策或編輯儲存庫時。當使用者提及模型、提示、`system_file`、`output_schema`、`questions`、`criteria`、信心閾值、Jev、`max_tool_calls`、`budget`、`effort`、成本、層級(Haiku/Sonnet/Opus)、ACP、worktree、「blocked」結果或「讓代理器做某事」時,都應使用此技能。

相容平台✓Claude Code✓Codex CLI~Cursor
npx skills add https://github.com/DartenZie/247-agent/tree/HEAD/skills/247-agent-model-actions

Installed? Explore more 程式設計與開發 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

247-agent 模型動作

守護程式的設計規則:控制流中不得使用 LLM。比對、去重、路由、重試與發佈皆為程式碼。模型僅能在 decide、llm 或 agent 動作內部執行,並以能完成任務的最便宜層級執行,且設有預算。此技能旨在妥善撰寫這三種動作,以及執行它們的執行器。

首先判斷是否需要模型

依序詢問:

  1. 觸發器的 filter 能否決定?(寄件者、標籤、儲存庫、關鍵字)若是,則非模型呼叫。
  2. 腳本或連接器操作能否確定性地產出答案?若是,則使用 shell/connector。
  3. 是否為標籤、是/否或層級,且無需產生文字(分類、路由、分級、閘門)?若是,則使用 decide:一種僅用於分類的模型,校準後的機率,成本約為 llm 呼叫的百分之一。
  4. 是否為單一判斷,需產出固定形狀的結構化輸出且需要文字(提取欄位、摘要、草稿)?若是,則使用 llm,優先使用 Haiku。
  5. 是否需要讀取檔案、執行命令並疊代處理?若是,則使用 agent,並選取能成功的最窄範圍。

兩個需要不同智慧等級的任務應是相同動作種類,但使用不同的 model/effort/max_tool_calls/system_file,而非不同的程式碼。請參閱 docs/examples/website-updates.yaml 中的任務 2–4 以了解參考形狀。

模型 ID 與參數

id用途備註
claude-haiku-4-5分類、提取、短摘要無 effort 參數
claude-sonnet-5範圍限定的代理器、較難的提取支援 effort 與適應性思考
claude-opus-5廣域代理器、困難的判斷支援 effort 與適應性思考

模型透過指定的提供者 (providers: 在 agent.yaml, provider: 在動作上; anthropic, openai 或 openrouter) 進行存取。其他提供者的 ID 會原樣使用,且需要 pricing: 條目,除非內建表格已知(目前的 OpenAI 模型)或提供者會回報成本(OpenRouter)。

ID 上無日期後綴。無助理預填。在建構模型級聯之前,先在相同的輸入上以 effort: low 測量較強模型:在當前世代中,這通常能超越以高 effort 運作的較弱模型,且單一模型意味著單一提示快取命名空間。

撰寫 decide 任務

完整的欄位列表、連線注意事項與陷阱請參閱 references/decide-action.md。基本要點:

action:
  kind: decide
  provider: openrouter                 # 必須是 openrouter 提供者;預設值為 defaults.decide.provider
  budget: { max_usd: 0.001 }
  state:                               # 被判斷的內容;字串可模板化,鍵不可
    subject: ${event.payload.subject}
    body: ${event.payload.body}
  questions:                           # 靜態政策;此處無 ${…}
    kind:
      type: choice
      instructions: 寄件者希望對網站做什麼?
      criteria:
        event_list_update: 新增、移除或變更事件清單中的條目
        general_change: 對網站的其他任何變更
        ignore: 非變更請求(問題、感謝、垃圾郵件)
    urgent:
      type: noul
      instructions: 寄件者是否需要今天完成這件事?
  • 結果是答案映射:result.kind.choice、result.kind.confidence、result.urgent.noul (P(true))、result.<score>.score (層級索引的機率加權平均值)。使用 emit … when: 進行路由;閾值存在於任務中,從不在執行器中,並需根據真實資料進行校準。
  • 務必包含一個備用標籤 (ignore、other):若無,離題輸入會得到一個自信但錯誤的答案。
  • 條件會被字面遵循:它們是政策,像版本控制程式碼一樣對待它們。保持選項順序穩定(它會影響信心)。在一次呼叫中詢問多個問題;每個額外問題僅增加其自身的 Token 成本。
  • 傳入的內容是資料:它應放在 state 中,絕不在問題中。整個請求必須能容納在 32k Token 內。
  • 只有 openrouter 提供者類型能存取 Jev (typesafe/jev-1.13,預設模型);oa validate 會拒絕任何其他類型。不需要 pricing: 條目。

撰寫 llm 任務

完整的欄位列表與執行器說明請參閱 references/llm-action.md。基本要點:

action:
  kind: llm
  model: claude-haiku-4-5
  max_tokens: 512
  system_file: prompts/classify_email.md   # 靜態 → 可提示快取
  input: |
    主旨:${event.payload.subject}

    <email>
    ${event.payload.body}
    </email>
  output_schema:
    type: object
    additionalProperties: false
    required: [kind, summary]
    properties:
      kind: { enum: [event_list_update, general_change, ignore] }
      summary: { type: string }
  • 將系統提示放在一個檔案中,位於 prompts/ 目錄下,並使其為靜態且優先渲染,以便跨執行進行快取。將可變的事件資料放在最後,在 input 中。
  • 傳入的內容(電子郵件、聊天、PR 文字)是不受信任的。將其包裹在一個分隔區塊中 (<email>…</email>),並在系統提示中告知模型這些是資料。
  • 務必在綱要中包含一個逃生艙口(ignore、unknown、confidence),以便路由的 emit.when 可以丟棄非可操作的結果,而無需再次呼叫。
  • 使用 emit … when: 對結果進行路由;下游任務將觸發該事件。
  • 任何可以等待的任務都使用 batch: true(半價,結果以事件形式到達)。

撰寫 agent 任務

完整的欄位列表與執行器說明請參閱 references/agent-action.md。基本要點:

action:
  kind: agent
  connector: claude                     # 傳輸層:acp 連接器 (connectors.d/claude.yaml;沙箱:bwrap 在那裡)
  model: claude-sonnet-5                # 可選:在會話上設定(ACP 配置選項);未設定 = 使用代理器的預設值
  effort: medium                        # 可選:代理器的 thought_level 選項
  max_tool_calls: 20
  budget: { max_usd: 0.50 }
  workspace: { kind: git-worktree, repo: /var/lib/247-agent/repos/site, branch: main }
  tools: [read, edit, search, execute]  # ACP 工具種類;其他一切都被拒絕
  bash_allow: ["npm run build"]         # 代理器執行的任何指令都必須符合此規則
  system_file: prompts/agent_event_list.md
  prompt: |
    根據以下請求更新 data/events.yaml。不要修改任何其他檔案。
    完成後執行 `npm run build`。

    <email>
    ${event.payload.email.body}
    </email>
  result: { path: RESULT.json, schema: schemas/site_change.json }
  post:                                 # 僅在 status: done 後執行
    - shell: ["npm", "run", "build"]
    - shell: ["git", "commit", "-am", "events: ${result.summary}"]
emit:
  - type: site.change_done              # 在此事件上路由審批,絕不在 task.<name>.succeeded 上
    when: "result.status == 'done'"
    payload: { summary: "${result.summary}" }
  - type: site.change_blocked           # 代理器無法完成:說明缺少什麼
    when: "result.status == 'blocked'"
    payload: { summary: "${result.summary}", missing: "${result.missing}", email: "${event.payload.email}" }

不可協商的事項,因為它們是讓代理器能安全無人值守運作的關鍵:

  • 每次執行使用全新的工作區(git-worktree 位於 agent/<run_id> 分支上,或使用 temp),失敗時刪除,成功時保留。代理器絕不編輯基礎檢出。
  • tools + bash_allow 是完整的能力表面,每次權限請求都會被判斷,且絕不授予「始終」;代理器未經請求而執行的工具呼叫會在事後被判斷,違規會導致執行失敗(unasked_execute: sandboxed 僅放寬指令檢查,且僅限於 Codex,其自身的沙箱限制了它未詢問的內容)。授予最小權限;提示不是安全邊界。mcp_servers 將連接器操作新增為工具:授予命名的操作({ connector: email, ops: [fetch_new] })而非整個連接器,為它們將代理器的種類(對於 claude-agent-acp 為 other)新增到 tools 中,且絕不授予能自行發佈或發送的連接器。
  • 代理器絕不持有部署金鑰,也絕不發佈。 它進行編輯,post 閘門證明建置仍能成功,提交記錄它,而一個獨立的 shell 任務則進行部署。回滾方式是 git revert 後重新發佈。模型金鑰存在於連接器清單的 env 中,而非任務中。
  • RESULT.json 是合約,執行器在每個提示中都會說明它:status: done | blocked 加上 summary,然後是任務的 result.schema。done 會執行閘門;blocked 會跳過它們,但執行仍算成功,因此 emit … when: "result.status == 'blocked'" 會將「因為缺少 X 而無法完成」的結果路由到一個回覆任務。設計每個代理器任務時都應包含兩個分支,並在 done 事件上觸發發佈。
  • post 閘門是確定性的,不涉及模型。失敗的閘門會導致執行失敗。
  • max_tool_calls 與 budget 是硬性停止點(會話會被取消);如果代理器未報告使用量或成本,則該輪執行失敗。
  • concurrency: 1 應用於共用儲存庫的任務;timeout 是每次嘗試的掛牆時鐘時間。
  • 高影響的變更在發佈前需要一個審批閘門(wait + 聊天);247-agent-tasks 技能中有此模式。

預算與分類帳

每個模型呼叫都通過 ctx.llm 連接埠,該連接埠會記錄使用量(提供者、模型、輸入/輸出/快取 Token、美元)到分類帳中,並強制執行執行的 budget.max_usd(呼叫前的最壞情況,呼叫後的實際情況:超額將導致執行失敗)以及全域的 budgets.daily_usd(每個 UTC 日,一旦超過,該日內的每個模型呼叫都會快速失敗,並發出一次 budget.exceeded 事件,notify 任務應監聽此事件)。沒有價格的模型會導致驗證失敗。絕不新增無預算的呼叫,包括執行器內部的「輔助」呼叫:使用 ctx.llm,絕不直接使用 SDK。agent 輪次是模型由其他人(ACP 代理器,使用其自己的金鑰)呼叫的唯一情況:執行器會將代理器透過 ctx.llm.record 報告的內容以連接器的名稱記錄到分類帳中,並在報告的成本超過上限時取消會話。oa cost --by task --since 7d 可顯示分類帳。

目前狀態

llm 動作已通過驗證,並與 providers:/pricing: 交叉檢查,可透過 ctx.llm 執行,已套用分類帳與預算,且所有三種提供者類型(anthropic、openai、openrouter)都有適配器。batch: true 在 anthropic 提供者上運作(Message Batches,執行將等待直到 llm.batch.ended;請參閱 references/llm-action.md)。decide 動作透過相同的連接埠 (ctx.llm.decide()) 執行,Decisions API 僅在 openrouter 適配器中實作;docs/examples/decide-triage.yaml 是參考。agent 動作在 ACP 連接器 (transport: acp) 上執行;docs/examples/website-updates.yaml 中的任務 3、3b 與 4 是參考,docs/examples/connectors.d/claude.yaml 是連接器;會話會以逐字稿 (oa runs logs <id>) 的形式持久化,並在 retention.runs 設定時間後隨執行一起刪除。mcp_servers 透過核心的工具橋 (packages/core/src/connectors/mcp-bridge.ts) 向會話提供連接器操作。動作上的 model 與 effort 會設定會話的 ACP 配置選項(類別 model 與 thought_level)。已完成執行的 work/<run_id> 會在執行完成後由 retention.workspaces(預設 7 天)清理。

新增適配器或變更執行器時,請遵循 references/llm-action.md、references/decide-action.md 與 references/agent-action.md,並確保 docs/internal/model-actions.md、docs/internal/agent-action.md 以及 docs/tasks/ 下的使用者頁面與程式碼保持同步。

相關技能