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_action | review、承認、再実行、保留のどれか | 次の人間判断を迷わせない |
これは「きれいな報告テンプレ」ではありません。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 | 差分、検証、未解決リスク |
| 親 agent | structured summary、戻り値、次の tool call |
| 監査ログ | correlation id、承認ID、成果物 location |
| CI / eval | machine-readable status、fail reason |
| incident response | stop 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_by、partial_deliverable、next_action は最初から入れておくべきです。
根拠とログを混ぜる
根拠は判断に使ったもの、ログは実行証跡です。最終回答にログ全文を貼る必要はありません。ログの場所、検証結果、失敗したコマンドだけ返せば足ります。
導入順序
いきなり全 agent に厳密な schema を入れる必要はありません。
- まず final answer の 6 項目を AGENTS.md に固定する
- PR 作成、調査、incident など task type ごとに契約を分ける
verificationとrisksを review gate のチェックリストに接続するdeliverableとevidenceを監査ログの correlation id に接続する- API / MCP / batch 処理だけ JSON schema に落とす
この順番なら、会話型の柔軟さを残したまま、レビュー可能性だけを先に上げられます。
まとめ
AIエージェントの出力契約は、きれいな報告フォーマットではありません。agent が作った成果物を、人間がレビューし、別 agent が引き継ぎ、監査ログで説明し、eval で再現できるようにする境界です。
入力側は context engineering、保存側は memory design、agent 間は handoff contract、実行中は runtime monitoring、受け入れ前は review gate が担います。出力契約はその間にあり、作業の終わりを次の判断へ変換します。
まずは final answer に deliverable、scope、evidence、verification、risks、next_action を必ず返させるところから始めるのが現実的です。ここが揃うだけで、「AIがやったらしい」仕事を「レビューできる仕事」に変えられます。