247エージェントモデルアクション は何をしますか?
デーモンの設計原則: 制御フローにLLMを入れない。マッチング、重複排除、ルーティング、再試行、公開はコードで行います。モデルはdecide、llm、agentアクションの内部でのみ、タスクに最適な最小コストのティアで、予算制限付きで実行されます。このスキルは、これら3つのアクションを適切に記述し、それらを実行するランナーを扱うためのものです。
最初にモデルが必要かどうかを判断する
以下の順序で判断してください:
- トリガーの
filterで判断できるか?(送信者、ラベル、リポジトリ、キーワード)→ モデル呼び出しではありません。 - スクリプトやコネクタ操作で決定論的に答えを生成できるか?→
shell/connector。 - ラベル、Yes/No、レベル分けであり、テキストを生成しない(分類、ルーティング、トリアージ、ゲート)か?→
decide:分類専用モデル、キャリブレーション済み確率、llm呼び出しの約100分の1のコスト。 - 固定された出力形状でテキストが必要な判断(フィールド抽出、要約、下書き)か?→
llm、まずHaikuを使用。 - ファイルの読み取り、コマンド実行、反復処理が必要か?→
agent、成功可能な最小範囲で。
異なるインテリジェンス要件を持つ2つのタスクは、異なるコードではなく、異なる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と適応的思考をサポート |
モデルは名前付きプロバイダー(agent.yamlのproviders:、アクションのprovider:; anthropic、openai、openrouter)を介して到達します。他のプロバイダーのIDはそのまま使用され、組み込みテーブルが認識している(現在のOpenAIモデル)か、プロバイダーがコストを報告する(OpenRouter)場合を除き、pricing:エントリが必要です。
IDに日付サフィックスは付けません。アシスタントプリフィルは使用しません。モデルのカスケードを構築する前に、より強力なモデルを同じ入力に対してeffort: lowで測定してください。現在の世代では、これは高努力の弱いモデルを凌ぐことが多く、1つのモデルは1つのプロンプトキャッシュ名前空間を意味します。
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)を含めてください。これがないと、トピック外の入力に対して自信過剰な誤った回答が生成されます。 - 基準は文字通りに従われます。これらはポリシーであり、コードのようにバージョン管理します。オプションの順序を安定に保ってください(信頼度が変わります)。1回の呼び出しで複数の質問をしてください。追加の質問ごとに、自分のトークンだけが追加で消費されます。
- 受信コンテンツはデータです。
stateに配置し、質問には決して配置しません。リクエスト全体は32kトークンに収まる必要があります。 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: |
Subject: ${event.payload.subject}
<email>
${event.payload.email.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}" }
譲れない条件(これらがエージェントを無人実行しても安全にするものです):
- 実行ごとに新しいワークスペース(ブランチ
agent/<run_id>上のgit-worktree、またはtemp)、失敗時は削除、成功時は保持。エージェントはベースチェックアウトを決して編集しません。 tools+bash_allowが全機能面であり、権限リクエストごとに判断され、「常に」許可されることはありません。エージェントが許可なく実行したツール呼び出しは事後判断され、違反は実行を失敗させます(unasked_execute: sandboxedはコマンドチェックのみを緩和し、Codexに対してのみ、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ポートを通過し、台帳に使用量(プロバイダー、モデル、入力/出力/キャッシュトークン、USD)を記録し、実行のbudget.max_usd(呼び出し前の最悪ケース、呼び出し後の実際: 超過は実行を失敗させる)とグローバルbudgets.daily_usd(UTC日ごと。一度超過すると、その日のすべてのモデル呼び出しは即座に失敗し、budget.exceededが1回発行され、notifyタスクがリッスンする必要があります)を適用します。価格がないモデルは検証に失敗します。予算設定がない呼び出しを決して追加しないでください。ランナー内部の「ヘルパー」呼び出しも含めて、ctx.llmを使用し、SDKを直接使用しないでください。agentターンは、モデルが他の誰か(ACPエージェント、独自のキーを持つ)によって呼び出される唯一のケースです。ランナーはエージェントがctx.llm.recordを通じて報告したものをコネクタ名で台帳に記録し、報告されたコストが上限を超えたときにセッションをキャンセルします。oa cost --by task --since 7d で台帳を表示できます。
現状
llmアクションは検証され、providers:/pricing:とクロスチェックされ、ctx.llmを通じて実行可能で、台帳と予算が適用され、3つのプロバイダータイプ(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/下のユーザーページをコードと同期させてください。