マガジン

AIエージェントの操作記録に何を残すか:あとで追える作業ログの項目設計

AIを使いこなす

Claudeで執筆し、GPTで自動校閲・修正しています。

紙製フォルダと変更前後のカード、空のチェック欄を並べた机上
記事の内容をもとに制作したAI生成イメージです。実際の製品画面や検証結果の写真ではありません。

結論から言うと、最小構成は「1回の操作につき1行、12項目前後」です。軸になるのは次の5つです。 • 誰が何を依頼したか(依頼) • エージェントがなぜその操作を選んだか(判断) • どのツールをどんな引数で呼んだか(ツール呼び出し) • 何が起きたか(結果) • 誰が許可したか(承認者) この5つを同じ依頼ID(request_id)でつなげば、「あの変更はどの依頼から始まり、誰が通したのか」を後から逆にたどれます。入出力の全文は別に保管し、ログ行には要約と参照先だけを置くのが、多すぎず少なすぎない落としどころです。 以下は編集上の設計案です。サンプル行は説明用の例で、実際に動かして得た記録ではありません。

この記事の目次
  1. 先に公式ツールが何を出してくれるかを知る
  2. 最小のログ項目表
  3. サンプル行(説明用の例)
  4. 残す・参照にする・残さないの判断表
  5. エージェントに書かせる依頼文
  6. 運用で崩れやすい点

先に公式ツールが何を出してくれるかを知る

自前で項目を決める前に、使っているエージェント製品が標準で何を記録するかを確認します。ここがずれると二重に作ることになります。

Claude Codeのフックのリファレンス(2026年10月28日に閲覧)では、ツール呼び出しの前後で動くフックに、session_id、prompt_id、tool_name、tool_input、tool_use_id、cwd、permission_modeなどがJSONで渡されると説明されています。成功後のフックにはtool_responseも含まれます。prompt_idはOpenTelemetryのイベントと突き合わせる用途だと書かれています。

監視(OpenTelemetry)のドキュメントには、claude_code.user_prompt、claude_code.tool_decision、claude_code.tool_resultなどのイベントがあります。tool_decisionには承認か拒否か(decision)と、その出どころ(source:設定、フック、ユーザーの許可など)が入ります。プロンプト本文やツールの引数・出力は、既定では伏せられます。出すにはOTEL_LOG_USER_PROMPTSやOTEL_LOG_TOOL_DETAILSなどの設定を明示的に有効にする作りです。

つまり、製品側のログで取れるのは「呼び出し・許可の経路・成否」が中心です。一方で「依頼の目的」「なぜその操作を選んだか」「承認した人の役割」は、運用側で足す必要があります。ほかの製品を使う場合も、同じ観点で一覧を見比べてください。

最小のログ項目表

次の表が提案する項目です。右端に、Claude Codeの上記ドキュメントで確認できる近い項目を添えました。「なし」は、その資料から該当項目を確認できなかったという意味で、製品に機能がないという断定ではありません。

  • ts、内容:発生時刻(ISO 8601、タイムゾーン付き)、区分:時間、製品側の近い項目:event.timestamp
  • request_id、内容:1つの依頼を束ねるID、区分:依頼、製品側の近い項目:prompt_id / prompt.id
  • session_id、内容:作業セッションのID、区分:依頼、製品側の近い項目:session_id
  • event、内容:request / decision / tool_call / result / approval のいずれか、区分:種別、製品側の近い項目:イベント名で区別
  • request_summary、内容:依頼内容の1文要約と依頼者、区分:依頼、製品側の近い項目:プロンプト本文(既定は非表示)
  • reason、内容:操作を選んだ理由(エージェント自己申告の1〜2文)、区分:判断、製品側の近い項目:なし
  • tool、内容:ツール名、区分:ツール呼び出し、製品側の近い項目:tool_name
  • target、内容:触る対象(ファイルパス、ID、URL)、区分:ツール呼び出し、製品側の近い項目:tool_inputの一部
  • effect、内容:read / write / delete / external_send の別、区分:ツール呼び出し、製品側の近い項目:なし
  • status、内容:success / error / denied、区分:結果、製品側の近い項目:success、decision
  • result_summary、内容:結果の要約と件数、区分:結果、製品側の近い項目:tool_response
  • approver、内容:承認した人または承認ルール、区分:承認者、製品側の近い項目:source(経路のみ)
  • ref、内容:全文の保管先への参照、区分:参照、製品側の近い項目:transcript_path

押さえたいのは、reasonとeffectとapproverの3つです。この3つは製品の標準ログだけでは薄くなりがちで、後から「なぜ」「どれほど危険な操作だったか」「誰の責任で通ったか」を判断するときの決め手になります。

reasonはモデル自身が書いた説明であり、内部動作を正確に写した証拠とは限りません。あくまで「当時の意図の目安」として扱い、事実の確認はtool・target・statusで行います。

サンプル行(説明用の例)

経費精算の領収書フォルダのファイル名を整える、という架空の依頼です。1行が1イベントで、JSON Lines形式にしています。

json
{"ts":"2026-10-28T10:00:02+09:00","request_id":"r-001","session_id":"s-12","event":"request","request_summary":"領収書フォルダのファイル名を日付_店名に統一(依頼者:経理A)"}
{"ts":"2026-10-28T10:00:09+09:00","request_id":"r-001","session_id":"s-12","event":"tool_call","tool":"list_files","target":"/receipts/2026-09","effect":"read","reason":"変更前に対象ファイルと現在の名前を把握するため","status":"success","result_summary":"42件を取得"}
{"ts":"2026-10-28T10:01:30+09:00","request_id":"r-001","session_id":"s-12","event":"decision","reason":"42件中3件は店名が読み取れず、推測で改名すると誤りの恐れがあるため対象外にする","effect":"read"}
{"ts":"2026-10-28T10:02:11+09:00","request_id":"r-001","session_id":"s-12","event":"approval","tool":"rename_files","target":"/receipts/2026-09(39件)","effect":"write","approver":"経理A(画面で個別承認)","status":"approved"}
{"ts":"2026-10-28T10:02:15+09:00","request_id":"r-001","session_id":"s-12","event":"result","tool":"rename_files","effect":"write","status":"success","result_summary":"39件改名、3件スキップ、旧名対応表を保存","ref":"logs/r-001/rename_map.csv"}

この5行だけで、依頼の中身、3件を除外した判断、書き込み前の承認者、結果、元に戻すための手がかりまで追えます。逆に、各行にファイル一覧の全文を入れていないので、行は短いままです。

残す・参照にする・残さないの判断表

「多すぎる」を防ぐには、項目ごとに扱いを決めておきます。

  • 依頼の要約、ツール名、対象、成否、扱い:ログ行に直接残す、理由:検索と集計に使うため
  • ツールの出力全文、差分、変更前後の対応表、扱い:別保管してrefで参照、理由:行を肥大化させず、権限も分けられる
  • 内部の長い思考過程、扱い:原則残さない、理由:量が多く、事実確認にも向かない。理由は短い自己申告に絞る
  • パスワード、APIキー、セッショントークン、接続文字列、扱い:絶対に残さない、理由:漏えい時の被害が大きい
  • 個人情報(氏名、口座、健康情報など)、扱い:伏せるかIDに置き換える、理由:必要最小限に抑える

最後の2行は、OWASPのLogging Cheat Sheetが、セッション識別値、認証パスワード、暗号鍵などの秘密情報や、個人識別情報・健康情報・接続文字列をログに含めないよう挙げている点に沿っています。同資料は、時刻・場所・主体・内容(when/where/who/what)を記録すること、ログの改ざんや削除を検知できる仕組みを持つこと、閲覧権限を絞ることも述べています。

Claude Codeが既定でプロンプトや引数を伏せるのも同じ発想です。逆に、全文を出す設定を有効にするなら、保管先のアクセス権と保存期間を先に決めてください。個人情報を含むログの扱いは、組織の規程と適用される法令(日本なら個人情報保護法など)に左右されます。具体的な保存期間は自社の担当部門と確認してください。

エージェントに書かせる依頼文

ログをエージェント自身に書かせる場合の指示文の例です。製品側のフックで機械的に取れる項目(時刻、ツール名、成否)は、この指示ではなくフックに任せるほうが確実です。

作業ごとに、次のルールで作業ログ(JSON Lines)に1行追記してください。
- 書き込み・削除・外部送信の前に、必ず event=decision の行を書く。
  reason には「なぜこの操作が必要か」を1〜2文で書く。
- 人の承認が必要な操作は、承認が出るまで実行しない。
  承認後に event=approval の行を書き、approver に承認者を記録する。
- パスワード、キー、トークン、個人名・口座番号は書かない。
  必要なら「[伏せ字]」またはIDで表す。
- 出力全文は書かず、result_summary に件数と成否だけを書き、
  詳細は ref にファイルパスで示す。
- 分からないことは推測で埋めず、reason に「不明」と書く。

人が確認するポイントは3つです。approval行がないwriteやdeleteがないか。reasonが空や定型文ばかりになっていないか。ログに秘密情報が混ざっていないか。これを週1回、数十行だけ抜き取って見るだけでも、設計の穴に気づけます。

運用で崩れやすい点

  • request_idが途中で切れる:複数のエージェントやサブエージェントが動くと、IDが引き継がれないことがあります。Claude Codeのフックにはagent_idやagent_typeも渡されるとされているので、同様の項目を足すと切り分けやすくなります。
  • 承認が「設定で自動許可」になっている:approverに人名が入らないのは正常です。その場合は「ルール名」を入れ、誰がそのルールを作ったかを別途記録します。
  • ログを書く権限をエージェントが持つ:エージェントが自分のログを書き換えられると、追跡の意味が薄れます。追記専用にするか、保管先を分けてください。

まずは上の13項目からreasonが不要な読み取り操作の行を省く形で始め、実際に振り返って「足りなかった項目」だけを足すのが現実的です。

出典・参考資料