AIエージェントに調査、修正、PR作成、定期実行を任せ始めると、すぐに別の問題が出ます。何を残せば後から説明できるのか。逆に、どこまで残すと secret、顧客情報、不要な会話履歴を抱え込むのか。
この記事では artifact retention を扱います。何を監査ログとして記録するかは AIエージェント監査ログ設計ガイド、何を memory に残すかは AIエージェントメモリ設計ガイド、最終回答の形式は AIエージェント出力契約設計ガイド、稼働中の検知は AIエージェント本番監視設計ガイド に分けています。
今回の論点は、AIエージェントが作業中に生む 成果物と証拠を、残しすぎず消しすぎない単位に分けること です。
先に結論: raw log ではなく review artifact を残す
AIエージェント運用で残すべきものは、会話履歴や tool output の全文ではありません。後から人間が判断を再現できる最小の artifact です。
私は最初に、次の5種類へ分けます。
| 種類 | 例 | 保存目的 |
|---|---|---|
| deliverable | PR、commit、diff、生成レポート | 成果物をレビューする |
| evidence | 参照した docs、ログの抜粋、コマンド結果 | 判断根拠を追う |
| verification | build、test、lint、手動確認結果 | 完了条件を確認する |
| decision | 承認、却下、retry、rollback の理由 | 後から分岐を説明する |
| audit pointer | run_id、tool_call_id、approval_id | 監査ログへ接続する |
この5種類が揃っていれば、raw prompt や全文ログを長期保存しなくても、かなりのレビューはできます。
逆に、全部を1つの run.log に詰めると危険です。レビュー担当は読めませんし、消すべき情報だけを選んで削除することも難しくなります。
なぜ artifact retention が必要なのか
AIエージェントは、通常の自動化より artifact が増えやすいです。
- 会話履歴
- tool call の入力と出力
- MCP server から返った resource
- shell command の stdout / stderr
- 差分、PR、コメント
- 中間要約、handoff packet
- 失敗した retry のログ
- 承認待ちで止まった状態
これらを全部残すと、検索や監査には便利そうに見えます。しかし実務では、保存量より 保存単位 の方が重要です。
OpenAI は business data に対して retention controls やゼロデータ保持の選択肢を提供しています。Anthropic も Claude API で zero data retention や feature ごとの保持モデルを説明しています。つまり、ベンダー側にも保持制御はありますが、社内で作る PR、ログ、ticket、監査DB、MCP tool result までは自分たちで設計する必要があります。
OWASP の AI Agent Security Cheat Sheet も、agent の判断、tool call、結果、監査証跡、異常検知を残すことを推奨しています。ただし「残す」と「全文を永久保存する」は別です。必要なのは、後から調査できる構造です。
監査ログ、memory、artifact を混ぜない
artifact retention が崩れる一番多い原因は、用途の違うものを同じ場所に入れることです。
| 置き場 | 残すもの | 残さないもの |
|---|---|---|
| memory | 次回も使う短い運用知見 | raw log、承認、顧客情報 |
| audit log | tool実行、承認、操作対象、結果 | 長い本文、全文diff、個人的なメモ |
| artifact store | PR、検証結果、根拠抜粋、レポート | secret、不要な会話履歴 |
| incident archive | 隔離した証跡、復旧判断、legal hold | 通常runの全ログ |
memory は品質改善のための文脈です。監査ログは説明責任のための証跡です。artifact は成果物レビューのための材料です。
この3つを混ぜると、削除要求、権限棚卸し、事故調査のどれも難しくなります。特に「前回この操作は承認された」を memory に残すのは危険です。承認は依頼者、対象、期限、データ種別、外部影響が揃って初めて意味を持ちます。
retention policy を run 単位で持たせる
大きなポリシー文書だけでは、AIエージェントの実行時に使えません。run ごとに小さな retention policy を持たせます。
artifact_retention:
run_id: "agent-run-20260808-001"
owner: "platform-ai"
data_class: "internal"
deliverables:
- type: "pull_request"
location: "https://github.com/example/app/pull/123"
retention: "repository_policy"
evidence:
- type: "command_result"
command: "pnpm run build"
retention_days: 90
store: "ci_artifact"
redaction: "stdout_summary_only"
- type: "external_doc"
url: "https://example.com/docs/security"
retention_days: 365
store: "decision_record"
raw_tool_outputs:
retain: false
exception: "incident_hold_only"
deletion:
normal_expiry_action: "delete_raw_keep_summary"
incident_expiry_action: "security_owner_review"
最初から完璧な分類は不要です。最低限、owner、data_class、retention_days、raw_tool_outputs、deletion だけ決めます。
まず data class を決める
保存期間を決める前に、artifact のデータ分類を決めます。
| data class | 例 | 基本方針 |
|---|---|---|
| public | 公開docs URL、公開PR | 長めに残してよい |
| internal | 社内仕様、build log、非公開issue | 要約中心で残す |
| confidential | 顧客名、private repo の詳細、未公開障害 | raw は短期、要約も権限制限 |
| restricted | secret、token、認証cookie、PII | 原則保存しない |
restricted が含まれるなら、通常の artifact store に置きません。必要なら incident response と legal hold の判断へ分けます。
ここで大事なのは、「AIエージェントが読めた情報」と「保存してよい情報」は別だと扱うことです。たとえば private log を一時的に読ませても、全文を PR comment や final answer に貼ってよいわけではありません。
raw output は要約して捨てる
実務では、raw output を全部残したくなる場面があります。あとで debug できそうだからです。
しかし AIエージェントの raw output には、不要な情報が混ざります。
- secret に近い値
- 顧客名や個人情報
- 一時的な仮説
- 失敗した手順
- agent が誤読した外部文章
- 長すぎる stdout
通常runでは、raw output を短く要約して捨てます。残すのは、判断に使った箇所、コマンド名、終了コード、重要なエラー、参照元URL、diff location だけで十分なことが多いです。
verification:
command: "pnpm run build"
exit_code: 0
result: "pass"
important_output:
- "Generated 94 static routes"
- "Build completed successfully"
raw_log_retention_days: 7
summary_retention_days: 365
この形なら、レビュー担当はすぐ判断できます。必要以上のログも抱えません。
retention tier を4段階にする
保存期間は法務、契約、業界、会社ルールで変わります。ここでは日数の正解ではなく、設計の型として4段階に分けます。
| tier | 対象 | 例 |
|---|---|---|
| T0 transient | 保存しない | secretを含むtool output、不要な会話全文 |
| T1 short | 短期だけ残す | raw build log、失敗した探索ログ |
| T2 review | レビュー期間は残す | PR evidence、検証summary、外部docs参照 |
| T3 audit | 監査・事故調査に必要な期間残す | approval_id、tool_call要約、decision record |
| T4 hold | 期限を止めて隔離する | incident artifact、漏洩疑いの証跡 |
通常runの多くは T1 と T2 で足ります。T3 は監査ログ側へ寄せます。T4 は通常の保存期間から切り離し、security owner が解除するまで消しません。
PR と artifact を同じものとして扱わない
Codex や Claude Code に実装を任せると、PR が一番見やすい成果物になります。ただし PR は artifact の一部であって、全部ではありません。
PR に入れるべきものは、レビューに必要な最小情報です。
- 何を変えたか
- なぜ変えたか
- どのファイルが対象か
- 何を検証したか
- 何を検証していないか
- 既知のリスク
PR に入れない方がよいものもあります。
- 長い調査ログ全文
- secret を含む可能性のある raw output
- agent の思考過程のような不要な中間文
- 関係ない外部ページの抜粋
- 失敗した全コマンド履歴
PR には review summary を置き、詳細 artifact は権限付きの保存場所へ逃がします。PR が public repository に出るなら特に重要です。
Codex / Claude Code での実務例
たとえば Codex automation にブログ記事を書かせる場合、私は次のように分けます。
deliverable:
- "src/content/blog/ai-agent-artifact-retention-design.md"
- "data/seo/keyword-plan.md"
- "data/seo/learnings.md"
- "public/llms.txt"
- "public/llms-full.txt"
evidence:
- "keyword-plan の該当行"
- "既存記事の重複チェック結果"
- "一次情報URL"
verification:
- "pnpm seo:update-llms"
- "pnpm run build"
do_not_retain:
- "検索結果全文"
- "ブラウザに表示された不要な本文"
- "root checkout の未コミット差分"
Claude Code で社内repoを修正する場合も同じです。CLAUDE.md や settings で権限境界を固定し、task prompt で今回の artifact retention を渡します。
Artifact retention:
- Return only changed files, verification commands, and unresolved risks.
- Do not paste raw customer logs.
- Summarize external docs as source / date checked / implication.
- If a secret or PII appears, stop and return incident_hold_required.
これくらい短くても、残すものと残さないものが変わります。
MCP tool result は source と allowed use を付ける
MCP を使うと、artifact retention はさらに難しくなります。MCP server から来た tool result は、社内DB、SaaS、GitHub、Notion、Slack など出所がばらばらです。
tool result を保存するなら、最低限このメタデータを付けます。
mcp_artifact:
server: "github"
tool: "read_pull_request"
source_owner: "engineering"
data_class: "internal"
allowed_use:
- "review_current_pr"
- "summarize_findings"
forbidden_use:
- "train_memory"
- "paste_full_log_to_public_pr"
retention_days: 90
MCP server を許可することと、その結果を長期保存してよいことは別です。特に Slack、Gmail、CRM、ticket system のような人間の会話を含む source は、artifact store に全文保存しない方がよいです。
削除可能性を先に設計する
保存設計は、削除設計でもあります。
artifact を残すなら、次の質問に答えられる必要があります。
- 誰が owner か
- どの data class か
- どの retention tier か
- 期限が来たら何を消し、何を要約として残すか
- incident hold に上げる条件は何か
- 削除しても監査ログの連続性が壊れないか
特に delete_raw_keep_summary を標準にすると運用しやすいです。raw log は短期で消し、summary、hash、location、decision だけ残す。これなら後から「何を見たか」は追えますが、不要な機密情報を抱え続けません。
失敗パターン
1. 会話履歴を監査ログ扱いする
会話履歴は便利ですが、監査ログではありません。会話には冗長な文、途中仮説、誤読、機密情報が混ざります。
監査に必要なのは、誰が、いつ、どの tool を、どの承認で、どの対象へ実行し、結果がどうだったかです。会話全文はその代替になりません。
2. memory に判断根拠を残す
memory は次回の作業をよくするための短い知見です。判断根拠や証拠は artifact か audit log へ置きます。
「この顧客は外部送信してよい」「このrepoは本番DBを読んでよい」のような情報を memory に入れると、次回の前提が変わったときに危険です。
3. public PR に raw log を貼る
public repository の PR body や comment に raw log を貼るのは避けます。秘密情報が無いと思っても、path、hostname、内部issue番号、環境名が漏れることがあります。
PR には summary を置き、詳細ログは権限付き artifact store へ置きます。
4. incident と通常runを同じ期限で消す
通常runの raw log は短期で消してよいことが多いです。一方で、情報漏洩疑い、誤deploy、外部MCP write の事故は、通常の期限で消すと調査できなくなります。
incident hold は別状態にします。通常の retention job から除外し、解除条件と owner を明示します。
最小テンプレート
最初はこの程度で十分です。
artifact_retention:
owner: ""
run_id: ""
data_class: "public | internal | confidential | restricted"
retention_tier: "T0 | T1 | T2 | T3 | T4"
keep:
- "deliverable location"
- "evidence summary"
- "verification result"
- "decision record"
discard:
- "raw prompt unless incident"
- "raw tool output unless needed"
- "secret / PII"
expiry:
raw_days: 7
summary_days: 365
on_expiry: "delete_raw_keep_summary"
incident_hold:
trigger:
- "secret exposure"
- "external write outside approval"
- "customer data in output"
owner: "security"
このテンプレートを task intake、output contract、監査ログ schema に接続します。別々の文書に見えても、run_id と artifact_id でつながれば運用できます。
まとめ
AIエージェントの artifact retention は、ストレージ節約の話ではありません。レビュー、監査、削除、事故調査を同時に成立させるための設計です。
最低限、次の5点を決めます。
- raw log ではなく review artifact を残す
- memory、audit log、artifact store を分ける
- data class と retention tier を run 単位で持つ
- raw output は短期保存し、summary と pointer を残す
- incident hold は通常runと別に扱う
AIエージェントの作業は、残さなければ説明できません。しかし残しすぎると、説明責任のためのログが新しいリスクになります。成果物、根拠、検証、判断、監査 pointer を分けて、小さく残す。これが一番現実的な出発点です。