📦

AIエージェントに仕事を任せると、最初に困るのは「答えが間違っている」ことではありません。むしろ、何をやったのか、どの根拠を見たのか、どこまで検証したのか、次に人間が何を見ればよいのかが、毎回違う形で返ってくることです。

この記事では、AIエージェントの 出力契約 を扱います。1回の run に何を渡すかは AIエージェントのコンテキスト設計ガイド、session をまたいで何を残すかは AIエージェントメモリ設計ガイド、agent 間で何を渡すかは AIエージェント引き継ぎ設計ガイド、最終成果物を受け入れる前の確認は Codex レビュー完了ゲート設計ガイド に分けています。

今回の論点は、作業が終わった瞬間に、何をどの形で返させるかです。

先に結論: final answer は感想ではなく契約にする

AIエージェントの最終回答を自由文のまま受けると、レビューが属人的になります。

実装しました。ビルドも通っています。

これだけでは弱いです。どのファイルを変えたのか、依頼外の変更が混ざっていないか、どのコマンドを実行したのか、失敗した検証があったのか、未解決のリスクがあるのかが分かりません。

私なら、出力契約を次の 6 項目に分けます。

項目返させるもの人間が見る理由
deliverable作ったもの、PR、差分、生成ファイル成果物の場所を確認する
scope触った範囲、触らなかった範囲依頼外作業を見つける
evidence参照した docs、ログ、仕様、既存コード判断根拠を追う
verification実行した build / test / lint / manual check受け入れ可能か見る
risks未検証、既知の弱点、運用上の注意merge / deploy 前に止める
next_actionreview、承認、再実行、保留のどれか次の人間判断を迷わせない

これは「きれいな報告テンプレ」ではありません。AIエージェントの出力を、レビュー、監査ログ、eval、次の agent へ渡せる単位にするための契約です。

なぜ出力契約が必要になるのか

人間同士の作業なら、曖昧な報告でも補足質問で回収できます。けれど、AIエージェント運用では同じ前提が使えません。

  • Codex automation が夜間に PR を作る
  • Claude Code の subagent が調査結果だけを返す
  • MCP server が外部システムの値を structured result として返す
  • OpenAI Agents SDK の agent が JSON schema に沿った最終結果を返す
  • GitHub Action や scheduled run が、人間不在のまま成果物を残す

このとき、返却形式が毎回違うと、後段の review gate が壊れます。レビュー担当は会話履歴を読み直し、実行ログを探し、PR diff を見て、結局「たぶん大丈夫」と判断しがちです。

出力契約は、この曖昧さを減らすために置きます。

structured output と業務上の出力契約は別物

一次情報を見ると、各ツールはすでに構造化出力を持っています。

OpenAI API の Structured Outputs は、モデルの応答を JSON Schema に従わせるための仕組みです。OpenAI Agents SDK も agent output schema で JSON schema と validation を扱えます。MCP の tools 仕様にも output schema があり、server は structured result を schema に合わせ、client は検証する前提を置けます。Claude Code も --json-schema や hooks の JSON output で、実行後の返却形式や制御を固定できます。

ただし、ここで止まると足りません。JSON schema は「形」を保証しますが、業務上の出力契約は「レビューに必要な意味」を保証します。

たとえば、次の schema は形としては正しいです。

{
  "status": "done",
  "summary": "対応しました"
}

でも、これではレビューできません。人間が欲しいのは、少なくとも次のような情報です。

{
  "deliverable": {
    "type": "pull_request",
    "url": "https://github.com/example/app/pull/123",
    "changed_files": [
      "src/routes/billing.ts",
      "tests/billing.test.ts"
    ]
  },
  "scope": {
    "requested": "billing retry のバグ修正",
    "excluded": [
      "課金プランの仕様変更",
      "DB schema migration"
    ]
  },
  "evidence": [
    {
      "source": "failing test",
      "detail": "retry count が 0 のときだけ webhook が再送されない"
    }
  ],
  "verification": [
    {
      "command": "pnpm test tests/billing.test.ts",
      "result": "passed"
    }
  ],
  "risks": [
    "本番 webhook の再送キューでは未検証"
  ],
  "next_action": "human_review"
}

この差が、単なる structured output と、運用に使える出力契約の差です。

最初に決めるべき 5 つの境界

出力契約を作るときは、いきなり schema を書かない方がよいです。先に境界を決めます。

1. 成果物の単位

まず、agent が返す成果物を 1 つに決めます。

  • PR
  • patch
  • design doc
  • incident report
  • investigation memo
  • JSON payload
  • spreadsheet
  • deployment plan

ここが曖昧だと、agent は「調査も実装も提案も全部やった」ような報告を返します。便利そうに見えて、レビュー不能です。

たとえば Codex automation なら、成果物は PR と commit です。調査ログは補助情報であり、主成果物ではありません。MCP tool なら、成果物は structuredContent か tool result です。Claude Code subagent なら、成果物は main agent が統合できる短い report です。

2. 受け入れ条件

次に、何を満たせば受け入れるかを固定します。

acceptance:
  required:
    - requested_files_only
    - build_passed
    - no_secret_output
    - internal_links_valid
  optional:
    - screenshot_attached
    - migration_plan

これは eval とも review gate ともつながります。出力契約に acceptance がないと、agent は「作業した」ことを完了条件にし、人間は「受け入れてよい」かを毎回考え直すことになります。

3. 根拠の粒度

根拠は多ければよいわけではありません。

悪い例は、検索結果やログ全文を貼ることです。長いだけで、レビュー担当は読めません。良い例は、判断に使った最小の evidence を短く返すことです。

evidence:
  - source: "official docs"
    url: "https://modelcontextprotocol.io/specification/draft/server/tools"
    used_for: "MCP tool output schema の扱い"
  - source: "repo"
    path: "src/content/blog/ai-agent-context-engineering-guide.md"
    used_for: "既存記事との責務分担"

出力契約の evidence は、監査ログそのものではありません。監査ログへたどれる索引です。

4. 失敗時の返し方

成功時だけ schema を決めても、実運用では足りません。AIエージェントは途中で build に失敗し、権限で止まり、外部 API に到達できず、仕様の矛盾を見つけます。

失敗時にも同じ契約で返させます。

status: blocked
blocked_by:
  type: missing_permission
  detail: "GitHub write token がないため PR 作成不可"
partial_deliverable:
  - branch: "article/output-contract"
  - commit: "abc123"
next_action: "grant_permission_or_create_pr_manually"

これを決めておくと、「できませんでした」で終わらず、途中成果物を救済できます。

5. 次の受け手

出力契約は、誰が読むかで変わります。

受け手出力で強める項目
人間 reviewer差分、検証、未解決リスク
親 agentstructured summary、戻り値、次の tool call
監査ログcorrelation id、承認ID、成果物 location
CI / evalmachine-readable status、fail reason
incident responsestop condition、rollback path、再開条件

同じ agent でも、返却先が人間なのか、別 agent なのか、CI なのかで契約は変わります。ここを分けないと、読みやすいが機械処理できない報告、または機械処理できるが人間が判断できない JSON になります。

具体例: PR 作成 agent の出力契約

ブログ記事、コード修正、設定変更を任せる PR 作成 agent なら、私は次の形にします。

output_contract:
  status: done | blocked | needs_review
  deliverable:
    pr_url: string | null
    branch: string
    commits:
      - string
    changed_files:
      - path: string
        reason: string
  scope:
    requested: string
    excluded:
      - string
    unrelated_changes_touched: boolean
  evidence:
    - source_type: docs | repo | log | issue | user_input
      reference: string
      used_for: string
  verification:
    - command: string
      result: passed | failed | not_run
      note: string
  risks:
    - severity: low | medium | high
      detail: string
  next_action: review | merge | rerun | approve_external_action | unblock

この契約で重要なのは、status よりも next_action です。AIエージェントの完了報告は、人間の次の判断に変換されて初めて役に立ちます。

出力契約を AGENTS.md に置くときの書き方

チームで使うなら、出力契約は prompt の最後に毎回貼るより、AGENTS.md や skill に固定した方が安定します。

## Final Response Contract

When completing work, return:

- Deliverable: PR URL, commit, or artifact path.
- Scope: files changed and explicit non-goals.
- Evidence: primary docs, repo paths, logs, or tests used.
- Verification: commands run and results.
- Risks: unresolved issues or skipped checks.
- Next action: review, merge, rerun, unblock, or approve.

Do not claim completion if verification did not run. Say what is blocked.

ここで細かすぎる schema を置きすぎると、通常の会話まで重くなります。AGENTS.md には人間が読む契約を置き、API や batch 処理では JSON schema を使う、くらいの分担が実用的です。

MCP tool では output schema と監査ログを分ける

MCP server を組織で使う場合、tool の output schema はかなり重要です。仕様上も output schema を提供でき、structured result の validation に使えます。

ただし、MCP tool の output schema に監査ログの全項目を入れるのはやりすぎです。

たとえば search_customer_ticket tool なら、tool result は ticket id、status、summary、updated_at くらいで十分です。誰がなぜ呼んだか、どの承認で通したか、どの session から呼ばれたかは、監査ログ側で相関IDとして持つ方が扱いやすいです。

tool_output:
  ticket_id: "SUP-123"
  status: "open"
  summary: "billing retry failure"
  updated_at: "2026-06-27T09:00:00Z"

audit_event:
  correlation_id: "run_20260627_001"
  tool_name: "search_customer_ticket"
  mcp_server: "support-readonly"
  actor: "billing-investigation-agent"
  approval_id: null

tool result と audit event を混ぜると、LLM に不要な統制情報を見せたり、逆に監査に必要な情報を tool response の中だけに閉じ込めたりします。

よくある失敗

出力を Markdown だけにする

Markdown は人間には読みやすいですが、後段処理には弱いです。PR summary は Markdown でよいとしても、status、changed files、verification、risk は machine-readable にできる形で残した方が再利用しやすいです。

schema を細かくしすぎる

最初から巨大な JSON schema を作ると、agent は schema を満たすことに寄り、重要な補足を落とします。最小契約は 6 項目で十分です。必要になったら task type ごとに増やします。

成功時だけを定義する

失敗時の返却形式がない agent は、途中で止まったときに作業を救えません。blocked_bypartial_deliverablenext_action は最初から入れておくべきです。

根拠とログを混ぜる

根拠は判断に使ったもの、ログは実行証跡です。最終回答にログ全文を貼る必要はありません。ログの場所、検証結果、失敗したコマンドだけ返せば足ります。

導入順序

いきなり全 agent に厳密な schema を入れる必要はありません。

  1. まず final answer の 6 項目を AGENTS.md に固定する
  2. PR 作成、調査、incident など task type ごとに契約を分ける
  3. verificationrisks を review gate のチェックリストに接続する
  4. deliverableevidence を監査ログの correlation id に接続する
  5. API / MCP / batch 処理だけ JSON schema に落とす

この順番なら、会話型の柔軟さを残したまま、レビュー可能性だけを先に上げられます。

まとめ

AIエージェントの出力契約は、きれいな報告フォーマットではありません。agent が作った成果物を、人間がレビューし、別 agent が引き継ぎ、監査ログで説明し、eval で再現できるようにする境界です。

入力側は context engineering、保存側は memory design、agent 間は handoff contract、実行中は runtime monitoring、受け入れ前は review gate が担います。出力契約はその間にあり、作業の終わりを次の判断へ変換します。

まずは final answer に deliverablescopeevidenceverificationrisksnext_action を必ず返させるところから始めるのが現実的です。ここが揃うだけで、「AIがやったらしい」仕事を「レビューできる仕事」に変えられます。

参考にした一次情報

WRITTEN BY nidoneko

Full-stack engineer with 8+ years of experience in TypeScript, React, Node.js, and cloud-native development across healthcare, finance, HR, and IoT domains.

View Profile →