AIエージェントを社内で使い始めると、最初は「どのツールを許可するか」に目が行きます。けれど、本当に困るのは運用後です。誰が、どの依頼で、どの tool を呼び、どのファイルを変え、どの承認で通したのかを後から説明できないと、便利な自動化ほど止めるしかなくなります。
この記事では、Claude Code、Codex、MCP server、GitHub 操作、shell 実行を含む AIエージェント運用で、監査ログとして何を設計するべきかを整理します。社内ルール全体は AIコーディングツールの社内ガイドライン、組織導入の進め方は 生成AIの組織導入ガイド、MCP の injection 境界は MCP prompt injection 対策ガイド、Codex の権限境界は Codex sandbox / approvals 設計ガイド に分けています。
先に結論: ログは「会話履歴」ではなく操作証跡として設計する
AIエージェントの監査ログを、チャット履歴の保存だけで済ませるのは弱いです。チャット履歴には意図は残りますが、実際に何が実行されたか、どの権限で外部システムに触ったか、どの差分がレビューされたかまでは安定して追えません。
私なら、最小構成では次の6種類を分けて残します。
| 区分 | 残すもの | 目的 |
|---|---|---|
| 依頼ログ | prompt、依頼者、対象 repo、目的、禁止事項 | 作業意図を説明する |
| 権限ログ | sandbox、approval mode、network allowlist、MCP scope | 何が許されていたかを説明する |
| tool実行ログ | tool名、引数の要約、対象、成否、時刻 | 実際の操作を追う |
| 承認ログ | 承認者、承認理由、却下理由、例外番号 | 人間判断を残す |
| 成果物ログ | branch、commit、PR、diff、生成ファイル | 何が変わったかを追う |
| レビュー結果 | build、test、security scan、差し戻し理由 | 受け入れ判断を説明する |
ここまで分けると、会話を全部読まなくても「この作業は許可範囲内だったか」「危険な外部接続があったか」「人間レビューを通したか」を判断できます。
なぜ通常のアプリログでは足りないのか
通常のアプリログは、HTTP request、user id、status code、error、latency を追うには十分です。しかし AIエージェントでは、操作が複数段に分かれます。
たとえば、次のような流れです。
- 人間が「このPRの失敗を直して」と依頼する
- エージェントが CI log を読む
- shell で再現コマンドを実行する
- package を追加しようとする
- MCP 経由で issue や docs を読む
- branch に差分を作る
- PR に説明を書く
このとき、GitHub の監査ログだけでは shell 実行や MCP tool 呼び出しが見えません。逆に、AIツール側の会話履歴だけでは、GitHub 上の merge、label、review 状態が十分に見えません。MCP server 側のログだけでも、人間が何を頼んだのかは分かりません。
つまり、AIエージェント監査は単一製品のログ機能ではなく、依頼、権限、実行、成果物、レビューを相関IDでつなぐ設計として考える必要があります。
最初に決めるべき相関ID
監査ログを後から使える形にするには、まず相関IDを決めます。難しい命名である必要はありません。私なら次のようにします。
agent_run_id = 20260604-codex-blog-7f3a
この ID を、できるだけ多くの場所に残します。
- AIエージェントの作業ログ
- branch 名または PR body
- MCP server の request log
- 承認記録
- CI / build log
- セキュリティレビューのメモ
完璧に全ログへ入れられなくても、PR body と MCP / tool 実行ログに入るだけで追跡性は大きく変わります。重要なのは、あとから「この tool 呼び出しはどの依頼に紐づくのか」を人間が推測しなくてよい状態にすることです。
tool実行ログで必ず残す項目
AIエージェントの監査では、tool 実行ログが中心になります。最低限、次を残します。
| 項目 | 例 | 注意点 |
|---|---|---|
agent_run_id | 20260604-codex-blog-7f3a | 全ログの接続点 |
actor | user@example.com / codex-cloud | 人間と agent を分ける |
tool_name | shell.exec / mcp.github.create_pr | 製品名ではなく操作名で残す |
target | repo:nidoneko/HP / url:api.github.com | 対象システムを残す |
risk_level | read / write / external-send | 後から検索しやすい粒度 |
input_summary | pnpm run build | secrets を丸ごと残さない |
result | success / denied / failed | 失敗と拒否も残す |
approval_id | apr-20260604-02 | 承認が必要な操作だけ |
ここで大事なのは、入力全文を無条件に保存しないことです。AIエージェントは秘密情報や個人情報に近い文脈を扱うことがあります。監査ログが第二の情報漏洩源にならないよう、input_summary と raw payload の保存場所を分けます。
私なら、通常ログには要約だけを残し、必要な raw payload は短い保持期間の隔離ストレージに置きます。特に prompt、tool argument、MCP response、ファイル内容は、便利だからといって全部 SIEM に流すと危険です。
MCP では scope と server version を残す
MCP を使う場合、監査ログには tool 名だけでなく、server と認可情報も残します。
MCP の Security Best Practices は、過剰な scope、token passthrough、監査証跡の欠落を具体的なリスクとして扱っています。特に scope elevation をログに残し、correlation ID を持たせる考え方は、AIエージェント監査にもそのまま使えます。
MCP では次を残します。
- server 名
- server URL または stdio command の識別子
- server version
- OAuth client / service account
- granted scope
- scope elevation の有無
- tool call の risk level
- response の要約
たとえば、GitHub MCP server に read-only scope で PR を読ませるのと、write scope で label や comment を追加させるのは、同じ「GitHub連携」ではありません。監査上は別のリスクです。
承認ログは「誰がOKしたか」だけでは足りない
承認ログでよくある失敗は、approved_by しか残さないことです。AIエージェント運用では、承認理由と却下理由の方が価値があります。
残すべき項目は次です。
- どの操作を承認したか
- どの policy に照らして許可したか
- 代替案を確認したか
- いつまで有効な承認か
- 承認者は依頼者と同一か
- 却下した場合、どの条件なら再申請できるか
たとえば npm install を承認した場合、「依存関係追加を許可」だけでは不十分です。package 名、registry、lockfile 差分、既存代替の有無、CI scan 結果まで見たのかを残さないと、あとから説明できません。
保存場所は3層に分ける
すべてを1か所に集めると運用が単純に見えますが、実際には危険です。AIエージェントのログは、監査価値が高い一方で、機密度も高いからです。
私なら3層に分けます。
| 層 | 置くもの | 保存期間の考え方 |
|---|---|---|
| SIEM / 監査基盤 | event type、actor、tool、target、result、risk | 長めに保持 |
| 作業成果物 | branch、commit、PR、review、build結果 | 開発プロセスに合わせる |
| 隔離ログ | prompt raw、tool argument raw、MCP response raw | 短めに保持しアクセス制限 |
OpenAI の Codex は Enterprise 文脈で Compliance API や管理機能に接続され、Claude Enterprise も audit logs や Compliance API を提供しています。ただし、製品ログだけで自社の開発証跡が完成するわけではありません。GitHub、CI、MCP server、端末側ログ、社内承認フローをどこで接続するかを決める必要があります。
検知ルールは少数から始める
最初から複雑な異常検知を作るより、まずは明らかに危険な操作を検知します。
初期ルールはこれで十分です。
- high risk tool が approval なしで実行された
- read-only run で write tool が呼ばれた
- 未承認 MCP server が使われた
- scope elevation が連続した
.env、秘密鍵、credential file へのアクセスがあった- 外部送信直前に未信頼コンテンツを読んでいた
- agent が生成したログや成果物を agent 自身が消した
OWASP の AI Agent Security Cheat Sheet や MCP Top 10 でも、agent monitoring、structured logging、audit and telemetry の欠落は重要な論点です。実務では、検知の高度さよりも、まず high-risk 操作が検索できることの方が効きます。
小さく始める実装例
いきなり専用基盤を作らなくても、最初の運用は作れます。
{
"agent_run_id": "20260604-codex-blog-7f3a",
"timestamp": "2026-06-04T10:15:42+09:00",
"actor": "developer@example.com",
"agent": "codex",
"workspace": "nidoneko/HP",
"tool_name": "shell.exec",
"target": "repo:nidoneko/HP",
"risk_level": "read",
"input_summary": "pnpm run build",
"approval_id": null,
"result": "success",
"artifact": {
"branch": "article/ai-agent-audit-log-design-20260604",
"commit": null,
"pr": null
}
}
この程度でも、何も残さないより大きく違います。重要なのは、JSON の美しさではなく、run、tool、target、approval、artifact が同じ ID でつながることです。
導入順序
私なら、次の順で入れます。
- PR body に
agent_run_idと実行コマンドを残す - high-risk 操作だけ approval log を残す
- MCP server 側に
agent_run_idを渡す - SIEM には要約イベントだけ流す
- raw prompt / raw response は隔離して短期保持する
- 月次で deny / failed / high-risk event を棚卸しする
最初から全社ログ基盤を作る必要はありません。ただし、何も残さないまま write 権限、MCP、shell、外部送信を広げるのは順番が逆です。
まとめ
AIエージェント監査ログの目的は、誰かを疑うことではありません。便利な自動化を止めずに、事故時に説明し、普段は危険な操作を早く見つけるためのものです。
会話履歴だけでは足りません。依頼、権限、tool実行、承認、成果物、レビュー結果を分け、相関IDでつなぐ必要があります。特に MCP と Codex のように外部 tool や sandbox が絡む運用では、何を許可したかより、許可された範囲で実際に何が起きたかを残す設計が重要です。