コンテンツにスキップ

自律ゴールループ(Goal Loop)

会話の中でゴールを1つ渡すだけで、AI従業員は自律的に計画・実行・自己検収し、完了または行き詰まったときに戻ってきて知らせてくれます。このページでは、チャンネルから /goal を使う方法、自律度(AutonomyLevel)の段階、関連する設定キー、そして人による対応が必要になったときのボタンの意味を説明します。

ディスパッチエンジンは v1.59 以降デフォルトで有効です(ゴールタスクがないときは定期的な SQLite ポーリングのみを行い、タスクが実際に review に入って初めて LLM 呼び出しが発生します——後述の「二段階検収判定」を参照)。通常の一問一答の会話には一切影響しません。不要な場合は config.toml に [dispatch] enabled = false を設定するか、ダッシュボードの「設定 → 自動化」で「ディスパッチエンジン(派工引擎)」のスイッチを切ってください(再起動不要でホットリロードされます)。


接続済みのどのチャンネル(Telegram / Discord / Slack / LINE / …)からでも、AI従業員に対して次のように入力します。

コマンド 動作
/goal <ゴールの説明> 現在の会話の AI従業員に割り当てられた自律ゴールタスクを作成します。検収基準を別途指定しない場合は、ゴールの説明そのものが検収基準になります。
/goal <ゴール> || <検収基準> || で区切ります。前半がゴール、後半が検収基準(ジャッジが照合する基準)です。
/goal <ゴール> || <検収基準> || outcome:<spec> さらに構造化された成果物検収の層を追加します(後述の「構造化された成果物検収」を参照)。納品前にゼロコストの決定的チェックを実行し、基準未達ならジャッジを呼ばずにそのまま修正へ差し戻します。
/goal status 現在の AI従業員が進行中のゴールタスクを一覧表示します(短縮コード/状態/何ラウンド目か)。
/goal 使い方を表示します。

例

/goal この顧客データをまとめて月次レポートを作り、送信して || レポートには月次売上グラフを含め、boss@example.com に送ること
/goal Q3の月次レポートを作成 || 月次売上グラフを含めること || outcome:files:report.docx

作成すると、タスクの短縮コード、ラウンド上限、そして「完了または行き詰まったらここで通知します」という確認メッセージが返信されます。タスクの進捗と人的対応が必要な通知は、AI従業員の [proactive] 通知チャンネルだけでなく、あなたがゴールを作成したこの会話(発信元チャンネル)にも押し戻されます。

ディスパッチエンジンが無効([dispatch] enabled = false)の場合でもタスクは作成されますが、確認メッセージで自動的には実行が始まらない旨が案内されます。


ゴール契約:作成時に凍結され、後からこっそり変更できない

Section titled “ゴール契約:作成時に凍結され、後からこっそり変更できない”

ゴールを作成した瞬間、検収基準は不変のベースライン(acceptance_criteria_baseline)として凍結されます。以後のすべての判定——一次評価器、MAV検収ジャッジ——はこの凍結されたベースラインのみを読み、後から編集される可能性のあるフィールドは決して参照しません。これは両方向の「契約のこっそり変更」を防ぐためのものです。AI従業員がタスク実行中に自分で検収基準を緩めることはできず、また運用者もダッシュボードのフィールドを編集しただけで判定基準そのものを変更したと誤解することがありません。

  • AI従業員は変更できない:エージェント身分で MCP の tasks_update を呼び出し、自分のゴールタスクの acceptance_criteria を変更しようとしても、その呼び出しはまるごと拒否され、監査ログに1件記録されます(理由:goal_contract_frozen)。ゴールタスクの title と description はジャッジが読むゴールそのものなので、AI従業員の tasks_update がどちらかを変更しようとした場合も同じように拒否されます。タスクの制御用タグ(outcome:…、grant:…、auto-research)も、AI従業員は追加・削除・並べ替えできません(理由:reserved_tag_change)。
  • 運用者は表示用のコピーを編集できるが、判定基準そのものは変わらない:ダッシュボードの tasks.update はタスク上に表示される acceptance_criteria(人が読むための補足など)を編集できますが、凍結されたベースライン値は連動して変わりません。ジャッジと評価器は引き続き、タスク作成時に設定された基準で判定を続けます。本当に検収基準を変えたいなら、それは新しいゴールを作ることと同じです。
  • 凍結ベースラインを持たない古いタスク(この仕組みが導入される前に作成されたもの)は、変更可能なフィールドを読む従来通りの挙動にフォールバックします。

検収基準を指定しなかった場合のガイダンス

Section titled “検収基準を指定しなかった場合のガイダンス”

/goal <ゴールの説明>(|| なし)でもいつも通りタスクは作成され、ゴールの説明そのものが検収基準になりますが、確認メッセージには次回に向けてより明確にするためのヒントが1段付け加わります。

💡 今回は検収基準を別途指定していません。次回はこの4点を考えておくとより的確になります。
・ゴール:何を達成したいか
・入力:どんなデータや素材が必要か
・出力形式:成果物がどんな形か(例:Word/Excel/文章/画像)
・制約:スタイル、期限などの制限、そして「何をもって完了とするか」
具体的で結果が確認できる検収基準を3〜5個用意してみてください(「よくできている」ではなく「レポートに月次売上グラフを含む」のように)。
/goal 説明 || 基準 の形式で再提出すればOKです。

|| で検収基準を明示している場合、このヒントは表示されません。planner_enabled を有効にしたサブタスク分解も同じ規律に従います。各検収基準は「結果」を書き「やり方」は書かない(HOW を凍結すると、別の正しい経路で作ったのに誤って失敗判定される可能性があります)、3〜5個に絞る(契約が重くなるほどサブタスクは収束しにくくなります)、範囲外の事項は検収基準に無理やり詰め込まず Non-goals として扱う、という点です。


検収台帳(検収基準の項目別管理)

Section titled “検収台帳(検収基準の項目別管理)”

凍結された検収基準は一つのテキストです。ジャッジには項目ごとに確認するよう指示していますが、すべての項目が実際に扱われたことをプログラムで確かめる手段はありませんでした。検収台帳はそれを補います。

作成されるタイミング。 ダッシュボードまたは MCP tasks_create kind="goal" で作成したゴールは、作成時に凍結基準から台帳を持ちます。空でない行ごとに1項目、C1、C2… と順に番号が振られます。追跡は最大20項目で、21行目以降は注記付きで C20 に統合され、捨てられることはありません。システムは各項目に安定した id(canonical_id(タスク id, "criterion", 番号, 本文のフィンガープリント))も付けるので、モデルは短い番号を返すだけで、自分で id を作ることはありません。この機能より前に作成されたゴールや、モードが off のときに作成されたゴールには台帳がなく、従来どおりに動きます。チャットの /goal コマンドや、ゴール提案の確認(「立為目標任務」と「想一想」の両方)から作成したゴールにも同じ方法で台帳が作られます。autopilot ルールが作成したゴールと、プランナーが分解したサブタスクには台帳がありません。

実行者に見えるもの。 各ラウンドのディスパッチには <state> ブロックの直後に ## 驗收帳本 セクションが入り、項目ごとに1行で現在の状態と報告方法が示されます。実行者は tasks_complete の結果サマリーの最後にタグを付けます。

<criteria_status>[{"id": "C1", "status": "covered", "evidence": ["reports/summary.md を作成"], "unresolved": []},
{"id": "C2", "status": "blocked", "evidence": [], "unresolved": ["メール送信の権限がない"]}]</criteria_status>

タグの中身はちょうど一つの JSON 配列でなければならず(前後に文章を置かない、余計なフィールドを入れない)、すべての番号がちょうど一回ずつ必要です。status は covered(evidence 必須、unresolved は空)、blocked(unresolved 必須)、candidate(完了したと考えているが確認が必要、evidence 必須)のいずれかです。evidence と unresolved の各項目は500文字で切られ、各フィールド最大8項目です。どれか一つでも違反した報告は丸ごと破棄されます。台帳はそのまま、invalid_reports が1増え、security_audit.jsonl に criteria_status_invalid イベント(違反内容と、マスク後のタグ本文最大200文字)が1件書かれます。タグのないラウンドは何も変えず、カウントもされません。ジャッジが読むテキストとチャットに返す ✅ メッセージからは、このタグが取り除かれます。

モード(config.toml [goal_loop] criteria_ledger、毎ラウンド読み込み、再起動不要):

モード 台帳 ジャッジ
off 作成・注入・解析しない 変更なし
report(デフォルト) 作成・注入・解析し、人に表示 実行者の自己申告による台帳を「自己申告であり証拠ではない」と明記した参考ブロックとして受け取る。返答形式は変わらない
enforce report と同じ パネルは criteria: [{"id": "C1", "pass": true, "reason": "..."}] も返す必要があり、各番号はちょうど一回。欠落や重複はその項目の FAIL。correctness はすべての項目が合格し、かつその観点自体も合格したときだけ合格

不明な値は report として扱われます。enforce への切り替えは strict_reply_parsing と同じ観察期間の規律に従い、実際のジャッジラウンドを見てから自分で切り替えてください。enforce でも外部ジャッジ(judge = "external")には項目別の判定を求めず、その pass/fail がそのまま使われます。

確認できるもの。 tasks.timeline は criteria_ledger(台帳がなければ null)を返します。中身は mode(現在有効なモード)、units[](id、handle、text、status、evidence、unresolved、updated_round)、last_report_round、invalid_reports です。台帳を持つゴールが needs_human になると、通知カードに 驗收帳本:1/3 條已回報達成;C2 受阻(沒有寄信權限);C3 尚未回報 のような1行が加わります。各ラウンドの台帳はそのラウンドの iteration 記録にも残ります。

needs_human の pause_reason と台帳は別の問い(ループがなぜ止まったか/どの項目がまだ終わっていないか)に答えるもので、統合はしません。

ゴールタスクの状態が遷移するたびに、発信元の会話へ短い(1〜3行程度の)進捗メッセージが押し戻されます。

  • 実行開始/再試行(上限中の第Nラウンド)
  • 検収中
  • 却下 → 修正して再試行(ジャッジのフィードバック要約付き)
  • 完了 ✅(結果の要約付き)
  • 行き詰まり → あなたの判断が必要(同時に承認ボタンを送信、一時停止理由の分類付き——後述の「needs_human ボタンの意味」を参照)

同じタスク・同じ状態は重複して通知されません。発信元の会話が存在しない場合は AI従業員の [proactive] チャンネルにフォールバックし、両方とも存在しない場合はダッシュボードの Activity Feed に書き込まれるだけで、あなたを煩わせません。

タイムアウト時の進捗レポート

Section titled “タイムアウト時の進捗レポート”

タスクが認領(in_progress)された後、[goal_loop] progress_report_minutes(デフォルト10分)を超えても観測可能な進捗シグナルが一切ない場合(Activity Feed のイベントを基準とします——updated_at フィールドは lease renewer によって定期的に更新されるだけなので「動いている」証拠にはなりません)、ドライバーは「実行開始からX分経過しても進捗報告がなく、まだ実行中です」という通知を1件送信します(Activity Feed +発信元の会話)。同一ラウンド内では最大1回のみです。

これはあくまで通知であり、介入ではありません。再ディスパッチも、エスカレーションも、タスクのキャンセルも行いません。実際に手を動かすのは従来通り stalled_secs(再ディスパッチ)、iteration_cap(人的対応へ)、wall_clock_hours(人的対応へ)の各ガードだけです。0(または負数)に設定するとこの機能全体がオフになり、オフの間は追加のクエリも一切発生しません。


ツール連打アドバイザリー(tool streak)

Section titled “ツール連打アドバイザリー(tool streak)”

自律ループの中で、AI従業員が「同じツールを同じパラメータで何度も繰り返し呼び出す」ループにはまることがあります。結果はとっくに得られているのに、自分が繰り返していることに気づいていない状態です。これは後述の「停滞検知」とは異なります。停滞検知は連続する2ラウンド(ディスパッチ→検収)が揃って初めて行き詰まりを検知しますが、ツール連打アドバイザリーは1ラウンド内のツール呼び出しの並びを見ており、ジャッジが介入する前に先に注意を促せます。

判定基準は同じツール・同じマスク済みパラメータ(監査ログですでに行っている機密マスキングを再利用)の連続呼び出し回数で、閾値ごとに警告の強さが上がっていきます。

連続回数 警告内容
3回 前回の実行結果を読み直し、必要な情報がすでに得られていないか確認することを提案し、無駄な繰り返しでラウンドを消費しないよう促す
5回 現在のやり方では進展していない可能性があると指摘し、別の方法や角度を試すよう提案する
8回 繰り返しを止めるよう強く提案する。現時点で得られている結果をまとめて報告するか、tasks_block を呼んで何に阻まれているかを説明し助けを求める

このリマインダーは次のラウンドのディスパッチの <state> ブロックに注入され、LLMコストはゼロで純粋にアドバイザリーです。ツール呼び出しやディスパッチをブロックしたり、リトライさせたり、拒否したりすることは一切なく、従うかどうかは AI従業員自身の判断に委ねられます。リマインダー自体は意図的に state_hash から除外されており、既存の(状態、行動)振動検知を妨げません。

config.toml [goal_loop] tool_streak_advisory(デフォルト true)でこの機能全体をオフにできます。


各 AI従業員の自律度は agent.toml [capabilities] autonomy_level という1つのダイヤルで制御されます。未設定または解析不能な場合はデフォルトの Approver(保守的:行き詰まったときや人的対応が必要なときだけ質問する)になります。

レベル 動作
operator ループはまったく自律駆動しません。タスクは作成後静止し、人が手動で進めます。
collaborator 最初のディスパッチ前に人による承認(キックオフ承認)が必要です。承認後は完了まで自律的にリトライします。
consultant collaborator と同じキックオフ承認が必要です。
approver デフォルト。キックオフのゲートはなく、行き詰まったとき、または本当に人的対応が必要なときだけエスカレーションします。
observer 完全自動。人的対応が必要な場合も通知するだけで待機しません(タスクは自動的に終了します)。
agent.toml
[capabilities]
autonomy_level = "approver"

タスク単位の権限付与(scoped_tools、v1.41)

Section titled “タスク単位の権限付与(scoped_tools、v1.41)”

高リスクなツールは「権限付与がなければ使えない」と宣言できます。scoped_tools に列挙されたツールは、AI従業員が有効な権限付与(grant)を得るまで一律拒否され、しかも権限は単一タスクのライフサイクルの中でのみ生きています。そのタスクが終了(受理・却下・人的対応へ・キャンセル)した瞬間にすべて自動的に取り消され、次のタスクへ持ち越されることはありません。

agent.toml
[capabilities]
scoped_tools = ["shared_wiki_delete", "odoo_execute"] # これらのツールはタスクごとの権限付与が必要
grant_ttl_secs = 3600 # 権限付与が生存できる秒数の上限、デフォルト 3600

権限付与を得る方法は2つあります。

  1. AI従業員自身が申請する:MCP ツール capability_request { tool, reason, task_id? } を呼び出すと承認リクエストに変換され(他の承認と同じ通知/ダッシュボードの導線を使います)、あなたが承認すれば権限が有効になります。期限までに判断されなければ拒否扱いになります。
  2. ゴールタスクの開始時にまとめて付与する:ゴールタスクの tags に grant:<ツール名> を追加しておくと、キックオフ承認(collaborator/consultant レベル)が承認された時点で原子的に付与され、タスク終了時に自動的に回収されます。

判定は常に fail-closed です。権限データベースが読めない場合は「権限なし」として扱われます。scoped_tools に列挙されていないツールはまったく影響を受けません。


[dispatch]
enabled = true # 自律ディスパッチエンジン(goal loop ドライバーを含む)を有効化。デフォルト false
policy = "fixed_hierarchy" # ディスパッチポリシー(どの AI従業員がタスクを引き受けるか)。後述「ディスパッチポリシー」を参照。デフォルト fixed_hierarchy
grounding_precheck_enabled = true # 検収前のグラウンディング事前チェック(「グラウンディング事前チェック」を参照)。デフォルト true
two_stage_judge = true # 検収前に安価な一次評価を実行するか(「二段階検収判定」を参照)。デフォルト true
strict_reply_parsing = "shadow" # ジャッジ応答の厳格 JSON 契約:off / shadow / enforce(「ジャッジ応答の厳格契約」を参照)。デフォルト shadow
judge = "mav" # 誰が検収を判定するか(「検収ジャッジの差し替え」を参照)。mav / external(evaluator_only / human_only は v1.69.0 で削除)。デフォルト mav
judge_provider = "antigravity" # 任意:ジャッジを別のランタイムで実行(「ジャッジを別のモデルで実行する」を参照)。未設定 ⇒ デフォルトのユーティリティ用ランタイム
judge_model = "gemini-3-pro-preview" # 任意:そのランタイム内のジャッジ用モデル id。未設定 ⇒ デフォルトのユーティリティ用モデル
admission = "queue" # エフェメラルな子エージェント(ephemeral spawn)が並行数上限に達したときの扱い、"queue" または "fail"。デフォルト queue(後述「エフェメラル spawn の受け入れキュー」を参照)
[task_forward_model] # タスク層のフォワードモデル(同名セクションを参照)。v1.54 以降デフォルトでオン
enabled = true
[goal_loop]
iteration_cap = 5 # 難しいゴールのディスパッチ回数のハード上限。超えると人的対応へ。デフォルト 5
iteration_cap_simple = 3 # 簡単なゴールのディスパッチ回数上限(動的ジャッジ深度による)。デフォルト 3
wall_clock_hours = 24 # 作成時点からの経過時間の予算(時間)。超えると人的対応へ。デフォルト 24
max_concurrent = 3 # 同時に飛んでいるゴールタスクの上限(spawn の暴走防止)。デフォルト 3
tick_secs = 30 # ドライバーのポーリング間隔(秒)。デフォルト 30
stalled_secs = 600 # ディスパッチ後にこの秒数だけ認領がなければ停滞とみなし再ディスパッチ可能にする。デフォルト 600
planner_enabled = false # 有効にすると、ゴールを依存関係付きのサブタスク DAG に分解できる(「並列サブタスク」を参照)。デフォルト false
resume_on_restart = "pause" # gateway 再起動時の進行中ゴールタスクの扱い、"auto" または "pause"(「再起動時の挙動」を参照)。デフォルト pause、ダッシュボードの「設定 → 自動化」で切り替え可能
progress_report_minutes = 10 # 認領済みタスクが進捗シグナルなしにどれだけ経過したら1回通知するか、`0` で無効化(「タイムアウト時の進捗レポート」を参照)。デフォルト 10
tool_streak_advisory = true # 同じツールを同じパラメータで3/5/8回連続呼び出した際にリマインダーを注入するか(「ツール連打アドバイザリー」を参照)。デフォルト true
criteria_ledger = "report" # 検収基準の項目別台帳:off / report / enforce(「検収台帳」を参照)。デフォルト report
steering_enabled = false # タスクページの「次のラウンドへの指示」(「タスクページの指示と停止」を参照)。デフォルト false
[dispatch_guard] # フィードバック経路のサーキットブレーカー(自己増幅型の無限ループを防ぐ)
window_secs = 60 # スライディングウィンドウの長さ(秒)。デフォルト 60
max_in_window = 20 # 1ウィンドウ内で許容されるディスパッチ回数、超えるとトリップ。デフォルト 20
cooldown_secs = 60 # トリップ後、ディスパッチを拒否するクールダウン秒数。デフォルト 60
max_hop_depth = 5 # 委任チェーンをまたぐプロセス間 re-spawn の深さ上限。デフォルト 5

すべてのブロックは省略可能で、未設定または一部だけ設定されている項目は上表のデフォルト値にフォールバックします。未知の policy 値は常に fixed_hierarchy にフォールバックし、警告を1件記録します。


並列サブタスク(依存関係 DAG)

Section titled “並列サブタスク(依存関係 DAG)”

[goal_loop] planner_enabled = true にすると、ゴール作成時にまず AI従業員が依存関係を注釈したサブタスクの集合に分解することを「試みます」(例:2つのデータソースをそれぞれ調べてから統合する、など)。分解されたサブタスクはそれぞれ Task Board 上に載り、depends_on がすべて満たされたサブタスクは並行して実行され、それぞれ独立に検収されます。並行度は依然として max_concurrent と dispatch_guard サーキットブレーカーの制約を受け、それを迂回することはありません。

  • 強制ではありません:モデルが分解不要と判断した場合(またはその返答が解析できなかった場合)は単一タスクにフォールバックし、この機能をオフにしたときと完全に同じ挙動になります。
  • 循環依存の防止:分解された計画に循環依存(またはインデックス範囲外の参照)が含まれる場合、計画全体が破棄され単一タスクにフォールバックし、警告が記録されます。壊れた DAG が着地することは決してありません。
  • 上流の行き詰まりは下流を孤児化しない:あるサブタスクの上流の依存先が failed / cancelled / needs_human になった場合(または依存先が存在しない場合)、下流のサブタスクはエスカレーションを継承して同じく人的対応へ移行し、行き詰まった一連の枝全体が見えるようになります。上流がまだ実行中なだけであれば、下流はそのラウンドは凍結され、次のラウンドで改めて判断されます。

想定される効果が最も大きいのは「複数データソースの照会」型のゴールです。独立した再テストではおよそ 1.25 倍の高速化が確認されました(論文が自己申告する 3.7 倍ではありません)。一般化する前に、eval による実測を基準にしてください。


ディスパッチポリシー(DispatchPolicy)

Section titled “ディスパッチポリシー(DispatchPolicy)”

[dispatch] policy は「どの AI従業員がゴールタスクを引き受けるか」を決めます。デフォルトの fixed_hierarchy は従来と完全に同じ挙動です(タスクに元から割り当てられている相手にディスパッチします)。

ポリシー 動作
fixed_hierarchy デフォルト。タスク既存の assigned_to にそのままディスパッチします。LLM コストはゼロで、完全に決定的です。
round_robin 「タスクのカテゴリ」(タグがあれば最初のタグ、なければ優先度)に基づき、名簿を順番に回します。状態はメモリ上にのみ存在し、再起動でリセットされます。
llm_select LLM がツール呼び出しを通じて名簿の中から最適な AI従業員を選びます。fail-closed:出力が名簿に存在しない場合、あるいは解析や LLM 呼び出しが失敗した場合は、常に fixed_hierarchy の結果にフォールバックし、存在しない AI従業員にディスパッチすることは決してありません。モデル名はハードコードされておらず、設定されたユーティリティ用ランタイムを使用します。
role_team 選ばれるのは fixed_hierarchy とまったく同じく AI従業員です。ロールはその従業員の内部にあります(後述の「チームラウンド」を参照)。この設定は「このデプロイはチームを編成する」ことをログとテレメトリで見えるようにするためのもので、タスクの割り当て先は変わりません。

名簿 = <home>/agents/ 配下の AI従業員ディレクトリ。名簿が空の場合、round_robin と llm_select はいずれも元の割り当てにフォールバックします(タスクを孤児化しません)。再割り当てはタスクの assigned_to に書き戻されるため、ハートビートの取得とアクティビティログの整合性が保たれます。


AI従業員は、ゴールの1ラウンドを自分の内部の小さなチームとして進めることができます。計画 → 実行 → レビューの各ロールが、それぞれ自分のベンダーのモデルで動きます。v1.66 以降、[team] enabled のデフォルトは true ですが、実際にチームを成立させるのは [team.roles] で2社目のベンダーを指定することであり、このフラグではありません。ロールを何も書かなければ、実行とレビューの両方が従業員自身のモデルにカスケードして同じモデルファミリーになり、相関除去ルールがこの仕様を拒否します。タスクは静かに Solo で動き、監査行も残りません。全体像は 56-team-as-agent.md を参照してください。このセクションでは goal loop に関わる部分だけを扱います。

経路全体(プランナー、エグゼキューター、ベリファイア、そしてそれらの間でパケットを運ぶ team_handoff ツール)は実装済みで、ジャッジが受理したライブラウンドで実際に動かしています。ただしこれは1回の統合結果であり、Solo に勝ったという測定結果ではありません。[team.roles] は、監視できるデプロイでのみ設定してください。enabled = false(フリート全体または従業員単位)と gate = "always_solo" は、どちらも1行で元に戻せます。

会話には新しいものは何も現れません。従業員は1つの声で答え、進捗は同じボードに届き、あなたの対応が必要なタスクは引き続き6つの一時停止分類のいずれかを持ちます。内部では、1回の起動メッセージの代わりに3つのステージでラウンドが進み、検収ジャッジに届くのはエグゼキューターの最終成果物だけです。そのジャッジは、これまでと同じ二段階評価器と3方向パネルです。チームが変えるのは「誰が作業するか」であり、「誰が完了と判断するか」ではありません。

チームタスクがあなたの手元に落ちてくる新しい理由が2つあります。

一時停止 何が起きたか
判断が必要(blocked_needs_decision) 計画ステージがサブタスクを1つも返しませんでした。ループは文章から分解を推測せず、そのゴールが本当に分割できるのか、それとも単独の従業員としてそのまま実行すべきかをあなたに尋ねます。
予算切れ(budget_exhausted) タスクが一部を消費した後でロールメンバーの spawn 予算を使い切りました。ほかの予算エスカレーションと同じく、それまでに出せた最善のラウンドを渡します。劣化させた1ラウンドすら予算で賄えなかったタスクは、代わりに Solo で動きます。まだ始まってもいない作業のために停止されるより、通常の方法でやってしまう方がましだからです。

各ラウンドの前に、LLM コストゼロのルールセット(crates/duduclaw-core/src/team_gate.rs)が Solo か Team かを決めます。意図的に Solo に寄せてあります。

  1. 強制的に Solo:従業員が [container] sandbox_enabled = true にしている場合(always_team を含むすべてのモードより先に確認されるため、サンドボックスを有効にした従業員はチームを組みません)、ライブのチャンネルターン、あなたの承認待ちのままの plan-first ゴール、計画に不可逆なアクションが含まれる場合、残り予算が 3 ラウンド未満の場合。
  2. 4 つのシグナルを数える:bulk(独立して進められる作業項目が 4 つ以上あり、依存関係のハブがない)、context overflow(推定入力がモデルのコンテキストウィンドウを超える)、capability gap(ロール行列の差が、行列で宣言された MDE 以上)、long horizon(検収基準が 3 つ以上あり、タスクが成果物を作る)。測定できないシグナルは発火しません。
  3. 判定:3 つ以上でチームを編成し、0 または 1 つなら Solo、ちょうど 2 つならグレーゾーンです。

グレーゾーンでは、ループは計画ステージを 1 回実行し(タスクがどのみち必要としていた呼び出しです)、同じルールをもう一度適用します。今回は bulk シグナルを、プランナーが実際に書いたサブタスクのパケットから測定します。計画ができる前の bulk シグナルには測定対象がないため、グレーゾーンは常に残り 3 つのシグナルのうち 2 つが発火した状態です。2 回目の判定でチームが編成されるのは、計画に互いの依存関係のハブがないサブタスクが 4 つ以上ある場合だけで、それ以外は通常の単独従業員ラウンドに戻ります。プランナーのロールがないチーム仕様では 2 回目の判定ができないため、Solo で動きます。

すべての判定は、発火したシグナルとともに team_gate_decision として監査ログに書かれるため、デプロイの Solo/Team の比率は逸話ではなく測定できます。

仕様はタスクごとに凍結される

Section titled “仕様はタスクごとに凍結される”

タスクが使うチームは作成時に1度だけ決まり、タスクに保存されます。後からの [team] の変更は次のタスクに影響します。検証に失敗した仕様(最も多いのは、ベリファイアがエグゼキューターとモデルファミリーを共有している場合)では、チームはまったく編成されません。タスクは Solo で動き、部分的なチームは存在しません。

この拒否が目立つかどうかは、誰がチームを要求したかによります。enabled = true と書いた運用者、またはロールを設定したのに検証に失敗した運用者には、ロールと理由を添えた team_refused として監査された拒否が返ります。[team] にまったく触れていないデプロイには debug! の1行だけが出て、監査ログには何も残りません。この拒否は v1.66 のデフォルト反転以降、すべてのインストールの既定状態であり、あらゆる場所のすべてのゴールタスクに行を刻むと、本物の拒否が見つけられなくなるからです。

model が未設定のロールは、従業員の [model] preferred にフォールスルーする前に、測定済みの能力マトリクス(<DUDUCLAW_HOME> 内の role_model_matrix.toml。duduclaw eval --matrix が書き出します)から埋めることもできます。そのロール自身のランタイムの resolved セルだけがカウントされ、同点の場合は何も選ばれず、明示的に設定されたモデルが常に優先されます。

config.toml
[dispatch.team_budget]
max_spawns_per_task = 12 # 4 ロール x 3 ラウンド。下限は 3 にクランプ
max_turns_per_role = 3
degrade_order = ["utility", "verifier_second_pass", "executor_replica"]

1ラウンドの課金は planner? + executors + verifier + repair? です。ベリファイアは scaffold ではなくユーティリティ呼び出しですが、独自の台帳行を書き込み、予算はメンバー id を持つ行をそのまま数えるため、ほかのステージと同じくスロットを1つ消費します。下限の 3 は、プランナー + エグゼキューター + ベリファイアです。

spawn 予算が減ると、機能はこの順で手放されます。まず合成、次にベリファイアの1回の修復パス、その次にファンアウトが単一のエグゼキューターへ縮退し、その後でタスクが budget_exhausted としてエスカレーションします。認識できないエントリは警告とともに破棄され、リスト全体が使えない場合はデフォルトのチェーンが維持されます。

最初のチームラウンドの前に、ループは [dispatch] ephemeral_max_active が、この設定で必要になりうる並行ロールメンバー数(max_concurrent × iteration_cap × roles。デフォルトの上限 32 に対して 45)を収容できるかも1度だけ確認し、引き上げるべき数値を添えて警告します。何も強制はされません。上限を超えるとロールの spawn はキューに入り、期限切れになることもあり、そうなると、あるラウンドからなぜかベリファイアが欠けているという形でずっと後になって表面化するためです。

ロールメンバーの spawn は専用のサーキットブレーカーのバケットと予算([dispatch_guard] role_team_max_in_window、デフォルト 60)で動くため、チームを編成中の従業員が、その従業員自身のサブエージェント spawn を守るブレーカーをトリップさせることはありません。

チームラウンドの証拠:従業員とそのメンバー

Section titled “チームラウンドの証拠:従業員とそのメンバー”

ラウンド以降のすべて、つまりチーム自身のベリファイア、グラウンディング事前チェック、MAV パネルの <tool_activity> ダイジェストは、タスクの認領から検収までの時間窓におけるツール呼び出しの監査証跡を読みます。Solo ラウンドでは、この証跡は1つの agent id に属します。チームラウンドでは違います。作業はそれぞれ自分の id を持つ短命なロールメンバーが行い、従業員自身の時間窓には、ラウンドを開いた帳簿上の呼び出しだけしか残っていない場合があります。

そう読むと、チームラウンドは、作業をしたと主張しながら何もしなかったタスクとまったく同じに見えます。ライブラウンド3で実際に起きたのがこれで、ベリファイアも settle の評価器も、実際に行われた作業を「ファイル作成を裏付けるツール活動がない」として却下しました。そこで、チームラウンドの証拠セットは、どちらの経路でも role_turns.jsonl から取った従業員 ∪ そのラウンドのロールメンバーになります。

  • チームのベリファイアの <tool_activity> ブロック
  • settle 経路のグラウンディング事前チェックとジャッジダイジェスト

重複する id は統合され、ロールメンバーのいないタスクは id を追加しないため、Solo タスクの見る証拠は以前とビット単位で同一です。時間窓は変わらないので、ラウンド番号による検索がタスク全体にフォールバックする場合でも(ループの進行中のイテレーションカウンターと settle 経路のリビジョンカウンターは別物で、gateway の再起動をまたぐと食い違うことがあります)、他のラウンドのメンバーは何も寄与しません。

ロールメンバーは、自分専用の使い捨て scaffold ではなく従業員のワークスペースで作業するため、メンバーが書き込んだファイルは、ベリファイアが尋ねたときにもそこに残っています。ファイルを書き込むロールは現時点で claude と codex に限られます。56-team-as-agent.md を参照してください。

id の和集合を取るだけでは必要でしたが十分ではありませんでした。ライブラウンド8の後にさらに2つの証拠ソースが加わり、どちらもチームのベリファイアと settle 経路が共有するため、同じラウンドについて両者が異なる説明で判断することはありません。

  • ネイティブツールの作業が永続化されます。 ネイティブツール(codex の shell、Claude の Write)で作業するメンバーは MCP 呼び出しを行わないため、以前はその作業が監査証跡にまったく残りませんでした。ラウンド8では、実在することが明らかな3つのファイルが却下されました。現在は、各ネイティブツールイベントがメンバーの id の下で tool_calls.jsonl の1行として書かれ、マスク済みの呼び出し入力と結果テキスト、さらに source = "native" とそれを生成したランタイム/モデルを持ちます。セルフエコーのツールは MCP ライターと同じく出力が抑制されたままなので、ロールが自分でエコーしたパケットを根拠に主張を裏付けることはできません。
  • <artifact_receipts>:パケットが宣言する artifacts[].path はすべて、従業員のワークスペースに対して stat とハッシュが取られ、その結果(<path> <bytes>B sha256=<hex> exists|missing|mismatch)がプロンプトブロックと artifact_receipt 監査行の両方になります。宣言されているがハッシュがない場合は、バイト列から補われます。宣言されたハッシュが一致しない場合は宣言どおりに保持され、team_packet_artifact_mismatch イベントとともに mismatch として記録されるため、すり替えは黙って訂正されず、見える形で残ります。確認としてカウントされるのは exists だけです。

成果物を宣言しないタスクではブロックは追加されず、ネイティブツールのメンバーがいない Solo ラウンドが見る内容は以前とまったく同じです。

イベント 意味
team_gate_decision Solo / Team / グレーゾーン。発火したシグナル付き
team_refused 有効化された仕様が検証に失敗し、タスクは Solo で動く
team_round_started 3ステージのラウンドが開始。ロールと劣化ステップ付き
team_member_spawned ロールメンバーが1つ作成された(ロール、ランタイム、モデル)
team_stage_failed あるステージが次のステージに必要なものを生成しなかった、またはまったく実行できなかった。role、runtime、model とエラー付き
team_handoff あるロールがパケットを提出した(leg、ラウンド、サイズ、宛先、ファイル)
team_packet_skipped パケットファイルが読めない、ラベルが誤っている、または無効で、無視された
team_packet_artifact_refused パケットが従業員のワークスペース外に解決される成果物パスを宣言した
team_packet_fidelity_corrected パケット自己申告の証拠グレードが観測結果と食い違い、上書きされた

各ステージは team_handoff を呼んで引き継ぎます。このツールはファイルパスを受け取らず、導出します。

~/.duduclaw/team_packets/<task_id>/r<round>/planner-to-executor.json
~/.duduclaw/team_packets/<task_id>/r<round>/planner-to-executor.01.json … up to .99

ゴールを4つのサブタスクに分解するプランナーは、同じ leg に4つのパケットを書きます。そのため新しいパケットは次の番号付きスロットを使い、同じ packet_id を再提出すると自分自身のファイルを上書きします(タイムアウト後の再試行でサブタスクが重複しません)。次のステージは、それらのスロットを数値順に読み戻します。標準ファイルが先で、続いて .01、.02、…の順です。パケット自身の from_role / to_role / タスク / ラウンドが置かれたファイルと食い違う、または検証に失敗した場合、そのパケットはスキップされ team_packet_skipped として監査されます。1つの不良ファイルのせいで、そのステージが残りのパケットを失うことはありません。

各ステージは <home>/role_turns.jsonl にも1行を追記します。ロール、ランタイム、モデル、effort、生成したパケット、観測の証拠グレード、終了の仕方です。パーミッション、ロック、ローテーションは tool_calls.jsonl と同じです。


エフェメラル spawn の受け入れキュー

Section titled “エフェメラル spawn の受け入れキュー”

ゴール分解や委任などの経路では、短命な子エージェント(ephemeral spawn)を立ち上げる必要がある場合があります。並行数上限(ephemeral_max_active、デフォルト 32)に達したとき、config.toml [dispatch] admission が上限を超えたリクエストの扱いを決めます。

値 動作
queue デフォルト。上限付き FIFO キュー。リクエストは決して消えてなくなることはなく、空きが出れば順番に実行されます。各キュー項目は TTL(queue_item_ttl_secs、デフォルト 600秒)を持ち、期限を過ぎると破棄され監査ログに1件記録されます。キュー自体にも深さの上限(queue_max_depth、デフォルト 64)があり、満杯の場合ははっきりと拒否されます(無制限のキューがそれ自体新たな暴走リスクになるのを避けるためです)。リクエストを発行した turn/session が終了すると、それに属するキュー項目もまとめて無効化されるため、すでに終わったプロセスから遅れて子エージェントが飛び出してくることはありません。
fail 旧来の挙動:上限を超えたら即座に拒否し、キューには入れません。

ephemeral_max_active 自体は「調整可能だがゼロにはできない」というルールに従います。0 に設定すると 1 にクランプされ警告が記録され、並行数上限が完全にオフになることは決してありません。

config.toml
[dispatch]
admission = "queue" # "queue"(デフォルト)または "fail"
queue_max_depth = 64 # キューの深さ上限、超えると拒否
queue_item_ttl_secs = 600 # キュー項目が生存できる秒数、期限切れは破棄され監査される
ephemeral_max_active = 32 # 並行数上限、0 は 1 にクランプされる

構造化された成果物検収(outcome schema、WP2.4)

Section titled “構造化された成果物検収(outcome schema、WP2.4)”

/goal … || outcome:<spec> を使うと、自由記述の検収基準に加えて機械的に検証可能な成果物契約をもう1層追加できます。AI従業員が完了を報告しタスクが review に入ると、この契約は決定的で LLM コストがゼロのチェックを検収ジャッジより前に実行します。

  • チェック不合格 → タスクは即座に revising に差し戻され、フィードバックには具体的な不足点(どのフィールドが欠けているか、どのファイルがないか)が示されます。ジャッジは一切呼び出しません。これはジャッジの偽陽性を防ぐ防御線です。構造的に明らかに不合格な成果物が過度に寛容なジャッジに通されることはなく、ジャッジ呼び出しも1回も無駄になりません。
  • チェック合格 → ここで初めてジャッジに到達し、ジャッジのプロンプトには「構造化された成果物検収はすでに決定的チェックに合格済み」という注記が付き、ジャッジは品質面に集中できます。

3種類の spec があります。

spec 意味
outcome:text デフォルト。構造化契約なし。outcome を付けなかった場合とまったく同じ挙動(永続化されず、ジャッジの前にチェックも走りません)。
outcome:json:<JSON Schema> JSON Schema のサブセット(object / array / string / number / integer / boolean、properties / required / items に対応)。AI従業員の最終返信中の ```json ブロックをチェックします(fenced ブロックが見つからない場合は返信全体を解析します)。フィールドの欠落や型の不一致はすべて具体的な不足点として列挙されます。
outcome:files:<glob,glob> AI従業員の作業ディレクトリ配下に、各 glob(*/? 対応)に一致する成果物ファイルが存在することを表明します。例:outcome:files:report.docx, out/*.pdf。

例FENCE9

境界と fail-closed の挙動:

  • パストラバーサルは拒否されます:files: の glob が絶対パス、ホームディレクトリ(~)、または上位ディレクトリを指す .. を含む場合、/goal 作成時点で一律拒否され(fail-closed、タスクは作成されません)、検証時にも再度チェックされます。作業ディレクトリの基準は <home>/agents/<agent>/ です。
  • 不正な spec は拒否されます:json: が有効な JSON オブジェクトでない、files: のリストが空、未知の型プレフィックスである場合、いずれも /goal は即座にエラーを返しタスクは作成されません(黙って text にフォールバックすることはありません)。
  • 永続化:spec は単一の outcome:<base64url> タグとしてタスク既存の tags フィールドに保存されます(base64url にはカンマが含まれないため、タグの区切りと衝突しません)。データベーススキーマの変更はありません。text は永続化されません。
  • planner との関係:outcome spec を設定すると planner_enabled によるサブタスク分解はスキップされます。構造化契約は単一の最終成果物を対象としており、分解されるはずだった各サブタスクには適用されません。
  • 最後の砦は依然としてジャッジです:タグが破損してデコードできない場合、決定的チェックはスキップされそのままジャッジに渡されます(ジャッジは通常通り関門として機能します)。観測性のギャップによってタスクが行き詰まることはありません。

グラウンディング事前チェック(v1.53)

Section titled “グラウンディング事前チェック(v1.53)”

AI従業員が完了を報告しタスクが検収に入ると、検収ジャッジを呼び出す前に LLM コストゼロのグラウンディング事前チェックが実行されます。最終返信を、このタスクで実際に実行されたツールの記録(監査ログ内のツール結果)と照合します。返信が何かを調べた・実行したと主張しているのに、実際のツール結果と重なる内容がまったく見つからない場合、ジャッジ呼び出しを消費せずそのまま修正に差し戻されます。なりすまし対策として2つの工夫があります。

  • 自己エコーは証拠にならない:tasks_complete のように AI従業員自身が書いた要約をそのまま返すタイプのツールは除外リストに載っており、自分の言葉で自分を証明することはできません。
  • 自分で投入した内容もカウントされない:AI従業員自身がツール呼び出しの引数に入れたテキストは証拠から差し引かれ、ツールが実際に返した内容だけがカウントされます。

config.toml [dispatch] grounding_precheck_enabled = false でオフにできます。照合できるツール記録がまったくない場合(純粋な対話型のタスクなど)、事前チェックはスキップ(Skip)され、不当にペナルティが課されることはありません。


タスク層のフォワードモデル(task forward model、v1.53。v1.54 以降デフォルトオン)

Section titled “タスク層のフォワードモデル(task forward model、v1.53。v1.54 以降デフォルトオン)”

有効にすると、goal loop は各ディスパッチの前に、過去の同種タスクの統計に基づいて「今回はおおよそどうなりそうか」(失敗しそうか、どのツールカテゴリを使いそうか)を予測します。実行後は予測と実際の観測を比較して遷移として記録し、システムは「この種のことをするとどうなりがちか」というタスク層の世界モデルを蓄積していきます。この処理はすべてのランタイムで動きますが、どこまで観測できるかは、そのランタイムがネイティブのツールイベントをコレクターに渡すかどうかで決まります。Claude(ディスパッチの stream-json 経路)、Codex、Gemini CLI(v1.67.0 で非推奨、v1.71.0 で削除)、Antigravity、OpenAI 互換のエージェントはネイティブのツールイベントを記録するため、観測は Full に達し得ます。Grok と 7 つの汎用 print-mode CLI(Qwen Code、Kimi Code、GitHub Copilot CLI、Kiro、Cursor、Mistral Vibe、OpenCode)はコレクターを持たないため、観測は McpOnly(tool_calls.jsonl のみから構築)、そのラウンドの記録がそのファイルにない場合は None になります。処理の内容は以下のとおりです。

  • 段階的なフォールバック予測:同種の統計があればそれを使い、なければ全体の周辺統計、それもなければ事前分布のデフォルト値を使います。コールドスタートでは LLM 呼び出しは一切発生しません。
  • 誠実な保真度の格付け:すべての観測には証拠の保真度(ネイティブツールイベント/監査ログのみ/証拠なし)がタグ付けされ、「見えなかった」ことが「起きなかった」ことと混同されることはありません。
  • <state> ブロック:タスク実行中、プロンプトには構造化された現在の状態ブロックが注入され、AI従業員は返信中の状態更新タグでこれを更新できます。(状態、行動)の訪問グラフと組み合わせ、同じ状態から同じ行動を2回以上繰り返すと早期に人的対応へエスカレーションします(振動検知)。
  • 予兆警告:予測がこのディスパッチはおそらく失敗すると示している場合、ディスパッチのプロンプトに警告文脈が付加されますが、直接ブロックはしません(予測は補助であり、関門ではありません)。
  • タスクルールの帰納:同種の遷移が繰り返し発生すると、決定的なテンプレートによりタスクルールとして帰納され、以後のプロンプトに注入されます(上限2件)。他の学習ルールと同じ helpful/harmful ライフサイクルを共有し、成績が悪ければ自動的に引退します。FENCE10

AI従業員が完了を報告しタスクが review に入った後、毎回フルの MAV ジャッジパネルを呼び出すわけではありません。まずはるかに安価な一次評価が実行されます。ツールなしの単発 LLM 呼び出しで、3択の JSON 判定のいずれかを出力します。

判定 意味 その後の動作
continue このラウンドではまだ完了していないが、方向性は正しい MAV をスキップし、評価器が示した次の一手をフィードバックとして即座に再ディスパッチします(イテレーション上限にカウントされます)
blocked 外部の障害(権限不足、データ不足、第三者待ちなど)で行き詰まっている ジャッジのラウンドを無理に完走したふりをせず、そのまま needs_human へ
candidate_complete 完了候補に見える ここで初めて完全な3方向の MAV ジャッジパネルによる慎重なチェックへ進みます

評価器がどんな状況(タイムアウト、解析失敗、呼び出し自体のエラー)に陥っても、常に MAV ジャッジへの直接実行に降格します。一次段階の障害によって自動的に合格や不合格になることは決してなく、安全性はこの層がない場合とまったく同じです。config.toml [dispatch] two_stage_judge(デフォルト true)で設定し、false にすると毎ラウンドフルパネルを実行する旧来の単段階の挙動に戻ります。

「この作業は本当に完了しているか」は、このプラットフォーム唯一のリリース権限のポイントです。デフォルトでは組み込みの3方向 MAV ジャッジパネルが判定しますが、config.toml [dispatch] judge で別の実装に差し替えることもできます。

値 誰が判定するか 使いどころ
mav(デフォルト) 一次評価器 → 3方向 MAV ジャッジパネル 一般的なケース
external あなた自身のプログラム(judge_command) 自前の CI、ルールエンジン、あるいは2つ目のモデルをジャッジとして組み込みたい場合
evaluator_only 一次評価器のみを実行し、candidate_complete は直接合格とする v1.69.0 で削除。 設定に残っている値は mav として扱われます(より厳しく、判定の費用が増えます)。mav に変更してください。two_stage_judge がすでに安価な評価器を先に走らせ、完了候補のときだけパネルの費用を払います
human_only 機械による判定はなく、すべての review タスクが needs_human へ v1.69.0 で削除。 設定に残っている値は機械による検収には戻りません。検収に回ったすべての作業が needs_human で止まり、完了にするか、設定を直してから再試行するまで進みません(再試行は以前の成果を消します)。mav とエージェント単位の [capabilities] autonomy_level / approval_required_tools を使ってください

4つの値はすべて引き続き解析されるため、非推奨モードで運用中の環境は設定どおりに動作します。プロセスごとに警告を1回記録し、ダッシュボード経由で書き込まれた場合は judge_mode_deprecated の監査イベントも残ります。ダッシュボードは mav と external だけを提示しますが、保存済みの非推奨値はラベル付きで表示し、黙って切り替えることはありません。deprecations.md を参照。

不正な値が静かに有効になることはありません。gateway が警告を出し mav(最も厳しいもの)にフォールバックします。この設定は判定のたびに再読み込みされ、two_stage_judge と同様、変更は再起動なしで即座に反映されます。

ジャッジを別のモデルで実行する

Section titled “ジャッジを別のモデルで実行する”

ワーカーと同じモデルファミリーのジャッジは、まさにそのファミリーが犯す間違いを許しがちです。ワーカーと同じ盲点を共有しているため、同じベンダーからのセカンドオピニオンは見た目ほどの価値がありません(arXiv:2607.13918)。2つの任意キーで、検収ジャッジと、それに伴う安価な一次評価器を、別のランタイムとモデルへ移せます。FENCE11

どちらも任意で、互いに独立しています。未設定の場合、ジャッジは通常のユーティリティ用モデル([runtime] utility_provider / utility_model)を使い続けます。これは既存のすべてのデプロイがすでに持っている挙動なので、これらを省略しても何も変わりません。

スコープ:グローバルのみ。 エージェント単位のバージョンはありません。すべての AI従業員の作業は、設定された同じジャッジによって判定されます。

設定が尊重できないときに何が起きるか。下の表の 4 つの場合すべて(最初の 3 つは何かを起動する前に検出、4 つ目はジャッジの実行中の失敗)で、ジャッジはデフォルトのユーティリティ用モデルにフォールバックして動き続けます。ルーティングの好みが判定を止めてはならないからです。

状況 挙動
judge_model が別のベンダーのモデルを指しているが judge_provider が未設定 拒否され、推測はされません。 ジャッジのランタイムが Claude に解決される状態で judge_model = "gemini-…" だけを設定するのは設定エラーであり、ランタイムを推測せよという指示ではありません。オーバーライドは何かが spawn される前に破棄され(コストはかかりません)、その破棄は judge_seam_degraded として security_audit.jsonl に書かれます。ランタイムも指定すれば動作します。
judge_provider がこのビルドの知らないランタイム id オーバーライドの全体が、有効な id を示す警告とともに破棄されます。タイプミスでジャッジが別のバックエンドへ黙って送られることはありません。
judge_provider の CLI やバックエンドがこのホストにインストールされていない spawn の前に検出され、オーバーライドは破棄され、同じ方法で監査されます。
ジャッジのランタイムが利用可能で、実際に使われ、その後実行中に失敗した(不正な引数、認証失敗、クラッシュ) ジャッジはデフォルトのユーティリティ用モデルで1回やり直され、失敗は judge_seam_degraded として、reason: "hinted_runtime_failed"、provider、モデル、根本のエラー、そして最終的に判定したフォールバックモデルとともに監査されます。重要なのは、失敗したジャッジが通常のランタイム間フェイルオーバーで救済されないことです。別のファミリーにルーティングされた呼び出しはファミリー間フェイルオーバーを無効にして実行されるため、ワーカー自身のファミリーに黙って回答されることはありません。同じファミリー内のフェイルオーバー(Claude のあるティアから別のティアへ)は通常どおり動作します。

設定の実際の効果を、想定ではなく目に見える形にする2つの監査イベントがあり、どちらも security_audit.jsonl に書かれます。

  • model_routed:オーバーライドが有効になり、ジャッジをワーカー自身のモデルから外しました。{slot: "judge", from: <worker model>, to: <judge model>, provider, reason: "dispatch.judge_model"} を伴います。
  • judge_same_family:ワーカーとジャッジが同じモデルファミリーだったため、相関を除いたセカンドオピニオンは実際には得られていません。これは警告であり、拒否ではありません。判定は通常どおり行われます。(AI従業員, ジャッジモデル)の組ごとに gateway の1回の実行につき1度だけ記録されるため、長い goal loop でもラウンドごとではなく1行になります。

judge 自体と同様に、どちらのキーも判定のたびに再読み込みされ、gateway の再起動は不要です。

必要とするジャッジのための構造化出力

Section titled “必要とするジャッジのための構造化出力”

Claude は「JSON オブジェクトだけで返信せよ」に従います。Codex は確実には従わず、チーム機能のライブラウンド8が、それが判定を失わせることを証明しました。judge_provider = "codex" のとき、一次評価器と MAV パネルの両方が散文で答え、両方のパーサーが fail-closed で拒否しました(「evaluator reply has no string decision field」)。パーサーは正しい動作をしました。ゴミを自動的に受理することは、ジャッジのパーサーが絶対にしてはならないことだからです。しかし構造的にパースできないジャッジは、機能しない seam です。

そこで各判定ステージは、自分のパーサーが要求する JSON スキーマを公開するようになり、返信の形式を強制できるランタイムはそれに従います。

ステージ スキーマ
一次評価器 {decision: "continue"|"candidate_complete"|"blocked", evidence, next_step}(blocker_key は宣言可能だが必須ではなく、パーサーは blocked 以外の判定でこれを拒否します)
MAV パネル アクティブな観点ごとに1つの {pass, reason} オブジェクト、すべて必須。観点の集合は、プロンプトやパーサーとまったく同じくゴールの難易度に従います

現時点でこれに対応しているランタイムは codex だけです。スキーマは一時ファイルに書かれ、codex exec --output-schema <FILE> として渡されます。ほかのすべてのランタイムは、そのリクエストを debug でログに残して無視します。スキーマは好みであり、前提条件ではありません。バックエンドが出力を制約できなくても何も失敗せず、スキーマファイルを用意できない場合も、呼び出しはそのフラグなしで実行され、実行されなくなることはありません。設定キーはありません。スキーマはパーサーの契約から導出されるため、パーサーの変更とスキーマの変更は一緒に動きます。

ジャッジの hint には、provider と model に加えて推論の effort も持たせられます。内部では UtilityModelHint は provider、model、effort という3つの独立した要素を持つため、呼び出し側はジャッジを別のベンダーへ移す、考える深さを変える、またはその両方を行えます。

Effort は hint の「空かどうか」の判定に意図的に含めていません。そこでの空とは「同じ (provider, model) の仕様に解決される」ことを意味し、モデルファミリーの検証が扱うのはまさにそれです。Effort が変えるのはモデルがどれだけ深く考えるかであり、どのモデルが答えるかではありません。

[dispatch] judge_effort キーはまだありません。設定ファイル側の対応は意図的な後続課題です。現時点では、ジャッジの effort が未設定の場合、回答するエージェント自身の agent.toml [model] effort にフォールバックします(ランタイムごとのフラグ対応とクランプ表は Effort を参照)。ほとんどの構成ではこれが望ましい挙動で、ジャッジは判定対象のエージェントと同じ強さで考えます。

プラットフォームはこのコマンドを実行し、stdin に次の JSON を流し込みます。FENCE13

コマンドは判定として次のような JSON オブジェクトを stdout に出力します。FENCE14

pass は true/false に加え、文字列の "pass"/"fail" も受け付けます。feedback は省略可能です。

事前に知っておくべきことが3つあります。

  1. 外部ジャッジがどんな状況に陥っても MAV ジャッジパネルにフォールバックします——タイムアウト、非ゼロの終了コード、stdout が有効な JSON でない、judge_command が未設定である場合を含みます。降格は常により厳しい方向へ働き、通しやすい方向に振れることはなく、降格のたびに security_audit.jsonl(judge_seam_degraded)に記録されます。
  2. その出力は信頼できないデータとして扱われます。 feedback は次のディスパッチラウンドのプロンプトに流れ込むため、まずインジェクションスキャンと切り詰めを経ます。スキャンでブロックされた場合、その判定全体は破棄され、代わりに MAV ジャッジパネルが判定します。フィードバックのテキストには出所が前置されるため、タスクのタイムライン上でどの行が外部ジャッジの発言かが分かります。
  3. judge_command はファイルを編集することでのみ変更でき、ダッシュボードからは変更できません。 これは実行可能ファイルを指定するものなので、system.update_config RPC は judge(4つの列挙値)のみを受け付け、judge_command や judge_timeout_secs は受け付けません。AI従業員自身にも ~/.duduclaw/config.toml への書き込み権限はありません。

duduclaw eval をジャッジとして使いたい場合は、judge_command を duduclaw eval をラップするスクリプトに向けるだけで済みます。別のモードは必要ありません。

サブプロセスは gateway の環境変数をすべて継承します。 judge_command はプラットフォームのプロセス spawn(tokio::process::Command)で直接実行されており、env_clear() もアローリストによるフィルタリングも行われていません。指定したジャッジプログラムは、呼び出された時点の gateway プロセスの環境変数一式を見ることができ、その中には gateway が LLM プロバイダーやチャンネル API を呼ぶために使う秘密情報も含まれます。これはデータが能動的にジャッジへ渡されているという意味ではありません(ジャッジの入力は前述の stdin JSON だけです)。ジャッジプログラム側にそれらの環境変数を読む「能力」がある、ということです(例えば悪意のある、あるいはバグのあるプログラムが std::env::vars() を読む場合)。これは脆弱性ではなく、現時点でのこの seam の設計上のトレードオフです。信頼でき、出所がはっきりしているプログラムだけを指定してください。サードパーティや未レビューの実行ファイルを指定してはいけません。より厳格な分離(ジャッジプロセスが gateway の秘密情報を本当に見られない状態)が必要な場合は、judge_command を、まず自分の環境変数をクリアしてからジャッジに実際に必要な少数の変数だけを再注入するラッパースクリプトとして包んでください。

ジャッジ応答の厳格契約(strict_reply_parsing)

Section titled “ジャッジ応答の厳格契約(strict_reply_parsing)”

3つの判定パーサー(MAV ジャッジパネル、一次評価器、外部ジャッジ)は、現在どれも「最初の { から最後の } まで」を切り出して JSON を取り出しています。そのため前後に文章が付いた応答も受け付けてしまい、壊れた応答の一部は黙って修復されます。厳格契約が受け付けるのは、応答全体から前後の空白と最大1層の ```json フェンスを取り除いた結果が、余分なフィールドのない、期待どおりの形の JSON 値ちょうど1つである場合だけです。パネルは有効な観点ごとに {pass, reason}、評価器は decision/evidence/next_step/省略可能な blocker_key、外部ジャッジは pass と省略可能な feedback です。FENCE15

モード 判定を決めるもの 厳格パース
off 現行の寛容なパース(バイト単位で従来どおり) 実行しない
shadow(デフォルト) 現行の寛容なパース 同じ応答に対して実行し、比較だけ行う
enforce 厳格パース 違反時はそのパーサー既存の失敗経路を通る:パネルは fail-closed の不合格、評価器と外部ジャッジは失敗扱いとなり MAV パネルが判定する

認識できない値は shadow として扱います。このキーは判定のたびに読み直されるため、変更に再起動は不要です。

比較のたびに Prometheus カウンター judge_parse_shadow_total{parser, outcome} が1増えます(parser は panel、pre_evaluator、external のいずれか、outcome は agree、strict_rejects、lenient_rejects、both_reject、disagree のいずれか)。結果が agree 以外の場合は、さらに security_audit.jsonl に judge_parse_shadow_mismatch を1件書き込みます。内容はパーサー名、比較結果、厳格パースの違反内容、秘密情報をマスクした応答の先頭 200 文字です。

デフォルトを shadow から enforce に変えるのは、運用者がこの数値を見て判断した場合だけです。条件はジャッジのラウンドが 50 回以上または観察 7 日以上、かつ strict_rejects が比較総数の 2% 未満であること。自動では切り替わりません。自分の環境で先に enforce にする場合は、使っているジャッジ runtime の strict_rejects を確認してください。JSON の後に一文を付け足す癖のあるモデルだと、enforce ではパネルが不合格を返し、評価器と外部ジャッジは MAV に降格します。

MAV ジャッジと一次評価器のプロンプトにはいくつかの規律が組み込まれています。これは実際のテストで捕捉された失敗パターン——ジャッジが自ら偽の却下理由を作り出し、正しい成果物を永久にブロックしてしまう——に対処するためのものです。

  • 反ラチェット:検収基準が変わっていないのに、ジャッジが毎ラウンド新しい粗探しをすることはできません。これはゴールを永遠に完了させない典型的な失敗パターンです。
  • 監査のみ、証拠の自作は禁止:ジャッジは AI従業員が提出した証拠とツール監査サマリーを照合することしかできず、自分で証拠を想像したり作り出したりすることはできません。「もっと良いやり方があると思う」を基準にすることもできません。
  • 契約範囲外への拡張禁止:検収基準に書かれていない事項を却下の理由にすることはできません。これは最もよくある偽の却下であり、正しく範囲内で行われた作業が行き詰まる最大の原因です。
  • エージェント自身の「完了しました」は証拠にならない:「もう完了した」「もう対応した」といった自己申告そのものは合格の根拠にはならず、ジャッジは検収基準と実際の成果物を項目ごとに照合しなければなりません。

これらの規律には設定スイッチはなく、すべてのゴールタスクに即座に適用されます。

パネルのプロンプトには、実行者ではなくシステムが提供する一行も含まれます。実行者の作業ディレクトリ、つまり <home>/agents/<agent_id> の絶対パス(<worker_working_directory>)で、結果中の相対パスはこれを基準にします。criteria_ledger = "off" を含むすべてのモードで入り、ディスパッチエンジンに home ディレクトリがない場合だけ省かれます。この一行が入る前は、正しい hello.txt が「作業ディレクトリではなくサブディレクトリにある」と判断され、2回却下されていました。

検収ジャッジがチェックする観点の数は、ゴールの難易度に応じてスケールし、不要なジャッジの LLM コストを節約します。

  • 簡単なゴール(短く、単一ステップで、多段階/リサーチ/比較/デプロイ/移行などのキーワードを含まない):ジャッジは正確性+安全性の2観点のみをチェックし、ディスパッチ上限には iteration_cap_simple(デフォルト 3)を使います。
  • 難しいゴール:正確性+完全性+安全性の完全な3方向 MAV パネルを使い、ディスパッチ上限には iteration_cap(デフォルト 5)を使います。

安全性はどの深度でも維持されます(fail-closed の設計思想)。深度を下げても削られるのは完全性のきめ細かさだけで、安全性チェックが削られることは決してありません。難易度はローカルの LLM コストゼロなヒューリスティック(長さ+CJK対応のトークン推定+キーワード)で判定され、ジャッジの深度とディスパッチ上限は同じ判定を使うため、両者は常に一致します。


停滞検知:ギャップ指紋の照合

Section titled “停滞検知:ギャップ指紋の照合”

「2ラウンド連続で同じ場所に行き詰まっている」の判定は、もう却下フィードバックが一字一句同じかどうかだけを見るわけではありません。ジャッジは毎回まったく同じ言い回しをするとは限りません。「goal_loop.rs:120 のエラー処理が欠けている」と「goal_loop.rs の120行目でバリデーションを忘れている」は同じギャップを指していますが、文字列比較ではこれらを2つの別の事柄と判定してしまい、本当に行き詰まっているシグナルが言い回しの違いに埋もれてしまいます。

現在は却下フィードバックから path:line の参照とバッククォートで囲まれたキーワード(関数名、変数名、エラーコード)を抽出し、正規化した上で(一時/scratch パスは同じプレースホルダーに統一、大文字小文字を無視、重複排除してソート)指紋を組み立てます。同じギャップを別の言い方で表現しても同じ指紋になります。参照もキーワードもまったく抽出できない場合(純粋に説明的なフィードバックなど)は、元の一字一句比較にフォールバックし、挙動の互換性を保ちます。2ラウンド連続で同じ指紋になって初めて後述の needs_human がトリガーされ、閾値そのものは変わっていません。

早期切り上げ検知(bail detection)

Section titled “早期切り上げ検知(bail detection)”

自律ループの中で、AI従業員が「終わったように聞こえるが、実際にはジャッジによって検証されていない」言葉でそのラウンドを終えることがあります。「とりあえずここまでにしておきます」「後ほど結果をご確認ください」「レビュー提出済みです」「VERDICT: PASS」(ジャッジではなく自分で署名したもの)といった具合です。これらの言葉自体は作業に誤りがあることを意味しませんが、記録しておく価値のあるプロセス上のシグナルであり、次のラウンドでも少し注意を払う価値があります。

9個の zh+en 正規表現は、そのラウンドのエージェントの返信の最後の空でないテキストブロックだけをチェックします。いずれかに一致すると、

  • Activity Feed イベントを1件記録します(goal_loop.premature_stop_suspected)
  • Prometheus カウンター goal_loop_bail_pattern_total{pattern="<一致したパターン名>"} を加算します
  • 次のラウンドの <state> ブロック、一次評価器の入力、MAV ジャッジの入力にヒントを持ち込みます。中立的な注記(「早期に切り上げた疑いがあります。タスクが本当に完了しているか確認してください」)であり、評価器やジャッジの判断を先取りすることはありません

この検知レイヤー自体は、タスクを却下したり、ブロックしたり、人的対応へエスカレーションしたりすることは一切ありません。純粋にシグナルとリマインダーであり、実際に合格とするかどうかは評価器・ジャッジが証拠をどう読むか次第です。

再起動時の挙動(resume_on_restart)

Section titled “再起動時の挙動(resume_on_restart)”

gateway の再起動やクラッシュからの復旧後、進行中のゴールタスクはデフォルトで needs_human にエスカレーションされます(resume_on_restart = "pause"、デフォルト値)。gateway は起動のたびに、終端状態でないすべての goal_mode タスク(todo/pending/revising/in_progress/review/blocked)を needs_human(理由:gateway_restart)に移し、既存のチャンネル通知を経由してあなたが「再試行」を押すまで待ちます。予期しないプロセス再起動やデプロイが、誰にも安全性を再確認されていないゴールをこっそり実行し続けることはありません。

より緩い元々の挙動を維持したい場合は、[goal_loop] resume_on_restart を "auto" に設定してください。進行中のゴールタスクは、プロセスが一度も中断されなかったかのようにそのまま続行されます(これはこの設定が存在する前の唯一の挙動でした)。

どちらの方向であっても、このチェックは gateway 起動時に一度だけ実行され、設定のホットリロード(system.update_config)ではトリガーされません。変更は次に実際に gateway が再起動されたときにのみ反映されます。

ダッシュボードでの切り替え:「設定 → 自動化」の「gateway 再起動時の進行中ゴールタスク」ドロップダウンから直接切り替えられ、config.toml を手動で編集する必要はありません。system.update_config は "auto"/"pause" の2値のみを受け付け、それ以外は一律拒否されます。


タスクが「人的対応が必要」にエスカレーションすると(ディスパッチ上限到達/経過時間の上限超過/同じギャップ指紋で2ラウンド連続却下/リトライ予算が尽きても検収ジャッジが不合格のまま/上流の依存サブタスクが行き詰まりエスカレーションを継承した/resume_on_restart = "pause" の状態で gateway が再起動した)、4つのボタンが AI従業員のコントロールチャンネルに送信されます。

一時停止理由の分類(pause_reason)

Section titled “一時停止理由の分類(pause_reason)”

「人的対応が必要」はもう単一のバケツではありません。既存の自由記述の judge_feedback(ジャッジまたは評価器の完全なフィードバックで、複数の文にまたがることもあります)に加え、人的対応へエスカレーションするたびに6択の閉じた分類が同時に刻印されます。これは「どんな種類の行き詰まりか」を一目で判別できるようにするためのもので、judge_feedback は依然として文単位の詳細を担います。

分類トークン UI表示テキスト
no_progress 行き詰まり・進展なし
budget_exhausted 回数または時間の上限に到達
blocked_needs_decision あなたの判断待ち
infra システムの問題
restart 再起動により一時停止
unknown 人による確認が必要

この分類はトリガーが発生した現場で静的に刻印され(各エスカレーション経路がそれぞれ自分のカテゴリをタグ付けします)、judge_feedback の LLM による文章から逆算されることは決してありません。モデル自身の言い回しは信頼できず、ルーティングの根拠にすべきではないからです。分類なし、認識できない古い値、あるいはこのフィールドが導入される前からあるタスクは、すべて unknown(「人による確認が必要」)として扱われます。種類の分からない行き詰まりは、実は当て推量に過ぎない具体的な分類に誤って割り当てられるより、あいまいなものとしてあなたに提示される方がましだからです。

表示場所:/goals ボードのカードとタスク詳細ページの分類チップ、チャンネルの needs_human 承認メッセージ内の「種類」の1行(Observer の完全自動モードの通知のみのケースにも表示されます)。タスクが人によって決定される(再試行/完了とする/諦める)と、分類フィールドはクリアされ、次のエスカレーションには持ち越されません。

ボタン 動作
再試行 タスクは再試行待ち(pending)に戻り、ドライバーが次のラウンドで再びディスパッチします。
完了にする タスクを直接完了(done)にマークします。
諦める タスクをキャンセル(cancelled)します。
自分で対応 あなたが引き取り、タスクはあなたによって認領された(claimed_by)とマークされます。状態は needs_human のままなので、ドライバーはもともと自動的に再ディスパッチしません(候補クエリが見るのは todo/pending/revising だけです)。これが現時点のこの機能の範囲です。自動リトライの停止+マーク付け+カードの折りたたみです。会話のコントロールを完全にあなたへ渡す(以後のメッセージが AI の判断に届かなくなる)のは次段階の機能で、まだ実装されていません。

1つのメッセージで許容される主要アクションは最大3つで、4つのボタンはこれを超えるため、「諦める」と「自分で対応」は、二次階層をサポートするチャンネルでは二次階層に折りたたまれます。Telegram では2段目のボタン、Discord でも2段目のボタン、Slack ではネイティブの overflow メニューです。LINE には対応する二次メニューの仕組みがないため、これら2つのアクションは LINE のクイックリプライボタンには表示されず、代わりにメッセージ本文中にダッシュボードへのリンク付きで説明されます。

ボタンの判定は冪等で fail-closed です。再試行/完了にする/諦めるは、タスクを needs_human から遷移させることしかできず、2回押した場合や状態がすでに変わっている場合は no-op です。「自分で対応」は比較すべき終端状態を持たないため、もう一度押しても(たとえ別の権限を持つ人が押しても)認領を再スタンプするだけで、エラーにはなりません。collaborator/consultant のキックオフ承認も同様で、期限までに判断されなければ拒否扱いになります(fail-closed)。

v1.53 以降、人的対応へのエスカレーションにはシミュレーションプレビュー(simulate-before-act)が添付されます。タスクを続行させることを選んだ場合、次の3ステップでおおよそ何が起きるかを示します。シミュレーションには15秒の上限があり、タイムアウトした場合はシミュレーションなしで承認リクエストが通常通り送信されます(それによってブロックされることはありません)。シミュレーションが参照するナレッジは読み取り専用の namespace に限定され、シミュレーションの記述自体があるアクションが可逆かどうかを決定することはできません(自己証明の禁止)。ダッシュボードの承認カードはこのプレビューを描画します。

シミュレーションプレビューが扱うのは「続行を許可したら何が起きそうか」ですが、「変更」タブが扱うのはすでに何が起きたかです。ダッシュボードの受信箱の判断カードとタスク詳細ページの両方に、このタスクが各ラウンドで実際に触れたファイルを一覧表示する「変更」タブがあります。

項目 内容
パス 作成/変更/削除されたファイルのパス。command タイプの場合は shell コマンドそのものを表示し、どのファイルに触れたかを勝手に推測することはありません。ワンクリックでコピーできます。
操作 新規作成/上書き、編集、削除、コマンドの4種類のいずれかです。
ステータス 失敗またはブロックされた呼び出しも一覧に含まれ「失敗」とマークされます。これはまさに、リアルタイムのツール状態クエリでは見えない半分です。
要約の抜粋 書き込まれた内容やコマンドの説明の抜粋で、監査ログのマスキング済み結果をそのまま再利用します(表示のためだけに元ファイルを読み直すことはありません)。
ソース 実行時のネイティブツールイベント(Write / Edit / NotebookEdit / Bash…)か、MCP の監査記録(wiki_write など)のいずれかです。

証拠は既存の2つの経路から得られます。実行時のネイティブツールイベントは各ディスパッチラウンドの後にファイル変更記録として落とし込まれ(タスク ID で帰属付けされます)、MCP の監査記録はジャッジの <tool_activity> がすでに使っているのと同じ「認領から検収までの時間窓+実行者」の帰属付けを再利用します。記録がなければ、それは記録がないということです。何もない場合、タブには「このタスクにはファイル変更の記録が残っていません」と表示され、作り話で埋め合わせることはありません。

現時点で表示されるのは「どのファイルに触れたか、操作は何か」であり、まだ行単位の before/after diff ではありません。本当の diff には書き込み前のスナップショットが必要で、それは今後の課題です。


「考えてみる」プランファーストモード(plan-first、I-1c)

Section titled “「考えてみる」プランファーストモード(plan-first、I-1c)”

ダッシュボードの割り当てパネルには「聞いてみる」「任せる」に加えて、第3のモード「考えてみる」があります。AI従業員がまず実行計画を作成してあなたに見せ、あなたが承認して初めて本当に作業を始めます。

「考えてみる」を選んで送信しても、フロントエンドは同じく tasks.goal_create を呼び出しますが、plan_first: true が追加されます。バックエンドはタスク作成のその場で(ディスパッチループの1ラウンドとしてではなく、同期的に)ユーティリティ用 LLM を呼び出し、ゴールの説明と検収基準から3〜8項目のプレーンテキストの実行計画を生成します(JSON ではなく、人が読むための文章です)。タスクは直接 needs_human として生まれ、既存の blocked_needs_decision(「あなたの判断待ち」)分類を再利用します。新しい分類は追加されません。承認前はディスパッチループの候補クエリに一切入らないため、1ラウンドすら実行されません。

計画のテキストは2箇所に書き込まれます。

  • judge_feedback(既存のフィールド):「判断待ち」カード、タスク詳細ページ、チャンネルの承認メッセージが、表示ロジックを一切変更せずに計画内容を表示できるようにするためです。
  • plan_pending(新規フィールド、I-1c専用):judge_feedback とは別に保存されます。これは、承認アクション自体(どの needs_human タスクにも共通の「再試行」ボタン)があなたの承認メモで judge_feedback を上書きしてしまうためです。もし計画も同じフィールドに存在していたら、承認した瞬間に自分自身の承認アクションによって上書きされてしまい、最初のディスパッチラウンドに永遠に届かなくなってしまいます。

承認は既存の「再試行」ボタンで行われ、新しいボタンの種類は追加されません。承認されるとタスクは pending に戻り、ドライバーの次の tick でディスパッチする際、plan_pending の内容が <execution_plan> ブロックに包まれてそのラウンドの作業プロンプトに注入され、AI従業員は計画に沿って実行を開始します。注入直後に plan_pending は即座にクリアされるため、計画が貼り付けられるのは一度きりで、以降のラウンドでプロンプトに繰り返し登場することはありません。

計画はガイダンスであり、検収を免除する保証ではありません。実行が完了しても、他のゴールタスクとまったく同じ二段階検収判定/MAV ジャッジパネルを通過する必要があり、計画に書かれたステップがジャッジによって不十分または誤りと判断されれば、同じように修正へ差し戻されます。

計画を作成するユーティリティ用 LLM の呼び出し自体が失敗することもあります(タイムアウト、通信エラー、あるいは完全に空の返信)。この場合もタスクは fail-closed のまま needs_human にとどまりますが、分類は blocked_needs_decision ではなく infra(システムの問題)に変わり、plan_pending は付与されません。このようなタスクを承認しても、常に「注入する計画がない」最初のラウンドが解放されるだけで、計画が忽然と消えたり、黙ってスキップされたりすることはありません。


タスク詳細ページには、進行中の goal タスク向けの操作が 2 つあります。詳しいルールは継続タスク、実行中の指示、タスクの停止を参照してください。

  • 次のラウンドへの指示([goal_loop] steering_enabled = true が必要。既定はオフ):最大 4000 文字の補足で、次のラウンドが送り出されるときに AI従業員へ渡されます。進行中のラウンドは中断しません。そのラウンドが実際に送り出されたときだけ渡したと数え(「第 N ラウンドに組み込みました」)、止められたり送り出しに失敗したりしたラウンドの指示は次のラウンド待ちに戻ります。指示は固定された検収基準に触れず、ジャッジからも見えません。指示を含むラウンドは AI従業員 1 人で実行し、チームラウンドにはなりません。
  • タスクを停止:ダッシュボードの本人確認済みの身元で、タスクとすべてのサブタスクをすぐに取り消します。すでに走っているラウンドは最後まで進むため(cancel_pending)、何も動いていないと確認できたときだけ stopped になり、確認できないもの(リースが切れたのに完了記録のない取得、結果不明の外部操作、スキャン上限を超えるツリー)があれば stopped_uncertain になります。確認ダイアログは開いた時点のバージョンを覚えており、確認前にタスクが変わっていればそれを表示して、もう一度の確認を待ちます。停止したタスクは再試行も続行もできません。やり直すには新しいタスクを作成してください。

ハードな境界を握っているのはモデルではなくドライバーであり、行き詰まったゴールが無限にループすることはあり得ません。完了シグナルとして認められるのは検収ジャッジの承認だけです(AI自身の「完了しました」という自己申告は決して信頼されません)。ディスパッチ上限、経過時間上限、並行数上限、進捗の振動検知、フィードバック経路のサーキットブレーカーはそれぞれ独立に働き、いずれか1つでも踏めば人的対応へのエスカレーション、またはブレーカーのトリップが発生します。