v5.4.4:エージェントスモークテストの信頼性——出力コントラクトクライアントとタイムアウト自動エスカレーション¶
クイックアンサー: v5.4.4 は「command 無効 / workflow スタック」という障害モードを修正します。エージェントは自分とは無関係な理由で恒久的に無効化されていました。Codex のようなクライアントはすべての応答を JSON 出力コントラクトで包むため(プローブは自分の ACK を認識できない)、ハードコードされた 30 秒のタイムアウトが一度の遅いコールドスタートを恒久的なブロックに変えていました。プローブは出力コントラクトを明示的に上書きし、JSON ラップされた応答を許容し、設定可能なタイムアウト(デフォルト 60 秒、
AIOS_AGENT_SMOKE_TIMEOUT_MSまたは--timeout-ms)を使い、エージェントをブロックする前に 2x/4x で自動エスカレーションして再試行します。
障害モード:静かに死ぬワークフロー¶
ワークフローが突然 overallstatus: "blocked" を報告し、すべてのコマンドが「無効」と判定されます。根本原因の連鎖は見た目より長い:
- live smoke プローブはゲートキーパーです——エージェントは smoke エビデンスが記録されるまでライブオーケストレーションに参加できません。
- プローブが失敗するとエビデンスは書かれず、エージェントはワークフロー無効のままです。
- 無効なエージェント →
strict.blocked→ すべての Command が無効として拒否されます。
2 つの独立したバグが、正常なエージェントでもプローブを失敗させていました:
バグ 1——出力コントラクトの罠。 一部のクライアント(最も一般的なのは Codex)は、「ACK だけ返して」というプローブの指示に対してもすべての応答を JSON handoff コントラクトで包みます。プローブはプレーンな ACK マーカーを探しますが、JSON のラッパー内では見つからず、失敗と報告します。さらに悪いことに、クライアントが自社のコントラクトに厳密に従うほどプローブは確実に失敗します——プロトコルのデッドロックです。
バグ 2——一度の遅い応答 = 恒久的なブロック。 プローブはハードコードされた 30 秒のタイムアウトで、再試行がありませんでした。遅いコールドスタートやモデル待ちがプローブを 30 秒超に押し込み、エージェントはブロックされ、何も再試行しません——復旧には --timeout-ms を知っている人間が手動で smoke を再実行する必要がありました。
v5.4.4 の変更点¶
出力コントラクトクライアントで動作する smoke¶
- プローブプロンプトは「Do NOT return a JSON handoff object — reply with the ACK marker only」と明示的に宣言し、プローブに限りクライアントの出力コントラクトを上書きします。
- ACK 検出は JSON ラップされた応答を許容します。プレーンなマーカーが見つからない場合、応答を JSON としてパースし、ラッパー内部を検索します。
- post-receive 圧縮証明は
minRawBytes(2048 バイト)以上の出力にのみ要求されます。短い出力は設計上インライン化されます——これは正当な境界挙動であり、smoke の失敗ではありません。 - 空の圧縮 refs でエビデンス記録がクラッシュしなくなりました(
refs[0]のオプショナルチェーン化)。
一発死ではなく、エスカレーションするタイムアウト¶
- ハードコードされた 30 秒は
AIOS_AGENT_SMOKE_TIMEOUT_MS(環境変数)とagents smoke --timeout-ms <ms>(CLI)に置き換わり、デフォルトは 60 秒に引き上げられました。 - 一時的な遅延応答では、プローブは 60s → 120s → 240s とタイムアウトを自動エスカレーションして再試行します。3 回すべてがタイムアウトした場合のみエージェントはブロックされます。
- 最終的な blocker メッセージには正確な復旧コマンドが含まれており、ブロック解除の方法を推測する必要はありません。
なぜエージェント自身にタイムアウトを決めさせないのか?¶
自然な疑問です。エージェントに「もっと考えさせて」自分で時間を延ばさせるのはどうか? それはできませんし、すべきでもありません。タイムアウトはホスト側のプロセスパラメータであり、エージェントプロセスはそれを見ることができません。また、テストされる側に自分のテストを採点させることは、自己認証的な合格を生むだけです。予算はクライアントのコールドスタート特性を知っている運用者に属し、ホスト側が自動エスカレーションするのが正しい形です。
実際のタスク実行は完全に別の予算です:サブエージェントジョブは SUBAGENT_TIMEOUT_MS(デフォルト 10 分)を使用します。30 秒/60 秒のプローブタイムアウトは実際の作業を制約したことはありません——接続性ハンドシェイクを守るだけです。
あなたがすべきこと¶
- 既存インストール:
aios update。 - 以前「command 無効 / workflow スタック」に遭遇した場合:
aios agents smoke --live --client <名前> --timeout-ms <ms>を再実行して v2 smoke エビデンスを再生成し、aios doctor --agentsでカタログがグリーンであることを確認してください。 - クライアントのコールドスタートが特に遅い場合:毎回フラグを渡す代わりに、環境に
AIOS_AGENT_SMOKE_TIMEOUT_MSを設定してください。
FAQ¶
この変更で本当に壊れたエージェントが見逃されるのでは?¶
いいえ。長い出力で圧縮 ref がない場合は引き続き fail-closed です。タイムアウト以外のエラー(コマンド欠落、非ゼロ終了、managed-invocation 証明の欠落)は一切再試行されず、即座にブロックされます。2x/4x エスカレーションを受けるのはタイムアウトクラスの失敗だけであり、それも合計 3 回までです。
60 秒 × 3 回はプローブとして長すぎないか?¶
エスカレーションは実際のタイムアウト後にのみ発生します。正常なクライアントは数秒で応答します——最初の試行で成功し、再試行は発生しません。240 秒の最悪ケースは、60〜120 秒で本当に応答できないクライアントだけが支払います。
移行は必要ですか?¶
不要です。これは動作の修正であり、エビデンスファイルのスキーマは変わりません。エージェントが現在ブロックされている場合は、live smoke を再実行して v2 エビデンスを再生成するだけです。
ここで覚えておくべき教訓があります:一度の遅い応答を失敗として罰するゲートキーパーは、ヘルスチェックではなく時計です。エスカレーションし、再試行し、それから初めて判断する。