自然言語の依頼を、本番で動くAIエージェントへ翻訳する——App Builders編

Day 1で迎えた「ものすごく優秀な新人」に、今度は仕事道具を作ってもらうことになりました。

依頼は一見簡単です。

顧客からの質問に答え、必要なら社内データを検索し、計算もできるサポートAgentを作ってください。

ここでいうAgentは、利用者の依頼を読み、必要な手順を選んで仕事を進めるソフトウェアです。Toolは、そのAgentが検索、計算、データ更新などを行うために呼び出す機能です。この二つを分けて考えることが、この記事の出発点です。

優秀な新人は、驚くほど速くコードを書けます。しかし、依頼した側が本当に知りたいのは、生成された行数ではありません。

  • どの質問へ答え、どの質問は断るのか
  • どのToolを、どんな条件で使うのか
  • Toolが返した値は実データか、テスト用データか
  • 会話中の情報を、いつまで、誰の単位で覚えるのか
  • 答えだけでなく、そこへ至る経路も正しかったか
  • 失敗したとき、安全に止まり、原因を調べられるか

Build with Gemini Tokyo Day 2のApp Builders Trackでは、AIと相談しながらAgentの雛形を作り、テストし、対話実行し、処理の足跡を確認し、外部機能を追加するところまで進みました。後半では、会話をまたぐ記憶、社内文書の検索、安全なコード実行、画面表示、公開後の運用を扱いました。個々の製品名は、役割を説明する1.2節以降で示します。

この記事では、この流れを「AIがコードを書いた」という一場面ではなく、曖昧な人間の意図を、検査できるソフトウェアへ段階的に翻訳する工程として読み解きます。

この記事の地図

最初に結論を置きます。

ここでいうCoding Agentは、開発者の依頼を読み、コードの作成だけでなく、調査、編集、実行、テストまで進める開発支援Agentです。

Coding Agentの価値は、コードを速く出すことだけではない。自然言語の依頼を、仕様、実装、Tool契約、テスト、実行証跡、配布可能な成果物へ変換し、人間が検証できるようにすることにある。

意図から実行証跡までの変換

この変換は、コンパイラに少し似ています。高水準の意図を、実行可能な形へ少しずつ具体化し、途中の各段階で間違いを検出します。

次の表は左から右へ読みます。人が口頭で頼んだ内容を、どんな中間成果物へ変え、その段階で何を検査するかを並べています。右端の用語は、直後の日常語表で言い換えます。

人間の言葉 変換後の成果物 確かめたいこと
何をしたいか 仕様と制約 曖昧さや禁止事項が残っていないか
どう動くか Agentのコード 開発部品の規約に合うか
何を使えるか Toolの入出力仕様 名前、引数、戻り値が一貫するか
何を覚えるか Session、State、Memory 範囲、保持期間、削除が明確か
正しいか テストと評価 結果と経路の両方を検査したか
何が起きたか 処理の足跡(Trace) Tool選択、引数、再試行を追えるか
どう届けるか 実行環境、画面、配備 認証、隔離、版管理があるか

この先も、一つの開発案件だけを追う

機能名が多いので、物語の軸を固定します。説明用の架空人物であるプロダクト担当のアヤさんが、開発担当の新人と一緒に「問い合わせへ答え、注文状況と料金を調べ、必要なら配送先の変更案を作るサポートAgent」を開発します。ただし、返金や注文変更は勝手に実行させません。

アヤさんの案件は、各技術を一続きで説明するための架空シナリオです。本文で「演習では」と書くテスト結果や画面は、ハンズオンで確認した内容です。架空の案件と演習事実を、その場で分けて示します。

最初の依頼は一文です。そこから、仕様を決め、Toolを作り、模擬データによる失敗を見つけ、評価し、会話の状態と情報源を分け、最後に本番で守る約束へ変えます。この先に長期記憶、社内文書検索、動的な画面生成が出てきても、別の話が始まったのではありません。同じサポートAgentを「作れたデモ」から「任せられる製品」へ近づけるための課題です。

先に、用語を日常語へ置き換える

用語 この記事での意味 サポート業務にたとえると
Agent 依頼を読み、必要な手順やToolを選ぶ実行主体 問い合わせ担当者
Tool 外部の計算、検索、更新を行う契約付きの機能 社内システムの操作画面
Schema / contract 入力、出力、失敗時の決まり 記入必須の業務票
Trace 一つの回答へ至る呼び出しの順序 対応履歴
Evaluation 期待する結果と経路を確かめる試験 応対品質の検品
Provenance 値がどこから来たかを示す情報 データの出典ラベル
Session / State / Memory 会話単位、作業途中、長期保持を分けた情報 今回の電話、処理中の案件票、継続顧客メモ
Identity 利用者やAgentをシステムが区別するための身元 担当者ごとの社員証
RAG 必要な資料を検索してから、その資料に基づいて回答する仕組み 社内マニュアルを開いてから答えること
Sandbox コードを本体から隔離して動かす実行場所 周囲へ影響を出さない実験室

用語の厳密さは必要な場所で補います。まずは「何を作る部品か」より、「サポートAgentのどの不安を解く仕組みか」を手掛かりにしてください。

記事は三つの段階で進みます。第1段階(1〜5章)は曖昧な依頼をToolと評価へ変える基礎編、第2段階(6〜10章)は会話、検索、実行環境、利用者向け画面(UI)、認証をつなぐ製品化編、第3段階(11〜18章)は変更を安全に続ける設計・運用編です。途中で新しい用語が出ても、アヤさんの案件のどの不安を解いているかへ戻ります。

1. 最初の仕事は、コードを書くことではなく曖昧さを見つけること

1.1 「サポートAgentを作って」では決まっていない

自然言語は、人同士なら文脈で補えます。しかしソフトウェアとして動かすには、未確定事項が多すぎます。

  • 問い合わせ対象は商品情報だけか、注文情報も含むか
  • 情報源は公式FAQ、社内DB、Webのどれか
  • 返金やキャンセルを実行してよいか
  • 顧客本人であることをどう確かめるか
  • Toolが失敗したら再試行するか、人へ渡すか
  • 会話履歴をいつ消すか
  • 長期Memoryへ何を残してよいか
  • 正しさをどの評価ケースで判定するか

Coding Agentが優れているほど、曖昧なままでも「それらしいもの」を完成させてしまいます。だから良い開発フローは、曖昧さを隠すのではなく、質問、計画、型、テストへ変換します。

flowchart LR
    A[人間の依頼] --> B[仕様と禁止事項]
    B --> C[AgentとToolの実装]
    C --> D[決定的テスト]
    D --> E[対話と経路の評価]
    E --> F[実行証跡]
    F --> G[配布可能な成果物]
    D -->|失敗| B
    E -->|期待との差| B

図のポイントは、最後まで一方向に進まないことです。テストやトレースで見つかった差は、プロンプトの言い換えだけでなく、最初の仕様へ戻します。

1.2 開発に使った道具は、それぞれ何を担当するか

名前が続くと急に難しく見えますが、それぞれの役割は異なります。

要素 たとえるなら 主な役割
Antigravity リポジトリを読める開発担当者 計画、編集、実行、検証を往復する
Skills 作業手順書 必要な場面で手続き知識と規約を渡す
公式資料へAIから接続する窓口(Docs MCP) 公式マニュアルへの検索窓口 変化するAPIや仕様を参照する
Agents CLI 工具箱と作業コマンド 雛形作成、実行、評価、配布を行う
Agent Development Kit(ADK) Agentを組み立てる部品体系 Agent、Tool、Session、Callbackを実装する
Tests / Eval 検品工程 計算、Tool選択、会話、品質を検査する

Agents CLIのProject Structureでも、Agent code、App、Tests、Eval、Manifest、依存関係の固定ファイルなどが分離されています。この分離には理由があります。変更の影響と失敗の場所を切り分けるためです。

1.3 Skillは能力そのものではなく、仕事の進め方

Agents CLI Getting StartedSkills Referenceでは、Workflow、ADK code、Scaffold、Evaluation、Deployment、ObservabilityなどのSkillがCoding Agentへ提供されます。

Skillを「魔法のプラグイン」と考えると誤解します。Skillが主に与えるのは、次のような手続き知識です。

  1. いまの依頼に関係するSkillを見つける
  2. 必要な本文だけを読む
  3. 書かれた順序や制約に従う
  4. 必要なツールやテンプレートを使う
  5. 検証し、成果物を残す

Skillが選ばれ利用される流れ

図はもう一つ重要な違いも示しています。

  • Capability:技術的に使える能力
  • Policy:今回使ってよい能力
  • Trace:実際に使った能力

能力一覧にあるから使ってよいとは限らず、使ってよいから実際に使ったとも限りません。この三つを分けると、Tool選択のレビューがしやすくなります。

Skillを増やせば自動的に賢くなるわけでもありません。似た説明のSkillが増えると選択が競合し、常時読み込む情報が増えると肝心の依頼を考える余地が減ります。Skillにも版管理、適用条件、回帰テストが必要です。

ここまでの振り返り

アヤさんの一文の依頼を、対象、情報源、禁止操作、失敗時の扱い、記憶、評価条件へ分けました。さらに、開発を支える道具の役割も整理しました。まだコードの良し悪しを議論する前の段階ですが、ここで曖昧さを残すと、後の高速な実装が高速な手戻りになります。

次に残る問題:サポートAgentは注文検索や計算を自分では行えません。外界へ出る窓口であるToolを、モデルにも実行環境にも誤解されない契約として設計する必要があります。

2. Toolは「関数」より広い——Agentと外界の契約である

2.1 なぜ普通の関数より慎重に設計するのか

通常のプログラムでは、開発者がコード中で関数名と引数を指定します。Agentでは、モデルが利用者の自然言語を読み、どのToolを呼ぶか、何を引数にするかを選びます。

つまりToolには二種類の読み手がいます。

  1. 実行環境:型、戻り値、例外を解釈する
  2. モデル:名前、説明、引数の意味から「いつ使うか」を判断する

docstringやschemaは、補足説明ではなく実行契約の一部です。

Tool契約の三層

Toolは少なくとも三層でテストします。

確かめること
処理本体 計算や検証が正しいか 金額計算、範囲チェック
宣言 名前、schema、説明が意味を表すか 引数名、必須項目、エラー形式
Agent連携 自然言語から正しく選ばれるか Tool選択、引数、呼び出し順

2.2 チップ計算を例に、契約を読む

いきなり顧客データや注文変更へ接続すると、Tool設計と権限設計の問題が同時に起きます。そこで演習では、まず外部システムを更新しないチップ計算を小さな教材にし、入力、計算、丸め、失敗という契約だけを観察します。ここで学ぶ書き方を、後で注文や配送のToolへ広げます。

演習では、請求額とチップ率からチップと合計を返すFunction Toolを追加しました。

Function Toolの実装

ここでやりたいのは、単に掛け算をすることではありません。「請求額と率がそろったときだけ使う」「率は18なら18%を意味する」「返す項目はチップと合計」という約束を、モデルにも実行環境にも伝えることです。

次は、通貨と丸め規則、異常値まで明示した例です。コードに慣れていない読者は読み飛ばして構いません。見るべき点は、曖昧だった業務ルールを、検査できる条件へ移していることです。

境界条件を含むTool実装例
from decimal import Decimal, ROUND_HALF_UP
from typing import Literal

Currency = Literal["USD", "JPY"]

def calculate_tip(
    bill_amount: str,
    tip_percent: str,
    currency: Currency,
) -> dict[str, str]:
    """請求額、チップ率、通貨がそろったときだけ合計を計算する。"""
    bill = Decimal(bill_amount)
    percent = Decimal(tip_percent)

    if bill < 0:
        raise ValueError("請求額は0以上である必要があります")
    if percent < 0 or percent > 100:
        raise ValueError("チップ率は0〜100で指定してください")

    scale = Decimal("1") if currency == "JPY" else Decimal("0.01")
    tip = (bill * percent / Decimal("100")).quantize(
        scale,
        rounding=ROUND_HALF_UP,
    )
    total = (bill + tip).quantize(scale, rounding=ROUND_HALF_UP)

    return {
        "currency": currency,
        "tip_amount": str(tip),
        "total_amount": str(total),
        "rounding": "ROUND_HALF_UP",
    }

この例では、負の請求額、極端な率、通貨ごとの小数桁をAgentの会話能力へ任せず、決定的な処理へ移しています。「日本円の端数をどうするか」「税の前後どちらに率を掛けるか」など、組織のルールはさらに仕様とテストへ追加します。

2.3 テスト成功を、何の証明かまで読む

Function Tool追加後、処理本体だけでなく、AgentがそのToolを選択するテストまで成功しました。

Function Toolのテスト結果

これは重要な証拠ですが、あらゆる入力で正しいことの証明ではありません。テストされていない負数、巨大値、通貨混在、税や割引との順序は別途必要です。

テスト件数より、どの契約を覆っているかを読みます。

3. 最も面白い失敗:モデルは忠実なのに、答えが間違っていた

3.1 東京の天気が90°Fになった

決まった式を計算するToolの次は、外部から値を取得するToolを見ます。注文データへ進む前に、演習で使った天気Toolを調べると、「処理は成功したのに情報源が違う」という重要な失敗が見えました。

Playgroundで東京の天気と現在時刻を尋ねると、Agentは天気Toolと時刻Toolを使いました。時刻Toolでは地名を補正し、再試行も行っています。

複数Toolの実行経路

ところが、最終回答の東京の天気は90°F(約32℃)、晴れでした。「モデルが事実でない内容を作った」と結論したくなります。しかしToolの実装を確認すると、実際の天気APIではなく、特定都市以外へ固定値を返すテスト用の模擬Toolでした。

模擬Toolの境界

モデルは、与えられたTool結果へ忠実でした。誤りは文章生成ではなく、情報源の契約にあります。

この種の失敗は危険です。一時保存された古い値(cache)、別顧客のデータ、推定値、テスト用の固定データでも、Agentは自然で説得力のある文章に整えます。Toolの出力が、文章の流暢さによって「洗浄」され、確かな事実に見えてしまいます。

3.2 値だけでなく、値の素性を返す

対策は、Tool resultへprovenance、つまり値の出自を付けることです。

次のJSONは、温度そのものに加えて、実データか模擬データか、いつ観測したか、何を問い合わせたかを返す例です。目的は項目を増やすことではなく、Agentが「事実として断定してよい値か」を判断できるようにすることです。

Tool resultへ出自を付ける例
{
  "value": {
    "temperature_f": 90,
    "condition": "sunny"
  },
  "provenance": {
    "source_kind": "simulation",
    "upstream": "local_fixture",
    "normalized_query": "Tokyo",
    "observed_at": null,
    "valid_until": null,
    "dataset_revision": "demo-v1",
    "is_complete": true
  }
}

この結果なら、Agentは「実際の天気」ではなく「デモ用の応答」と明示できます。本番では、取得時刻、有効期限、上流API、データ版、欠損、ページング、品質フラグ、証拠URIなどを用途に応じて持たせます。

3.3 失敗した層を取り違えない

見えた症状 調べる場所
Toolを呼ばない Instruction、Tool description、routing
違うToolを呼ぶ Tool同士の役割重複、説明の曖昧さ
引数が違う schema、正規化、Entity resolution
Toolの値が違う 上流API、cache、fixture、実装
値は正しいが説明が違う 文章生成、grounding、format
操作が二重になった 再試行、時間切れ、重複実行の防止処理

最終回答の採点だけでは、この分類ができません。だから実行Traceが必要です。

ここまでの振り返り

Toolは単なる関数ではなく、「いつ呼ぶか」「何を渡すか」「返った値をどう解釈するか」まで含む契約でした。東京の天気が誤っていた場面では、モデルではなく模擬Toolが原因でした。最終文章だけを見ず、値の出自と実行経路を見ることで、修正すべき層を特定できます。

次に残る問題:Toolが技術的に呼べても、その利用者と目的で呼んでよいとは限りません。また書き込みToolは、善意の再試行でも二重処理を起こします。次は能力、許可、実行事実を分けます。

4. 「使える」「使ってよい」「実際に使った」を分ける

Agentに登録されたTool一覧は、能力の地図です。しかし、今回の利用者が使ってよい範囲や、実際に通った経路とは違います。

  • Capability graph:技術的に呼べるAgentとTool
  • Policy graph:この利用者、この目的、この状況で呼んでよい範囲
  • Execution trace:今回、どの順番、引数、結果で呼んだか

たとえば書き込みToolが登録されていても、問い合わせ用途では使用禁止にできます。Toolを呼んでも、通信の共通入口であるGatewayや、データ側の権限管理であるIAMで拒否されることがあります。失敗後に別Toolへ切り替える場合もあります。

4.1 再試行は、副作用があると別の問題になる

時刻の取得で地名を補正して再試行するのは、多くの場合安全です。しかし注文、予約、メール、決済を同じように再試行すると、二重実行になる可能性があります。

副作用のあるToolには、少なくとも次が必要です。

  • 同じ依頼を二度実行しないための識別子(idempotency key)
  • 引数全体のfingerprint
  • 実行済み重複の検出
  • 実際に確定するcommit point
  • 再試行可能な失敗と、再試行禁止の失敗の区別
  • 人の承認内容と実行引数の結合

「Agentが賢く再試行する」は、読み取り処理では回復力、書き込み処理では事故原因になり得ます。

5. Evaluationを、回答コンテストから品質保証へ変える

演習では単体テストに続き、CLIから評価を実行し、高いスコアを確認しました。

テストと評価の成功

この結果は「指定した評価データと評価軸では成功した」という証拠です。「あらゆる質問に正しく答える」という証明ではありません。

Agents CLI Evaluation Guideでは、一般品質、指示追従、Tool利用、複数ターンの経路、タスク成功、幻覚、grounding、安全性などを扱えます。

5.1 テストを階層に分ける

主な対象 判定方法
単体 計算、検証、正規化 厳密なassert
契約 Tool schema、error、timeout schema、snapshot
Agent連携 Tool選択と引数 期待trace
会話シナリオ 複数ターン、修正、拒否 採点基準(rubric)と禁止条件
配備後 Identity、Network、State 本番相当のE2E
継続監視 drift、実利用の長尾 samplingと人のreview

計算、認可、Tool名、引用URIの一致は、可能な限り決定的に判定します。説明の分かりやすさや文体のように一つの正解がない部分では、別の大規模言語モデルに採点させる方法(LLM Judge)と、人が一部を確認する標本レビューを使います。

5.2 LLM Judgeも測定器である

LLMによる採点は便利ですが、Judge modelの版、候補の提示順、rubricの曖昧さ、長文の位置、参照回答の誤りで揺れます。

したがって評価結果には、Agent側だけでなく次を固定・記録します。

  • Judge modelと版
  • rubricの版
  • 入力データセットの版
  • sampling条件
  • 実行回数
  • 人間評価との一致率
  • 重大条件を別判定した結果

高い平均点に、越権操作の一件を埋めてはいけません。

ここまでの振り返り

ここまでで、Toolを呼べること、今回呼んでよいこと、実際に呼んだことを分けました。そのうえで、計算は厳密なテスト、Toolの経路はTrace、説明品質はrubricというように、失敗の種類に合う測り方を選びました。

次に残る問題:一回の正解だけでは製品になりません。複数ターンの会話で何を保持するか、公式文書をどう検索するか、計算コードをどこで安全に動かすか、画面へ何を表示するかを決める必要があります。

6. Session、State、Memoryは全部「記憶」ではない

人間の新人にたとえると、机の上の会話メモ、進行中案件の管理票、長期的な顧客知識は別物です。Agentでも同じです。

Session、State、Memoryの境界

  • Session:一連の会話や実行をまとめる単位
  • State:その仕事の途中経過。現在のステップ、選択、Tool結果など
  • Memory:別のSessionでも参照する長期情報

Agent Architecture Componentsは、短期のSession/Stateと外部のPersistent Memoryを分けます。Memory Bankは、Session eventやContentからMemoryを生成し、Scopeに基づいて検索できます。

6.1 Memoryは便利なcacheではなく、新しいデータ製品

長期Memoryには、要約、好み、過去の判断が残ります。だから次を設計します。

  • 誰のMemoryか:利用者、組織、案件、Agent
  • 何を保存してよいか
  • 事実と推定をどう区別するか
  • 根拠と生成時刻を残すか
  • いつ期限切れにするか
  • 訂正と削除をどう反映するか
  • 検索したMemoryをどう監査するか

古いMemoryが現在の事実より優先されると、Agentは一貫して間違えます。Memoryの品質は、保存件数ではなく、正確性、鮮度、削除可能性、アクセス境界で測ります。

7. Code Executionは、二つの実行面を区別する

「AgentがPythonを実行する」と聞くと一つの機能に見えますが、目的の異なる実行面があります。

7.1 モデル応答の途中で行う計算

Gemini API Code Executionは、モデルが応答を作る途中でコードを生成・実行し、計算や解析結果を回答へ使うToolです。短い計算やデータ処理に向きますが、実行時間、File I/Oなどの制約があります。

7.2 Agentから独立したSandbox

Code Execution Sandboxは、Agent本体の実行環境(Runtime)とは分離した隔離資源として扱います。複数回の実行状態やファイルの読み書きを扱える一方、外部通信、存続時間、容量、成果物の持ち出しを明確にする必要があります。

選定時は、「Pythonが動くか」ではなく次を確認します。

  • 何のIdentityで実行するか
  • Networkは初期状態で閉じているか
  • 読み書きできるFileは何か
  • 実行時間、CPU、Memory、容量の上限
  • Session終了時の削除
  • packageの供給元と、内容から作る電子的な指紋(hash)
  • stdout、生成File、例外を証跡として残せるか

8. RAGは、一つの品質指標ではない

RAGは、必要な資料を検索してから、その内容を使って回答する仕組みです。ここで大切なのは、「検索」と「回答生成」を一つのブラックボックスにしないことです。

Gemini Enterprise Agent PlatformのRAG Engineも、文書の取り込み、検索しやすい大きさへの分割、意味を数値で表す処理、検索用の索引作成、検索、回答生成という複数段階で構成されます。

「RAGの答えが悪い」ときは、少なくとも次を分けます。

  1. 正しい文書が登録されていない
  2. 文書はあるが、分割で意味が切れた
  3. 検索queryが悪い
  4. 正しい断片が上位に来ない
  5. 取得した断片を回答が無視した
  6. 引用と主張の対応がずれた
  7. 文書が古い、または利用者に見せてはいけない

保存すべき証拠も、最終回答だけではありません。検索query、filter、取得したchunk、score、文書版、引用位置、生成時に使ったchunkを持つことで、どの段階を直すべきか分かります。

ここまでの振り返り

会話の「今回だけの情報」と長く覚える情報を分け、計算を行う実行環境を用途別に分け、RAGの失敗を取り込み・検索・生成へ分解しました。アヤさんのサポートAgentは、古い顧客メモを公式規程より優先したり、検索失敗を文章生成の問題と誤診したりしにくくなります。

次に残る問題:内部で正しく処理できても、利用者へ危険な画面を返したり、開発者の認証を本番へ流用したりすれば境界が崩れます。次は表示とIdentityを閉じます。

9. Agentが画面を作るA2UI:自由生成ではなく、表示契約を作る

Agentが回答に合わせて画面部品を指定し、利用者向けの画面へ変換する仕組みがA2UIです。ここでAgentが任意のHTMLやJavaScriptを生成・実行すると、品質、安全性、互換性を管理しにくくなります。A2UIの重要な考え方は、Agentが「どの部品をどう並べるか」という宣言的なUIデータを返し、信頼された表示プログラムが許可済みの部品だけを表示することです。

flowchart LR
    A[Agent] -->|版付きUIメッセージ| V[Schema validation]
    V -->|許可された部品| R[Trusted renderer]
    V -->|未知危険| X[拒否または安全な表示]
    R --> U[利用者の画面]

この境界では、schema版、許可component、action allowlist、URL制限、入力値検証、アクセシビリティ、古いclientへのfallbackを設計します。UIを「コード」ではなく「検証できるデータ」にすることで、Agentとfront-endの契約を安定させます。

10. 認証は「ログインできた」で終わらない

Agents CLI Authenticationも利用方法に応じた認証を説明しています。本番では、次の主体を混ぜません。

  • 開発者がCLIを使うためのIdentity
  • CI/CDがbuild・deployするIdentity
  • Agent Runtime自身のIdentity
  • Agentへ依頼するEnd user
  • Agentが外部Toolへ委譲するIdentity

ローカルで動いた資格情報を、そのままRuntimeへ持ち込む設計は避けます。誰の権限でデータを読んだのか、利用者の権限を引き継ぐのか、Agent自身の権限を使うのかを操作ごとに明示します。

デモから製品へ進む地点

サポートAgentは、会話を続け、社内文書を検索し、必要な計算を隔離環境で行い、検証可能なUIを返せるところまで来ました。同時に、利用者、開発者、実行環境、外部ToolのIdentityも分けました。ここまでが「機能を成立させる設計」です。

ここからは、同じものを翌日、別の開発者、別の版でも安全に変更できるかを考えます。話題は再現可能性、Toolの互換性、評価器の信頼性、MemoryとRAGの境界、運用費用へ進みますが、目的は一つです。変更しても、何が変わり、何が壊れ、出荷してよいかを説明できるようにすることです。

11. 同じものを翌日も作れるか:再現可能性の単位を広げる

「昨日と同じAIへの指示文(Prompt)を入れたのに、今日は別のコードになった」。Agentic Codingでは珍しくありません。原因はモデルの揺らぎだけではなく、Agentが読む世界全体が変わっているからです。

同じ開発結果を説明するには、少なくとも次の文脈を考えます。

再現可能なbuild文脈
  = 人間の依頼と受入条件
  + repositoryのrevision
  + project固有のinstruction
  + 利用したSkillとその版
  + 参照した公式資料の時点
  + CLI、SDK、templateの版
  + modelとtoolchain
  + 実行時の環境設定

この式は「すべてを固定して創造性を消す」という意味ではありません。何が変わったため結果が変わったかを説明できるようにするためです。

式は上から順に、依頼、ソースコード、開発ルール、参照手順、公式資料、開発道具、モデル、環境を並べています。全部を永久固定する一覧ではなく、結果が変わったときに差分を探すチェックリストです。

11.1 生成物だけでなく、変換過程を成果物にする

従来のbuildではsourceと依存関係からbinaryを作ります。Agentic Codingでは、計画、質問への回答、参照資料、Tool実行、テスト結果も、変換過程を説明する重要な資料です。

ただし、思考の全文を無制限に保存する必要はありません。保存したいのは、意思決定を検証できる最小限の情報です。

  • 最終的な仕様と未決事項
  • 変更したFileと差分
  • 読んだ公式資料のURIと取得時点
  • 適用したSkill名と版
  • 実行したコマンドと終了状態
  • テスト、評価、静的解析の結果
  • 人が承認した差分

これにより「AIが作ったから分からない」ではなく、「この仕様、版、検査を通した成果物」と説明できます。

11.2 Lockfileがあっても十分ではない

packageのlockfileは依存関係を固定しますが、外部APIの応答、検索index、model版、Skill本文までは固定しません。逆にすべてを完全固定すると、脆弱性修正や最新情報を取り込めません。

そこで、目的別に方針を分けます。

対象 開発時 評価時 本番時
package 更新可能 lockして再現 承認済みhash
model 比較可能 版を記録 rolloutを段階化
Skill 改善可能 revision固定 変更時に回帰評価
外部データ liveでもよい fixtureとliveを分離 freshnessを記録
Tool stub利用可 contractを固定 provenance必須

12. Toolを育てても壊さない:APIと同じ契約を持たせる

Toolの説明文を丁寧に書くだけでは、本番の契約として足りません。Webサービスの呼び出し口であるHTTP APIと同じように、互換性、エラー、時間切れ、部分成功、版を設計します。

12.1 引数の「型」と「意味」は別

amount: numberだけでは、通貨、税込・税抜、最小単位、負数可否が分かりません。date: stringだけでは、timezone、日付のみか時刻込みか、締切を含むかが分かりません。

機械的な型の外側に、通貨や時間帯のような業務上の意味を表す型(semantic type)を持たせます。

次の表では、中央の列だけでは足りない理由を右列で読みます。たとえばnumberは計算できますが、それが円かドルか、税込か税抜かがなければ、業務上の正解は決まりません。

機械的な型 追加で必要な意味
金額 number / string currency、scale、rounding、税区分
時刻 string timezone、精度、inclusive/exclusive
顧客 string ID namespace、Tenant、検証状態
位置 string country、locale、正規化方法
文書 URI version、閲覧権限(ACL)、内容のhash

12.2 Errorを自然文だけで返さない

Toolが「処理できませんでした」と返すだけでは、Agentは再試行すべきか、人へ聞くべきか、止めるべきか判断できません。

次のJSONは、失敗を構造化する例です。目的は、Agentへ無限再試行させず、安全な次の行動を選ばせることです。

Tool errorの契約例
{
  "status": "error",
  "code": "CUSTOMER_NOT_VERIFIED",
  "retryable": false,
  "safe_message": "本人確認が必要です",
  "operator_detail": "order lookup blocked before data access",
  "next_allowed_actions": ["request_verification", "handoff_to_human"],
  "trace_id": "trace-..."
}

この形式なら、利用者には安全な説明を出し、運用者には調査情報を残し、Agentには許可された次の行動だけを示せます。

12.3 Version移行を「モデルが何とかする」に任せない

Toolの引数名や戻り値を変えると、古いAgent、古いSession、評価データ、UI rendererが壊れる可能性があります。

  • 破壊的変更は新versionにする
  • 旧versionの廃止期限を公開する
  • Agent manifestへ要求versionを書く
  • contract testを提供する
  • rollout中は両versionを観測する
  • 未知のfieldは安全に無視するか拒否するか決める

自然言語は柔軟ですが、実行境界まで曖昧にする理由にはなりません。

13. 採点表そのものは正しいか:Evaluation systemを検査する

Agentの品質を測る評価コード、dataset、Judge promptもソフトウェアです。ここが壊れると、悪いAgentを良いと判定します。

13.1 評価問題が開発側へ漏れる(Dataset leakage)

評価問題がInstruction、Skill、example、training用資料へ混ざると、Agentは未知の仕事へ一般化したのではなく、答えを見た可能性があります。

対策は次の通りです。

  • 開発用、調整用、最終判定用を分ける
  • 最終判定用へのアクセスを絞る
  • 同じ意味の言い換えや境界値を追加する
  • 実利用から匿名化した長尾ケースを継続追加する
  • 問題作成者とrelease承認者を必要に応じて分ける

13.2 評価器の回帰テスト

評価器にも、結果が明白なcalibration caseを与えます。

  • 明らかに正しい回答を合格にする
  • 明らかな越権を不合格にする
  • 引用はあるが対象企業が違う回答を落とす
  • 内容は正しいが禁止Toolを使った経路を落とす
  • 「不明」と答えるべき条件で断定を落とす

Judgeを更新したら、Agentだけでなくこのcalibrationも再実行します。

13.3 評価値の差に意味があるか

4.82から4.86へ上がっても、samplingの揺らぎかもしれません。平均差だけでなく、ケース単位の改善・悪化、重大失敗、反復実行の分散、費用、遅延を見ます。

実務上は、次のようなrelease reportが読みやすくなります。

表は点数の大きさだけを比べるものではありません。上段で利用者価値と安全性を見て、下段で時間と費用の退行を見ます。p95遅延は、100回のうちおおむね95回が収まる応答時間です。一つでも許容できない行があれば、平均改善だけで出荷を決めません。

観点 旧版 新版 判定
必須シナリオ成功 96% 98% 改善
越権操作 0件 0件 維持
正しいTool経路 93% 97% 改善
長尾ケース重大失敗 1件 0件 改善
p95遅延 2.1秒 3.8秒 要判断
1実行当たり費用 1.0 1.4 要判断

品質だけでなく、遅延と費用の退行を同じ差分へ載せます。

14. 覚える情報と、調べ直す情報を分ける

MemoryとRAGはどちらも「過去の情報を取り出す」ため、混同されがちです。

  • RAGは主に、文書やデータsourceから根拠を検索する
  • Memoryは主に、利用者や案件に関する過去の状態や要約を再利用する

たとえば「返品期限は30日」は公式policy文書からRAGで取得すべきです。「この利用者は簡潔な回答を好む」はMemory候補です。公式規程をMemoryだけに保存すると、規程更新後も古い内容が残る危険があります。

14.1 Memoryへ保存しない方がよいもの

  • password、token、秘密鍵
  • 一時的な認証情報
  • 原文確認が必要な規程や価格
  • 削除要求へ追従できない個人情報
  • 根拠のない推定を事実化した要約
  • 高感度情報を含むToolの生出力

14.2 取得した情報の優先順位

回答時にMemoryとRAGが矛盾したらどうするかを決めます。一般には、版と権威が明確な公式sourceを優先し、Memoryは好みや文脈の補助に使います。矛盾を隠さず、利用者へ確認する選択肢も必要です。

14.3 RAGの評価を段階に分ける

段階 指標の例
取り込み 期待文書の収録率、更新遅延
分割 見出し・表・脚注を壊していない割合
検索 正解chunkのRecall@k、順位
生成 取得根拠への忠実さ、引用一致
Access ACL違反件数、Tenant混在件数

最終回答だけを採点せず、検索前後の証拠を残すことで改善点を特定できます。

15. 動作を観測できる仕組み(Observability)と費用を、後付けにしない

Agentは、一回の依頼で複数のmodel、Tool、検索、再試行を使います。利用者から見えるのは一つの回答でも、内部では小さな分散システムが動いています。

15.1 どこで時間を使ったかを分解する

総応答時間だけでは改善できません。次をspanとして分けます。

  • 入力検査と認証
  • modelの計画
  • Tool選択
  • Toolのqueue、network、処理時間
  • RAG検索
  • 再試行とbackoff
  • 最終生成
  • 出力検査

Playgroundで見たTool graphとeventsは、開発時の理解に役立ちます。本番では同じ発想をtraceへ持ち込み、遅いのがmodelか、Toolか、再試行かを区別します。

15.2 Tokenだけでなく、業務一件の費用を測る

Agentの費用には、model tokenだけでなく、検索、embedding、database query、sandbox、log、network、人のreviewが含まれます。

業務一件の総費用
  = model
  + Toolとdata access
  + 検索・index
  + sandbox
  + observability
  + 人の確認
  + 失敗と再試行

小さなmodelへ替えても、Tool選択を何度も誤り、再試行が増えれば総費用は上がります。反対に、高性能modelが一回で正しい計画を作り、人の確認時間を減らせば総費用は下がる場合があります。

15.3 品質・時間・費用を同じ変更差分で見る

変更 品質 p95時間 一件費用 判断
Tool説明を詳細化 Tool選択改善 わずかに増加 ほぼ同じ 採用候補
検索件数を増やす Recall改善 増加 増加 高リスク質問のみ
長いMemoryを常時投入 一部改善 大幅増加 増加 必要時検索へ変更
再試行を増やす 一時障害に強い 大幅増加 増加 読み取りだけに限定

一つの数字を最適化すると別の面が悪化します。release reviewでは、品質、重大失敗、遅延、費用を並べ、業務価値に対するtrade-offとして判断します。

15.4 監視ラベルの種類を増やしすぎない

利用者ID、query全文、Tool引数をすべてmetric labelへ入れると、値の種類が際限なく増える高cardinality状態になり、監視費用が増え、機密情報も拡散します。

  • metricには集約可能な分類を使う
  • 個別調査はtrace IDから安全なlogへ移る
  • PromptやTool resultの本文は既定で保存しない
  • samplingとredactionを設計する
  • 開発、運用、監査で閲覧範囲を分ける

観測可能性は、何でも保存することではなく、原因を特定できる最小限の信号を持つことです。

設計編の振り返り

依頼から実装までの再現条件、Toolの互換性、評価器の信頼性、MemoryとRAGの情報源、さらに時間と費用まで、一つの変更差分として見られるようになりました。これは機能を増やす章ではなく、既存機能を安全に変更し続けるための章でした。

次に残る問題:設計原則を運用へ渡すには、「気を付ける」ではなく、何を必ず守り、どの数字を監視し、代表案件でどうレビューするかへ落とす必要があります。

16. 本番で守る約束

ここまでの設計を、製品名ではなく「必ず守る条件」へ言い換えます。左列が利用者や運用者との約束、右列がその約束を確認する方法です。

守る約束 検証方法
要求と禁止事項が仕様として残る 実装前review、変更差分
Toolの説明とschemaが実装に一致する contract test、snapshot
模擬データを実データとして断定しない provenance検査、回答規則
Tool選択と引数を再現できる trace assertion
書き込み再試行で二重実行しない idempotency test
Session、State、Memoryの境界がある 利用範囲、保持期限(TTL)、削除試験
計算可能な条件をLLM採点だけにしない deterministic test
高リスク失敗を平均点へ埋めない hard release gate
Sandboxから許可外へ到達できない network・filesystem試験
AgentとUIの版不一致を安全に扱う schema compatibility test

監視したい指標

  • 間違ったToolの選択率
  • 引数正規化の失敗率
  • provenance欠落率
  • Tool timeoutと再試行回数
  • 副作用の重複率
  • traceを最後まで再構成できた割合
  • Memoryの期限切れ・削除反映時間
  • RAGで正解文書が上位に入る割合
  • 評価の重大失敗件数
  • 版更新前後の回帰差

17. アヤさんの案件へ戻り、設計レビューを行う

冒頭でアヤさんが依頼したサポートAgentを、ここまでの設計原則でレビューします。対象は「注文状況を回答し、必要なら配送先の変更案を作り、承認後にだけ変更する」という仕事です。

悪い設計は、広い権限の一つのToolへ注文番号と自由文を渡し、失敗時は自動再試行し、結果だけを自然文で返します。

改善後は次のようになります。

  1. 注文参照と配送先変更を別Toolにする
  2. 参照は利用者の権限、変更は専用の実行主体で行う
  3. 注文番号を顧客Identityと照合する
  4. 変更案を作り、人が確認した内容へ承認を結び付ける
  5. idempotency key付きで一度だけ確定する
  6. 依頼、承認、Tool引数、結果を同じtraceで結ぶ
  7. 参照成功、越権拒否、二重送信、timeout後の再試行をテストする

ここまで来ると、Agent開発はプロンプト調整ではなく、契約、状態遷移、権限、証跡を設計するソフトウェア工学になります。

18. 実務チェックリスト

仕様と実装

  • 読者や利用者のシナリオから要求を書いた
  • できること、できないこと、確認が必要なことを分けた
  • 仕様、Skill、template、依存関係の版を記録する
  • 自動生成後に人が差分と設計をreviewする

Tool

  • Tool名、説明、引数、戻り値が一貫する
  • 入力範囲、単位、通貨、時刻、Tenantを明示する
  • 実データ、cache、fixture、simulationを区別する
  • timeout、部分結果、paginationを表現する
  • 副作用へidempotencyと承認を持たせる

TestとEval

  • 計算とpolicyは決定的に検査する
  • AgentのTool選択、引数、順序も検査する
  • 成功だけでなく拒否、欠損、障害、敵対入力を含める
  • LLM Judgeの版、rubric、揺らぎを記録する
  • 重大失敗を平均値と分ける

State、Runtime、UI

  • Session、State、MemoryのscopeとTTLがある
  • Memoryの訂正、削除、鮮度を扱う
  • SandboxのIdentity、Network、File、資源上限を定義する
  • UI messageをschemaで検証する
  • 開発者、配備、Runtime、利用者のIdentityを分ける

おわりに

自然言語から短時間でAgentが生まれる体験は、たしかに印象的です。しかしApp Builders Trackの本質は、速さそのものではありません。

依頼の曖昧さを仕様へ変える。Toolを外界との契約として設計する。値に出自を付ける。会話の記憶を範囲と期限で分ける。最終回答だけでなく実行経路を評価する。計算、隔離、UI、認証まで、検査可能な境界へ落とす。

そうして初めて、優秀な新人が作ったものを「動いたデモ」から「会社が責任を持って運用できるソフトウェア」へ変えられます。

公式資料