誰がアシスタントにそれを頼んだか
監査記録は、誰がいつ何をしたかを、非公開の文章を残さずに伝えます。問題が起きたとき、全員のメッセージを写し取っていなくても、何があったかを再現できる必要があるからです。
火曜日に、ツールが奇妙な要求を断ります。金曜日に、誰かが理由を尋ねます。利用者ID、ツール名、結果、時刻の記録があれば答えられます。チャットの写しでも答えられますが、それは負担にもなります。
このレッスンのゴール
メモ
非公開の内容を含まない監査記録を書き、保存期間が終わったら削除することができる。
重要語句
| ことば | いみ | れい |
|---|---|---|
| 監査記録 | 誰が、何を、いつ、どんな結果でしたかの記録 | |
| 保存期間 | 記録を残しておく長さ | |
| パージ | 期限を過ぎた記録を削除すること | |
| 偽の時計 | テストが時間を操れるよう、コードが決める時刻 | |
| 識別子 | 名前を出さずに人を表すコード | u-17 |
学生が入力するセルは、このプレビューでは空白です。
誰が、何を、いつを記録する
アシスタントが何かをするごとに、小さな記録を一つ書きます。フィールドは、決まった一覧だけにします。プロンプトや返信のような、それ以外のものは、保存の前に捨てます。
人は名前ではなく識別子で表します。記録は追加するだけで、書き換えません。そうすれば、ログを信頼できます。
例: 一つの監査記録
| フィールド | 例 | 入れる理由 |
|---|---|---|
| at | 時刻 | いつ起きたか |
| user | u-17 | 誰が頼んだか。名前は出さない |
| action | read_note | アシスタントが何をしたか |
| outcome | 許可 | 検査がどう判断したか |
| tokens | 120 | いくらかかったか。数として |
| (残さない) | プロンプトの文章 | 個人情報を含むことがある |
学生が入力するセルは、このプレビューでは空白です。
役に立つ間だけ記録を残す
どの記録にも理由があり、その理由は終わります。種類ごとに保存期間を決めます。チャットの文章は短く、監査記録は長くします。そのあと、古いものを削除します。
法的な義務は、国や分野で異なります。数字を決める前に、自分に当てはまるものを確かめてください。
監査の処理を書く(1)
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const DAY = 24 * 60 * 60 * 1000;' 'let now = Date.UTC(2026, 0, 1);' 'const allowed = [\"user\", \"action\", \"outcome\", \"tokens\"];' 'const log = [];' '' '// 監査記録には、誰が、何を、いつを残す。文章は決して残さない。' 'function record(fields) {' ' const clean = { at: now, id: log.length + 1 };' ' for (const key of allowed) {' ' if (key in fields) clean[key] = fields[key];' ' }' ' log.push(clean);' ' return clean;' '}' > audit.js"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
監査の処理を書く(2)
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'record({ user: \"u-17\", action: \"read_note\", outcome: \"許可\", tokens: 120, prompt: \"こんにちは、さくらです\" });' 'now = now + 20 * DAY;' 'record({ user: \"u-18\", action: \"run_shell\", outcome: \"拒否\", tokens: 0 });' 'now = now + 20 * DAY;' 'record({ user: \"u-17\", action: \"add_numbers\", outcome: \"許可\", tokens: 60 });' 'console.log(\"残したフィールド: \" + Object.keys(log[0]).join(\", \"));' 'console.log(\"プロンプトを保存した: \" + (\"prompt\" in log[0]));' >> audit.js"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
監査の処理を書く(3)
docker exec -w /home/node/project agent sh -c "printf '%s\n' '// 保存期間: 記録を30日間残し、その後は削除する。' 'const KEEP = 30 * DAY;' 'function purge(list, at) {' ' return list.filter(function (item) { return at - item.at <= KEEP; });' '}' 'const left = purge(log, now);' 'console.log(\"前: \" + log.length + \"、後: \" + left.length);' 'console.log(\"残ったID: \" + left.map(function (item) { return item.id; }).join(\", \"));' >> audit.js"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
監査の処理を実行
docker exec -w /home/node/project agent node audit.jsここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
スクリプトの出力
| 行 | 意味 |
|---|---|
| 残したフィールド: at, id, user, action, outcome, tokens | prompt のフィールドは捨てられた |
| プロンプトを保存した: false | 非公開のものはログに入らなかった |
| 前: 3、後: 2 | 最初の記録は40日前で、上限は30日 |
| 残ったID: 2, 3 | 新しい二つの記録が残る |
学生が入力するセルは、このプレビューでは空白です。
配列が本物の保存先の代わり
スクリプトはログを配列に入れ、偽の時計を手で進めます。本物のシステムは、バックアップとアクセス制御のあるデータベースと、パージする定期ジョブを使います。
バックアップも関係します。データベースから消した記録は、バックアップも期限切れにならない限り、先月のバックアップに残ります。
よくある間違い
注意
たくさん記録するほど安全だと考える人が多くいます。すべてのプロンプトを残すログは、それ自体が個人情報の保管庫で、そのように守り、削除する必要があります。質問に答えるのに要るフィールドだけを記録してください。