AIエージェントを組織に入れるとき、一番危ないのは「secret を貼らない」という注意書きだけで安心することです。実際の事故は、API key そのものよりも、顧客データ、未公開の仕様、社内文書、MCP から取った検索結果、ログ、生成した成果物が同じ context や同じ保存先に混ざるところから起きます。
この記事では、AIエージェントの データ境界 を扱います。1回の run に何を渡すかは AIエージェントのコンテキスト設計ガイド、許可済み権限の棚卸しは AIエージェント権限棚卸し設計ガイド、MCP server の審査台帳は MCP サーバーカタログ設計ガイド、secret の扱いは AIエージェント secret handling 設計ガイド に分けます。
今回の論点は、どのデータを同じ run、同じ tool、同じログ、同じ成果物に混ぜてよいかです。
先に結論: データ境界は入力禁止リストではない
データ境界を「個人情報禁止」「機密情報禁止」だけで表現すると、現場ではすぐ壊れます。AIエージェントは単に文章を読むだけでなく、検索し、変換し、ファイルを書き、MCP tool を呼び、ログを残し、PR やチケットへ成果物を投稿するからです。
私なら、最初にデータを次の5つに分けます。
| 区分 | 例 | 基本方針 |
|---|---|---|
| public | 公式docs、公開issue、公開仕様 | 通常 run に渡してよい |
| internal | 社内wiki、設計メモ、private repo | 出力先と引用範囲を制限する |
| customer | 顧客名、契約情報、問い合わせ本文 | 原則は要約・匿名化して渡す |
| regulated | 個人情報、医療、金融、法務記録 | 専用 lane と owner 承認へ逃がす |
| secret | API key、token、cookie、秘密鍵 | agent context に入れない |
secret handling は重要ですが、secret だけを見ても不十分です。customer data と internal data は、単体では読ませてもよい場面があります。ただし、それを別顧客の成果物、公開PR、外部SaaS、長期memory、監査ログに混ぜた瞬間にリスクが変わります。
既存記事との役割分担
このテーマは近い記事が多いので、責務を先に切ります。
| 近いテーマ | 扱うこと | この記事で扱うこと |
|---|---|---|
| context engineering | run に渡す情報の選別 | データ分類ごとの混在可否 |
| permission review | 許可済み tool / scope の棚卸し | データ区分に応じた利用範囲 |
| MCP server catalog | server、scope、risk の台帳 | MCP resource が返すデータの境界 |
| audit log | 実行後に何を残すか | raw data をログへ残してよいか |
| secret handling | token や credential の扱い | customer / internal data の混在防止 |
つまり、データ境界は「何を読めるか」だけではありません。読んだものを、どこへ渡し、どこへ保存し、どの成果物に混ぜてよいかを決める層です。
私がSEO automationや社内向けの調査 run を設計するときも、最初に詰まるのはモデル性能ではありません。公開docs、Search Consoleの集計、private repo、問い合わせの抜粋、MCP tool result を同じ作業ログへ入れてよいのか、後から説明できる形で分けられているかです。ここを曖昧にすると、最終成果物のレビューより先に、どの情報を見たのかの棚卸しで止まります。
run の前に data boundary packet を作る
実務では、依頼文をそのまま agent に渡す前に data_boundary_packet を作ります。これは複雑なポリシーエンジンでなくてもよく、最初は YAML で十分です。
data_boundary_packet:
run_id: 20260723-customer-faq-refresh
owner: support-ops
data_classes:
input:
- internal
- customer_redacted
retrieval:
- public
- internal
forbidden:
- secret
- regulated_raw
allowed_outputs:
- private_pr
- internal_ticket
forbidden_outputs:
- public_blog
- external_saas_without_approval
log_policy:
raw_payload: forbidden
summary: allowed
hash: allowed
approval_required_when:
- customer_raw_data_needed
- data_class_changes
- output_destination_changes
ここで重要なのは、入力だけでなく output destination まで持つことです。同じ要約でも、private PR に置くのと公開ブログに置くのでは意味が違います。AIエージェントの安全運用では、データ分類と出力先をセットで見る必要があります。
MCP resource は data source として扱う
MCP を使うと、AIエージェントは社内ドキュメント、CRM、チケット、データベース、analytics へ自然に届きます。ここを「tool が読めたから context に入れてよい」と扱うと危険です。
MCP 公式docsは、MCPを外部システムのデータソースやtoolへ接続する標準として説明しています。つまり MCP resource や tool result は、ただの補助テキストではなく、出所と利用条件を持つデータです。OpenAI Agents SDK の guardrails も input / output / tool invocation のそれぞれで検査点が分かれるため、MCP result を受け取った直後の境界チェックを独立させた方が運用しやすいです。
MCP server ごとに、最低でも次を台帳化します。
| 項目 | 例 | 判断 |
|---|---|---|
source_owner | sales ops / platform | データ境界の責任者 |
data_class | internal / customer / regulated | run に混ぜてよい範囲 |
tenant_scope | single tenant / multi tenant | 別顧客への混入リスク |
tool_output_policy | summary only / raw allowed | context と log の粒度 |
export_allowed | false / private only / public allowed | 成果物への転記可否 |
特に multi-tenant の MCP server は慎重に扱います。tenant_id を tool argument で受け取る設計なら、agent が別 tenant を指定できないように server 側でも検査します。prompt で「A社のデータだけ」と書くだけでは、実行時の境界にはなりません。
境界を越える承認条件を固定する
データ境界は、すべてを禁止するためのものではありません。業務上、customer data を読まないと解けない仕事もあります。その場合は、境界を越える条件を明文化します。
| 境界越え | 例 | 必要な承認 |
|---|---|---|
| internal -> public | 社内設計を公開記事へ要約 | owner が公開可能範囲を確認 |
| customer -> internal | 問い合わせ本文を不具合調査へ利用 | support owner が目的を確認 |
| customer -> external | CRM から外部SaaSへ送信 | data owner と security review |
| regulated -> any | 個人情報や規制対象の処理 | 専用 lane、DPA、監査要件 |
| raw -> log | 生データを監査ログに保存 | 原則禁止。必要時は隔離保管 |
承認リクエストには raw payload を貼りません。必要なのは、分類、目的、出力先、保存期間、代替案です。raw data が必要な場合は、アクセス制御された原本の location と参照権限だけを渡します。
ログと成果物は別の境界を持つ
AIエージェントの運用では、作業中の context よりログの方が長く残りがちです。だから、ログは「後で見るから全部残す」ではなく、別の境界として設計します。
agent_log_policy:
store:
- run_id
- data_classes_seen
- tool_names
- approval_ids
- output_locations
summarize:
- customer_request
- internal_document_excerpt
hash_only:
- raw_file_path
- source_record_id
never_store:
- secret
- raw_customer_payload
- regulated_raw_data
成果物も同じです。PR、チケット、Slack 投稿、社内wiki、公開ブログでは許容される情報が違います。final answer に「検証済み」と書く前に、どの data class がどの output に出たかを確認します。
Claude Code の security docs は、read-only 操作を基本にしつつ、ファイル編集やコマンド実行のような追加操作で明示的な許可を求める設計を説明しています。ただし、read-only で読める情報でも、ログやPR本文へ転記した瞬間に別のリスクになります。権限の許可とデータの持ち出し可否は、別のチェックとして扱います。
実装するなら境界チェックを3回入れる
最初から完全な DLP を作る必要はありません。小さく始めるなら、次の3箇所にチェックを入れます。
- intake: 依頼時点で data class と output destination を決める
- tool result: MCP や検索結果を context に入れる前に要約・マスクする
- final output: PR、チケット、公開文書へ出す前に混在を確認する
例として、run 完了前に次のようなチェックリストを通します。
data_boundary_check:
before_finish:
- "data_classes_seen are recorded"
- "no secret or raw regulated data in context"
- "customer data is redacted or linked by controlled record id"
- "MCP outputs are summarized before logs"
- "final output destination matches allowed_outputs"
- "boundary escalation is attached when data class changed"
この程度でも、危険な混在はかなり減ります。完璧な分類より、run ごとに「何を見たか」「どこへ出したか」「越境したか」を説明できることが重要です。
判断基準: 迷ったら同じ run に混ぜない
最後に、私が使っている判断基準を置きます。
| 判断 | OK | NG |
|---|---|---|
| 顧客Aの情報で顧客Aの回答を作る | redacted summary を使う | raw log を丸ごと貼る |
| 社内仕様を実装に使う | private repo 内で参照する | 公開PR本文に転記する |
| MCP search を使う | tool result を要約して使う | raw response を memory に保存する |
| 障害調査をする | record id と hash を残す | 個人情報入りログを監査基盤に複製する |
| ナレッジ化する | owner 確認後に一般化する | 顧客固有の表現をブログへ流用する |
迷ったときは、同じ run に混ぜない方がよいです。別 run、別 worktree、別 output、別 owner 承認に分ける。AIエージェントは作業を速くしますが、データ境界まで自動で守ってくれるわけではありません。