書いても効かないフィールドが、ptygrid.yml に混ざっていた
自分の書いた記事に、嘘が混じっていた。この開発日誌の第3部に「retry を足した」と書いた。使い切ってもなお駄目なら人間に投げる、とまで説明している。ところが後日、実機のソースを開いて確かめたら、retry というフィールドはどこにも無かったのだ。config.rs の WorkflowStep 構造体を上から下まで見ても、そんな行は最初から存在しない。実装したつもりで、実装していなかった。
ここまで散々「エージェントの報告は鵜呑みにしない」と書いてきた自分が、自分の記憶を鵜呑みにしていた。前段のサブエージェントが「5.0.2 の Reliability を同梱した」と報告してきて、v0.5.6 の git タグ注釈にもそう書いてあった。でも該当コミットは git log に無い。おそらく、実ソースを含まないクラウド側の隔離環境で構文チェックだけ通して「完了」と返してきたのを、そのまま信じてタグに書いてしまった。証拠を見ずに信じた報いが、公開済みの記事に化石として残っている。
この一件で、ptygrid.yml の workflows: というブロックを、改めて棚卸しすることになった。そこで分かったのは、同じ YAML の中に「書けば効く行」と「書いても何も起きない行」が、見た目の区別なく同居しているという事実だった。今日はその棚卸しの話を書く。有料で読んでくれている人には、後半でそのまま貼って使える完成形の workflow も置いておく。
未知のフィールドを、黙って無視する親切
まず仕組みの話をひとつだけ。ptygrid.yml の workflows: は、知らないフィールドを見つけても、エラーを出さずに黙って無視する。forward compat、つまり「将来のバージョンで書かれた設定を、今のバージョンでも読み飛ばして起動できる」ための設計だ。これ自体はいい判断だと思う。
問題は、その親切が裏返しになる瞬間だった。retry: と書いても、それが「未来のフィールド」なのか「ただのタイポ」なのか「存在しないフィールド」なのか、config は一切教えてくれない。綴りを間違えても、実装されていないフィールドを書いても、赤い文字は出ない。構文としては正しく通ってしまう。だから retry を書いた自分は、それが機能していると信じ込めた。何も言われなかったのだから。
閉じた列挙、たとえば joinOn: の値を all/any/reply 以外に書けば、そこは即エラーになる。でもフィールド名そのもののタイポは検出されない。fanOut を fanOutt と書いても、静かに無視されて終わる。「エラーが出ない」は「正しく効いている」の証拠にならない。ここが、この設定ファイルを書くうえでいちばん最初に叩き込んでおくべきことだった。
timeoutMs: 600000 は、ただの飾りだった
retry の次に肝を冷やしたのが timeoutMs だ。ある step が延々と終わらなくて、画面の前で待っていた。「10分でタイムアウトするように書いておいたはずだが」と思って kickoff を見返すと、たしかに timeoutMs: 600000 と書いてある。10分。とっくに過ぎている。なのに step は RUNNING のまま、静かに回り続けていた。
orchestrator.rs を開いて理由が分かった。timeoutMs はパースされる。設定として読み込まれ、構造体のフィールドにちゃんと値が入る。ただ、その値をどこでも参照していない。超過を監視するロジックが、存在しないのだ。コード中のコメントは今も「deferred to 5.0.4」のまま残っていた。値だけ受け取って、何にも使っていない。書いた本人が「安全装置を仕込んだ」と思い込むための、飾りのフィールドになっていた。
これは怖い。retry が無いのは、無いと分かればまだいい。timeoutMs は「有るように見えて効かない」から、詰まった step を放置する運用を平気で組んでしまう。今は詰まった step を止めたいとき、人間か integrator が手でペインを閉じるしかない。timeoutMs を保険と数えてはいけない、と自分の運用メモに太字で書いた。
fanOut: 3 と書いた行が、3本になるとは限らなかった
第1部で書いた fan-out のバグも、突き詰めれば「ptygrid.yml の書き方の話」だった。fanOut: 3 と宣言したのに、立ち上がるペインが1本に潰れる。当時は既存機能のせいだと突き止めた。「同名の生きているセッションがあれば再利用する」という冪等スキップが、3本立てたい fan-out の意図と正面からぶつかっていたのだ。
ここで改めて思ったのは、YAML に書いた数字は宣言でしかない、ということだった。fanOut: 3 は「3本立てたい」という意思表示であって、「3本立つ」保証ではない。実際に何本立つかは、その裏にある「同名セッションは再利用する」という別の機能との綱引きで決まっていた。設定ファイルの一行だけを読んでも、実行時の挙動は分からない。同じフィールドが、隠れたルール次第で違う意味になる。
直したあとは、copies が2以上のときは常に新規 spawn するようにした。同名の生きたセッションがあっても、fan-out のときだけは再利用しない。だから今は fanOut: 3 と書けば、ちゃんと3本立つ。ただ、この修正で腑に落ちたのは、fanOut という一語の意味が「宣言」から「実際の挙動」へ橋渡しされるには、コード側の裏付けが要るという当たり前の事実だった。書ける、と、効く、は別物だ。
ここまでで3つ、書けるのに効かない/効くのに裏がある地雷を見てきた。この先には、もっと痛い事故と、そのまま貼って使える完成形のテンプレートを置いておく。
【★ここから先を「有料ライン」に設定(note編集画面で本文中にカーソルを置き、「¥ ここから先を有料エリアに設定」を選択)★】
【単体販売・メンバーシップ添付の両方に使う場合は、単体記事の価格設定 と メンバーシップの対象プラン指定 を両方行う】
ここから先は
サーバー代とコーヒー代になります☕ 役に立ったら応援よろしくお願いします!
