ゴールが決まるまで笛は鳴らない ~ Kiro CLI の goal コマンドで「完了」を勝ち取る
2026-07-02 | Author : 稲田 大陸 (いなりく)
はじめに
こんにちは ! ソリューションアーキテクトの いなりく です ! ワールドカップの季節になると、毎回のように議論になるシーンがあります。「今のは入ってた ? 入ってなかった ?」。選手がどれだけ自信満々に両手を上げても、ボールがゴールラインを完全に割っていなければ得点にはなりません。最終的に得点を認めるのは、選手の主張ではなくゴールラインテクノロジーや VAR が示す客観的な証拠です。
実は、AI コーディングエージェントにも全く同じ問題があります。エージェントに「この機能を完成させて」と頼むと、いくつかのテストが通った時点で「完了しました ! 」と高らかに宣言する。でも実際にはエッジケースが抜けていたり、ビルドが通っていなかったりする。いわば自己申告のゴールです。
前回の記事「Kiro にハーネスを付ける ~ 制御された全力疾走のすすめ」では、この「自己評価の甘さ」「早期完了宣言」という構造的な問題に対して、Generator と Evaluator を分離するハーネスを 自分で組み立てる アプローチを紹介しました。
今回は、その思想に通じる標準コマンドとして Kiro CLI 2.7.0 で追加された /goal コマンドを取り上げます。 /goal は、エージェントに「ゴール」を与え、そのゴールが検証されるまで笛を鳴らさない (=ループを止めない) 仕組みです。ちょうどワールドカップの季節。goal という名前にあやかって、その仕組みをサッカーになぞらえて読み解いていきます。(なお、私はサッカー経験はありませんので、サッカーのツッコミはお控えください笑)
builders.flash メールメンバー登録
builders.flash メールメンバー登録で、毎月の最新アップデート情報とともに、AWS を無料でお試しいただけるクレジットコードを受け取ることができます。
/goal とは何か ― 「キックオフ」から「試合終了」まで
/goal は、ユーザーが達成したい結果 (ゴール) を宣言し、エージェントがそれを満たすまで自律的に反復するコマンドです。通常のチャットが「1 回シュートを打って終わり」だとすれば、/goal は「ゴールが決まるまで何度でも攻め続ける試合」です。 Kiro CLI 2.7.0 (2026 年 6 月 12 日リリース) で追加されました (公式ドキュメント)。
# デフォルト : 最大 5 イテレーション/goal refactor the auth module to use JWT tokens and ensure all tests pass
# 複雑なタスクは --max で反復回数を増やせる
/goal --max 10 migrate the entire test suite from Jest to Vitest
# アクティブなゴールをキャンセル
/goal clear
コマンドをサッカーに例えると・・・
|
要素
|
サッカーで言うと
|
説明
|
|---|---|---|
|
<達成したいこと>
|
狙うゴール |
何を達成してほしいか |
|
--max <N>
|
試合時間 / 反復回数 |
何回まで攻め直すか (デフォルト 5) |
|
clear
|
試合の中断 |
アクティブなゴールをキャンセル |
ゴールをセット
ゴールをセットすると、画面上部にキックオフのアナウンスが表示されます。
Goal: "hello.py を作成して Hello from Kiro と出力されることを確認して" · 5 iterations max
経過をリアルタイム表示
そしてゴールがアクティブな間、画面下部には試合の経過がリアルタイムで表示され続けます。
Goal Active: ... · Iteration 1/5 · Ctrl+X to pause
なぜ「ループ」が必要なのか ― 1 本のシュートでは試合は終わらない
普通のチャットでエージェントに作業を頼むと、エージェントは「1 ターン」で答えを返して終わります。これはペナルティキック 1 本のようなもので、外したらそこで終了です。
しかし現実の開発は、1 回のシュートで終わるほど甘くありません。 前回のハーネス記事 でも触れた通り、ナイーブにエージェントを動かすと典型的な失敗が起きます。
- 早期完了宣言 : いくつか動いた時点で「ジョブ完了」と宣言し、残りを放置する
- 自己評価の甘さ : 自分の成果物に対して「よくできました」と甘く採点する
/goal のループは、この 2 つに正面から向き合います。ゴールをセットしたエージェントは、次のような反復ループに入ります。
- 目的を達成するためのステップを計画する
- 変更を実装する
- 結果をゴールの受入基準 (acceptance criteria) に照らして検証する
- 検証に失敗したら、修正して再挑戦する
- すべての基準を満たしたらゴールを完了とマークする
ポイントは、エージェントが勝手に「もういいかな」と引き上げられないことです。普通のプロンプトが「実装して終わり」だとすれば、/goal は「検証して、ダメならやり直す」を回数の許す限り繰り返します。笛を吹く条件は「検証に通ること」であって、「とりあえず手が動いたこと」ではないのです。
完了の判定 ― ゴールラインテクノロジーは自己申告を認めない
/goal の最も本質的な部分は、「検証してからでないと完了できない」という点です。ここがまさに「ゴールラインテクノロジー」に相当します。通常のプロンプトとの違いは、こう表現されています。
Unlike a regular prompt, the agent cycles through implementation and self-verification, only marking the task complete when acceptance criteria are met.
実際に手元で hello.py を作るシンプルなゴールを走らせてみると、完了時の出力に「証拠 (Evidence)」にあたる情報が現れます。ファイルを作成したこと、実行した結果 (標準出力に Hello from Kiro、終了コード 0) が並ぶのです。通常のプロンプトなら「作成しました」で終わりがちなところを、 /goal は実行して確認するところまでやり切ってから完了を宣言します。
❌ 「ページネーションを実装しました。動くはずです」(自己申告のゴール)
✅ 「GET /users?page=2 が 200 と 10 件を返すことをテストで確認した」(ゴールラインテクノロジーの記録)
前回のハーネス記事 で「verifier は基準が明示されていないと rubber-stamp (機械的に承認) する」と書きました。/goal はこの弱点に対して、「検証ステップをエージェント自身のループに組み込む」という形で答えを出しています。
どこを狙うかを明示する ― ゴールマウスの広さは自分で決める
ここで重要なのが、「受入基準は、あなたが宣言した文章から自動で導かれる」という点です。
The agent derives acceptance criteria from your goal statement. Be explicit about what "done" looks like — "all tests pass" or "no TypeScript errors" gives the agent a concrete verification target. Vague goals like "improve the code" may cause the agent to iterate longer than necessary.
エージェントは、ゴールの記述から受入基準を自分で推論します。だからこそ、「どうなれば得点なのか」を具体的に書くことが効いてきます。
❌ /goal improve the code (ゴールマウスがどこにあるか分からず、延々と走り続ける)
✅ /goal refactor the auth module to use JWT tokens and ensure all tests pass (「全テストが通る」という明確なゴールライン)
「全テストが通る」「TypeScript エラーがゼロ」のように検証可能な完了条件を書けば、エージェントは明確なゴールに向かってシュートを打てます。逆に「コードを良くして」のような曖昧なゴールは、どこに蹴り込めばいいか分からず、必要以上に反復が長引きます。狙うゴールの位置は、キックオフのときに自分で決めておきましょう。
試合中に方向修正する ― 監督の指示 (Queue Steering)
/goal で試合が始まったあと、「やっぱりこの方針で進めてほしい」と思うこともあります。従来は Ctrl+C で一度止めて最初からやり直すしかありませんでしたが、2.7.0 では同時に追加された Queue Steering で、ループを止めずに方向修正を送れるようになりました。試合を止めずにベンチから指示を飛ばす監督のイメージです。
- Steer モード (デフォルト) : メッセージが次のツール境界で即座に注入され、その場で軌道修正される
- Queue モード (Ctrl+S で切替) : メッセージはバッファされ、現在のターンが終わってから送信される
ゴールを完全にキャンセルしたいときは /goal clear 、走らせたまま微修正したいときは Queue Steering、と使い分けられます。なお、/goal clear でループを止めても、すでにディスクに加えられた変更はそのまま残ります。元に戻したいときはバージョン管理を使いましょう。
使いどころ ― VAR が活きるのは「際どい試合」
/goal が真価を発揮するのは、「完了をテストや検証で機械的に判定できる」マルチステップのタスクです。たとえば次のようなケースです。
|
向いているタスク
|
例
|
|---|---|
|
制約つきリファクタリング
|
「API ルートを Express から Hono に移行し、テストスイートを通す」 |
|
検証つきバグ修正
|
「ワーカープールの競合状態を直し、回帰テストを追加する」 |
|
基準つきコード生成
|
「全フォームコンポーネントに入力バリデーションを追加し、アクセシビリティテストを通す」 |
|
複数ファイルにまたがる変更
|
「User モデルを Account にリネームし、import を一切壊さない」 |
逆に、やることが既に決まっている単発のタスクには向きません。その場合は普通のプロンプトの方が速い。ゴールラインテクノロジーや VAR が活きるのは「際どい判定」がある試合であって、ど真ん中のシュートにはオーバースペックなのと同じです。/goal は「検証ステップごとエージェントに任せたい」ときの選択肢だと考えると、使いどころがはっきりします。
反則を防ぐ ― ゴールを「偽装」させないために
① 完了条件を「偽装できないもの」にする ― 中立の主審を置く
一番効くのは、完了判定をローカルではなく CI/CD パイプラインの実行結果 に置くことです。ゴールにこう書きます。
/goal CodePipeline my-app-dev の全 stage (Source → Build → Deploy → Smoke → E2E)
を Succeeded にする。確認方法: aws codepipeline list-pipeline-executions
--pipeline-name my-app-dev で最新の status が Succeeded であること。
パイプラインの Succeeded は、エージェントが手元で書き換えられません。実際に本物の環境で Build も Deploy も Smoke も E2E も通らない限り、得点は認められない。これは中立の主審が、本物のスタジアムでボールがラインを割ったことを確認するのと同じです。ローカルのテストが「自分で操作できるリプレイ映像」だとすれば、CI/CD は改ざんできない公式記録です。
前回のハーネス記事 の言葉で言えば、CI/CD パイプラインは「買収できない独立した Evaluator」です。選手が同時に主審を兼任できない、という分離が、自己評価の甘さを構造的に潰します。
② 静的解析を副審に加える ― 多層で見張る
主審だけでなく副審・VAR を置くように、静的解析の関門を重ねます。型チェック、Linter、未使用コード検出、シークレット検出、そして Mutation Testing (https://stryker-mutator.io/)。特に Mutation Testing は「そのテストは本当にバグ (ファウル) を検知できるのか」をわざとコードを書き換えて試すので、assertion を骨抜きにする抜け道を見抜けます。これらをパイプラインの Build ステージに組み込んでおけば、「テストは通ったが中身は空」を許しません。
③ 禁止事項と許容事項をゴールに明示する ― ルールブックを渡す
何が反則かを言葉にしておかないと、エージェントは「失敗テストを消す」を正当なプレーだと解釈します。そこで、ゴール文に禁止事項 (やってはいけない抜け道) と許容事項 (やってよい正当な修正) を添えます。以下はサンプルです。
禁止事項 (1つでも該当したら修正として認めない):
- test.skip() / xit などで失敗テストを無効化する
- assertion を弱める (toBe → toBeTruthy など)
- timeout や retry 回数を伸ばして不安定さを隠す
- 期待値を「失敗時の実際値」にすり替える (根本原因を直さず辻褄合わせ)
- 失敗するテストを削除する
- try/catch で assertion error を握り潰す
- プロダクションコードにテスト検知用の分岐 (if TEST / if CI) を入れる
許容する修正 (理由を説明してから実施):
- プロダクションコードのバグ修正
- 実装変更で古くなったテスト前提の更新 (変更理由を明示)
- インフラ設定の不備修正 (権限不足 / 環境変数 / 設定ミス)
- flaky の根本原因修正 (race condition / 順序依存の排除)
- lint / typecheck エラーの修正
ポイントは、禁止リスト (denylist) だけに頼らないことです。列挙されていない裏技は通り抜けてしまいます。そこで「許容する修正」のリスト (allowlist) を併記し、「これ以外は勝手にやらず、理由を説明してから」と縛る。禁止と許容の両面で挟むと、未知の抜け道も止まります。これは ハーネス記事 で触れた Sprint Contract (完了の定義を事前に合意する) の実践そのものです。
注意 ― 自律デプロイには相応のガードレールを
まとめ ― 笛を吹くのは誰か
/goal コマンドが解いている問題を一言でまとめると、「完了の定義をエージェントの自己申告から、検証可能な基準へと移す」 ことです。
- キックオフ : /goal <達成したいこと> --max N でゴールと試合時間を宣言する
- 試合進行 : エージェントは 1 ターンでは止まれない。実装 → 検証 → 修正を反復する
- ゴール判定 : 受入基準を検証してからでないと完了できない (ゴールラインテクノロジー)
- 試合中の指示 : Queue Steering でループを止めずに方向修正できる
- 使いどころ : テストで完了を判定できるマルチステップのタスク
- 反則防止 : 完了条件を CI/CD など偽装できないものに置き、禁止事項と許容事項を明示する
AI エージェントに自律作業をさせるとき、最大の敵は能力の不足ではなく「甘い自己判定」です。前回のハーネス記事では、Generator と Evaluator を分離して検証を独立させる仕組みを自分で組みました。 /goal は、その「検証して初めて完了」という発想を、コマンド一発で呼び出せる形にしたものだと言えます。サッカーがゴールラインテクノロジーで判定を客観化したのと同じように、「完了」を主観から検証へと引き戻す仕組みです。
ワールドカップを観ながら「今のゴール、本当に入ってた ? 」とつぶやくとき、ぜひお手元の Kiro CLI の /goal も思い出してみてください。それでは、良い試合を !
筆者プロフィール
稲田 大陸 (いなりく / @inada_riku)
アマゾン ウェブ サービス ジャパン合同会社
ソリューションアーキテクト
AWS Japan で働く筋トレが趣味のソリューションアーキテクト。製造業のお客様を支援させていただいています。最近は AI 駆動開発ライフサイクル (AI-DLC) の日本のお客様への布教活動もしつつ、Kiro のブログなどを執筆しています。