ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

LLM Agent敏感数据防护:全链路脱敏与工具调用安全实践

LLM Agent敏感数据防护:全链路脱敏与工具调用安全实践 你在开发 LLM Agent 时有没有遇到过这种情况用户问“帮我查一下这个用户的手机号”Agent 调用了 CRM 工具工具返回了真实手机号模型把它原样带到了回答里。等你打开后台日志发现手机号、邮箱甚至内部接口的 API Key 全都记录在案。如果这些日志被同步到第三方日志平台或者模型本身是云端 API那你甚至无法判断这条数据到底流转到了哪里。Agent 工作流和传统应用有一个本质区别Prompt 是会被“执行”的。传统应用里数据库查询结果只存在于应用内存中而 Agent 场景下工具返回的每一条数据都会被序列化进 Model Context再经过模型生成、日志记录、会话持久化等多个环节。敏感数据一旦进入上下文就失去了物理控制权它可能出现在 Token 日志、缓存、第三方 Embedding 服务、以及模型供应商的训练管道里。所以要解决的不是“在某个环节加一次脱敏”而是要在 Agent 的工具调用链路上建立一套完整的数据边界机制。本文会从数据暴露路径开始分析再给出一个可直接落地的 Python 实现包含脱敏模块、工具调用拦截、凭据注入隔离和日志审计最后补充生产环境下最容易踩的坑。1. 为什么 Agent 工作流里的敏感数据问题比传统应用更危险很多团队最早对 LLM 应用的预期是“智能问答”认为只要把工具返回结果传给模型让模型做总结就可以了。但实际接入后会发现Agent 的数据流路径比传统 API 服务复杂得多。传统应用中一次请求会经历客户端 - 接口层 - 服务层 - 数据库再沿原路返回。数据虽然经过多个模块但每个模块的职责边界清楚开发者可以用参数校验、脱敏注解、数据库权限等手段控制字段级可见性。数据不会平白无故地被复制到另一个系统。Agent 工作流则不同。以最常见的 ReAct 模式为例一次工具调用需要经历以下环节用户输入被拼接进 Prompt。模型根据工具 Schema 生成结构化参数。参数被解析并执行真实工具。工具返回结果被序列化成文本追加到上下文。模型根据上下文生成最终回复。整个对话历史含工具返回被持久化。这里存在两个方向的数据流动上行泄露用户输入的 Prompt 中包含 API Key、Token、业务机密模型将其作为工具参数直接传给外部系统。下行泄露工具返回的真实数据进入 Context被模型复述、被日志记录、被写入会话表。更麻烦的是LLM 对“脱敏”并没有内生理解。你可以在 Prompt 里写“不要输出手机号”但如果工具返回结果已经包含手机号模型在生成时仍可能根据上下文模式推断并复述出来。这个行为不稳定不同模型、不同温度参数下表现差异巨大。所以不能把敏感数据治理寄托在模型自律上必须从机制上让敏感数据在进入上下文之前就被替换或截断。这也是本文全部方案的第一原则。2. Agent 工作流中敏感数据的五条主要暴露路径在实际项目中敏感数据泄露很少来自单一环节而是多个薄弱点叠加。我习惯把暴露路径拆成五类先梳理清楚再谈防护。2.1 Prompt 拼接层这是最容易忽视的入口。很多开发者会在系统 Prompt 中写入内部系统名称、数据库表结构、第三方服务的 API Key目的是让模型“更懂业务”。但问题在于系统 Prompt 通常会被完整记录到日志平台也会被发送给模型服务商。任何写入 Prompt 的敏感信息本质上是主动上交。2.2 Tool Call 参数层模型在生成工具调用时会根据用户输入填充参数。如果用户输入本身是“用这个 key 调用接口”而 Agent 没有做参数校验这个 key 就会被当作普通参数传入工具。更隐蔽的是工具 Schema 里的字段名如果出现authorization、api_key模型会倾向于从上下文中“找”一个值填进去哪怕这个值来自无关的历史对话。2.3 工具返回结果层这是最常见的数据暴露源。工具返回结果通常是一个结构体或 JSON 串其中可能包含数据库字段的完整值。开发者为了省事经常直接在 Prompt 里让模型“根据这个 JSON 回答用户”结果 JSON 中的所有字段都被模型引用。2.4 对话历史持久化层Agent 应用基本都会使用 Memory 模块把对话历史存入数据库或向量库。如果工具返回结果在被模型使用之前没有被脱敏那么持久化的对话历史中就会包含真实手机号、邮箱、地址等数据。这些数据后续还可能与用户 Embedding 向量一起进入检索和训练流程。2.5 外部模型服务层如果 Agent 调用的是云端模型 API那么 Prompt 和工具返回内容都会发送到模型服务商。无论服务商的数据协议如何从企业数据治理角度这些数据已经离开内部网络边界。对于高敏业务这一层通常意味着合规风险。暴露路径典型数据主要风险控制时机Prompt 拼接层API Key、内部地址、表结构日志与模型服务商构造 Prompt 之前Tool Call 参数层用户输入中的密钥、Token错误工具调用工具执行之前工具返回结果层手机号、邮箱、地址、ID上下文复述与日志返回给模型之前对话历史持久化层全部上下文快照二次存储泄露落库之前外部模型服务层全量 Prompt 与输出合规与跨境传输架构选型阶段这五条路径不是相互独立的。例如工具返回结果未脱敏会导致对话历史持久化层被污染Prompt 拼接层写入了密钥又会让 Tool Call 参数层更容易被模型误用。所以治理方案必须覆盖全链路而不是只做“输出端脱敏”。3. 核心设计原则数据最小化与敏感操作本地化在动手写代码之前需要先建立一套设计原则。这些原则比具体实现更重要因为实现可以换语言、换框架但原则决定了整个架构的数据边界。3.1 原则一敏感数据不进 Prompt能不进就不进这句话听起来像废话但做起来远比想象中难。很多 Agent 框架默认会把工具执行结果、历史消息、用户资料全部塞进上下文。你要做的不是“让模型聪明地处理敏感数据”而是从机制上减少进入上下文的敏感字段数量。实现手段包括工具返回结果只保留模型回答所需的最小字段。对敏感字段做 value masking用[PHONE]替代真实值。对超长文本做截断避免把大段内部数据塞进上下文。3.2 原则二工具调用使用凭据引用不传密钥原文Agent 工具通常需要调用内部 API这时需要认证凭证。很多团队的实现是把 Token 写在环境变量里然后在工具函数里直接os.getenv()读取这是正确的做法。错误做法是把 Token 放进 Prompt让模型“记住”并在调用时传给工具。正确的凭据模型是工具函数自己从环境变量或密钥管理服务读取凭据LLM 只知道“这个工具可以查询订单”并不知道也无需知道凭据值。3.3 原则三出参脱敏谁返回谁负责每个工具的返回值都应当被看作一次数据出站。工具函数或中间层必须有字段级脱敏能力而不能依赖模型“不读”或“不提”。推荐做法是每个工具声明自己返回结果中的敏感字段名单由统一拦截器对名单字段执行脱敏。3.4 原则四审计不审原文审计操作在传统应用中审计日志往往包含请求体和响应体。但在 Agent 场景这样做会直接复制敏感数据到日志系统。更安全的方式是记录“谁在什么时间调用了哪个工具”。记录工具参数中非敏感部分。对敏感数据只记录 Hash 值。不记录 Prompt 原文或对 Prompt 做同级别脱敏。3.5 两组容易混淆的概念第一组是脱敏Masking与加密Encryption。脱敏是“替换”把真实值替换成占位符模型可以用占位符完成格式化输出但无法获取真实值。例如把手机号13800138000替换成[PHONE]。加密是“变换”密文仍携带全部信息只是没有密钥无法解读。Agent 上下文里绝对不要出现加密后的敏感密文因为模型会把密文当作普通文本处理极有可能原样输出或截断导致下游系统无法解密。第二组是隐私数据PII与凭据Credentials。隐私数据通常是业务字段例如手机号、邮箱、身份证号。凭据是访问系统的钥匙例如 API Key、Token、密码。凭据的敏感级别高于 PII一旦泄露攻击者可以直接重置你的系统权限。两者的处理策略也有差异PII 可以做局部遮蔽比如显示后四位凭据则必须完全隔离绝不能进入上下文。4. 环境准备与项目结构为了演示完整链路我会用一个最小 Python 项目来展示脱敏、工具调用拦截、凭据注入和日志过滤。项目不使用重量级框架核心逻辑可迁移到 LangChain、LlamaIndex 或自研 Agent 框架中。4.1 运行环境Python 3.10 及以上操作系统macOS / Linux / Windows 均可代码不依赖系统特性第三方依赖无需安装仅使用 Python 标准库实际项目中你可能使用 FastAPI、LangChain 等框架但示例中的逻辑可以原样抽离。4.2 项目结构sensitive-guard-agent/ ├── agent.py # Agent 上下文装配与安全工具调用入口 ├── masker.py # 脱敏规则与脱敏器 ├── tools.py # 工具实现与凭据注入 ├── audit_logger.py # 日志脱敏过滤器 ├── .env.example # 环境变量示例 └── README.md为了做到“可复制、可运行”项目刻意保持最小依赖。真实的 Agent 项目还会包含模型调用层、路由层、记忆层但安全边界代码的落点是一样的在一切数据进入模型上下文之前经过一个安全中间层。5. 代码实现SensitiveGuard Agent 完整示例这一节是核心。我会从脱敏器开始逐步构建整个安全链路。建议你按文件顺序创建代码最后运行验证。5.1 数据脱敏模块 masker.py脱敏模块采用“规则引擎”模式每个规则包含一个正则表达式、一个替换占位符和一个开关。这种设计的好处是你可以按业务需求动态调整规则而不是在代码里散落正则。# masker.py import re from typing import Any, Dict, Iterable, List, Optional class MaskRule: 单条脱敏规则。 def __init__(self, name: str, pattern: str, replacement: str [MASKED]): self.name name self.pattern re.compile(pattern) self.replacement replacement def apply(self, text: str) - str: return self.pattern.sub(self.replacement, text) # 默认内置规则可按业务扩展 DEFAULT_RULES [ MaskRule(email, r[\w.-][\w-]\.[\w.-], [EMAIL]), MaskRule(phone, r(?!\d)1[3-9]\d{9}(?!\d), [PHONE]), MaskRule(id_card, r\b\d{17}[\dXx]\b, [ID_CARD]), MaskRule(credit_card, r\b(?:\d[ -]*?){13,16}\b, [CARD]), ] class Masker: 通用脱敏器支持文本级脱敏和字段级脱敏。 def __init__(self, rules: Optional[Iterable[MaskRule]] None): self.rules list(rules) if rules is not None else DEFAULT_RULES def mask_text(self, text: str) - str: for rule in self.rules: text rule.apply(text) return text def mask_dict( self, data: Dict[str, Any], fields: Optional[List[str]] None, remove_fields: Optional[List[str]] None, ) - Dict[str, Any]: 脱敏字典数据。 :param fields: 需要脱敏的字段名列表为 None 时对所有字符串值执行全量脱敏 :param remove_fields: 需要整体删除的字段名列表适合内部调试字段 masked {} for key, value in data.items(): if remove_fields and key in remove_fields: continue should_mask fields is None or key in fields if should_mask and isinstance(value, str): masked[key] self.mask_text(value) else: masked[key] value return masked关键点说明mask_text用于处理任意字符串例如日志消息、Prompt 片段。mask_dict用于处理工具返回的结构化数据。fields参数可以让调用方精确声明哪些字段需要脱敏。remove_fields用于删除内部字段例如调试用的_debug_api_key这类字段绝不能进入上下文。5.2 工具注册与凭据注入 tools.py工具层有两个安全责任第一凭据只从环境变量注入第二工具返回结果必须声明敏感字段。# tools.py import os from typing import Any, Callable, Dict from masker import Masker def get_secret(secret_key: str) - str: 凭据只从环境变量注入不允许由 LLM 传入。 value os.getenv(secret_key) if not value: raise RuntimeError(fmissing required secret: {secret_key}) return value def query_user(user_id: str) - Dict[str, Any]: 模拟 CRM 用户查询。真实场景中会请求内部服务。 return { user_id: user_id, email: aliceexample.com, phone: 13800138000, id_number: 110101199001011234, level: vip, } def query_order(order_id: str) - Dict[str, Any]: 模拟订单查询。该工具需要访问内部订单服务使用密钥从环境变量注入。 # 真实业务中这里会用 get_secret 获取密钥后调用 HTTP API api_key get_secret(ORDER_SERVICE_API_KEY) # 仅做演示返回绝不把 api_key 放入返回值 return { order_id: order_id, buyer_name: 张三, address: 北京市朝阳区某街道 1 号, tracking_number: SF1234567890, amount: 299.00, } # 工具注册表LLM 只能看到工具名和描述看不到实现细节 TOOL_REGISTRY: Dict[str, Callable[..., Any]] { query_user: query_user, query_order: query_order, } # 每个工具的敏感字段声明这是安全边界的关键配置 TOOL_SENSITIVE_FIELDS: Dict[str, list] { query_user: [email, phone, id_number], query_order: [buyer_name, address, tracking_number], }这里有个值得关注的设计query_order内部调用了get_secret(ORDER_SERVICE_API_KEY)但 LLM 完全感知不到这个密钥的存在。外界需要调工具时只需提供order_id密钥在工具内部注入。你需要注意.env.example文件# .env.example ORDER_SERVICE_API_KEYplease_change_me5.3 工具调用拦截器与安全上下文装配 agent.pyagent.py是整个安全链路的中枢。它做三件事过滤 LLM 传入参数中的敏感键、调用工具并脱敏返回值、把脱敏后的结果拼进模型上下文。# agent.py import json from typing import Any, Dict, List from masker import Masker from tools import TOOL_REGISTRY, TOOL_SENSITIVE_FIELDS class ToolCallError(Exception): pass # 模型无论如何都不应该通过参数传入这些字段 SENSITIVE_PARAM_KEYS {api_key, token, authorization, secret, password} def sanitize_tool_args(tool_name: str, args: Dict[str, Any]) - Dict[str, Any]: 工具入参清洗移除一切敏感键。 safe_args {} for key, value in args.items(): if key.lower() in SENSITIVE_PARAM_KEYS: # 这里打点记录拦截事件用于审计 print(f[SECURITY] blocked sensitive param {key} for tool {tool_name}) continue safe_args[key] value return safe_args def safe_tool_call(tool_name: str, raw_args: Dict[str, Any], masker: Masker) - str: 安全工具调用 1. 清洗入参 2. 执行真实工具 3. 按声明字段脱敏 4. 序列化为 JSON 字符串供模型使用 if tool_name not in TOOL_REGISTRY: raise ToolCallError(funknown tool: {tool_name}) safe_args sanitize_tool_args(tool_name, raw_args) result TOOL_REGISTRY[tool_name](**safe_args) sensitive_fields TOOL_SENSITIVE_FIELDS.get(tool_name, []) masked_result masker.mask_dict(result, fieldssensitive_fields) # 双重保险任何名称类似密钥的字段一律删除 FINAL_REMOVE_KEYS {api_key, token, authorization, secret, password} masked_result { k: v for k, v in masked_result.items() if k.lower() not in FINAL_REMOVE_KEYS } return json.dumps(masked_result, ensure_asciiFalse, indent2) def build_agent_context( system_prompt: str, tool_calls: List[Dict[str, Any]], masker: Masker, ) - str: 把多轮工具调用结果组装成模型上下文。 这里的核心目标进入上下文的每一个字段都已经过安全过滤。 context_parts [system_prompt] for call in tool_calls: tool_name call[tool] args call.get(args, {}) context_parts.append( f[tool_call] {tool_name} args{json.dumps(args, ensure_asciiFalse)} ) try: tool_result safe_tool_call(tool_name, args, masker) context_parts.append(f[tool_result]\n{tool_result}) except ToolCallError as exc: context_parts.append(f[tool_error] {exc}) return \n\n.join(context_parts) if __name__ __main__: masker Masker() calls [ {tool: query_user, args: {user_id: U_1001}}, {tool: query_order, args: {order_id: O_20241001}}, # 模拟恶意参数LLM 尝试把 api_key 传给工具 {tool: query_user, args: {user_id: U_1002, api_key: SK-SUPER-SECRET}}, ] context build_agent_context( 你是客服助手回答用户问题时不要透露任何完整身份信息。, calls, masker, ) print(context)关键逻辑拆解sanitize_tool_args拦截的是“LLM 主动传参中的敏感键”。现实中模型确实可能受到 Prompt 注入影响试图把上下文中的密钥作为参数传给工具。这里直接按字段名黑名单拦截。mask_dict按照工具声明对返回结果做字段级脱敏。例如query_user返回的email字段会被替换成[EMAIL]phone会被替换成[PHONE]。序列化后的 JSON 会作为工具结果字符串进入上下文。由于真实数据已经被替换模型只能看到占位符无法复述真实手机号。对于query_orderget_secret(ORDER_SERVICE_API_KEY)在工具内部完成返回值中不包含密钥模型永远无法通过工具结果获取密钥。5.4 日志脱敏过滤器 audit_logger.py日志是另一个敏感数据重灾区。很多团队在应用层做了脱敏但日志里仍然记录了完整的 Prompt 和工具返回。这里写一个标准的logging.Filter对日志消息和参数做脱敏。# audit_logger.py import logging from masker import Masker # 日志平台索引中的敏感字段通常对应 Formatter 中的字段名 SENSITIVE_RECORD_KEYS { prompt, completion, tool_input, tool_output, email, phone, authorization, api_key, } class SensitiveDataFilter(logging.Filter): 日志过滤器所有日志消息与参数统一过脱敏。 def __init__(self): super().__init__() self.masker Masker() def filter(self, record: logging.LogRecord) - bool: # 处理日志消息本身 if isinstance(record.msg, str): record.msg self.masker.mask_text(record.msg) # 处理日志参数 if record.args: if isinstance(record.args, dict): safe_args {} for key, value in record.args.items(): if key.lower() in SENSITIVE_RECORD_KEYS and isinstance(value, str): safe_args[key] self.masker.mask_text(value) else: safe_args[key] value record.args safe_args else: record.args tuple( self.masker.mask_text(arg) if isinstance(arg, str) else arg for arg in record.args ) return True # 使用示例 logger logging.getLogger(agent) logger.addFilter(SensitiveDataFilter()) def demo_log(): logger.info(user query email%s, api_key%s, aliceexample.com, SK123456)日志过滤器的价值在于即使业务代码漏掉了某个敏感字段的脱敏日志系统也不会直接泄露明文。实际项目中建议把该 Filter 挂到所有使用到的 Logger 上尤其是框架自动产生的日志。6. 运行与效果验证写完了代码我们来实际操作一遍确认脱敏链路真的生效。6.1 运行命令在项目根目录创建.env文件echo ORDER_SERVICE_API_KEYtest_key_12345 .env然后导出环境变量并运行主程序export ORDER_SERVICE_API_KEYtest_key_12345 python agent.py6.2 预期输出运行后你应该看到类似下面的输出你是客服助手回答用户问题时不要透露任何完整身份信息。 [tool_call] query_user args{user_id: U_1001} [tool_result] { user_id: U_1001, email: [EMAIL], phone: [PHONE], id_number: [ID_CARD], level: vip } [tool_call] query_order args{order_id: O_20241001} [tool_result] { order_id: O_20241001, buyer_name: [MASKED], address: [MASKED], tracking_number: [MASKED], amount: 299.00 } [SECURITY] blocked sensitive param api_key for tool query_user [tool_call] query_user args{user_id: U_1002, api_key: SK-SUPER-SECRET} [tool_result] { user_id: U_1002, email: [EMAIL], phone: [PHONE], id_number: [ID_CARD], level: vip }6.3 如何判断运行成功检查以下三条核心标准上下文无真实 PII输出的 JSON 中email的值不是aliceexample.com而是[EMAIL]。上下文无凭据SK-SUPER-SECRET没有出现在任何[tool_result]中。同时ORDER_SERVICE_API_KEY的值test_key_12345也没有出现在输出中。拦截器生效当 LLM 试图把api_key作为工具参数传入时系统打印了[SECURITY] blocked sensitive param日志并且该参数没有进入工具执行。如果前两条不通过说明脱敏规则没有覆盖到对应字段或者工具返回值中混入了未声明字段。这时需要回到TOOL_SENSITIVE_FIELDS配置检查字段名单是否完整。7. 常见问题与排查思路部署这类安全机制时团队最容易遇到以下几类问题。我把现象、原因、排查方式和解决方案整理成表格方便你对照处理。问题现象可能原因排查方式解决方案工具返回的邮箱仍出现在模型回答中脱敏改造前历史会话中已有真实数据检查该 session 是否在改造前产生对历史上下文做一次性脱敏新会话全部走脱敏链路模型生成的 API Key 被当成工具参数Prompt 中被写入了密钥模型从上下文“学习”到了审查系统 Prompt 和工具 Schema 描述彻底移除 Prompt 中的密钥密钥改为工具内部注入脱敏字段被误伤模型无法回答“用户级别”等非敏感字段脱敏规则过宽没有区分字段类型打印脱敏前后的 JSON 对比使用字段级白名单声明不要对所有字符串做全量正则脱敏日志中仍然存在手机号明文只有业务 Logger 挂了 Filter第三方库或框架日志未处理在日志平台全文检索手机号正则对全局 Root Logger 添加 Filter对不可控输出做日志侧二次脱敏工具返回中出现了未声明的敏感字段TOOL_SENSITIVE_FIELDS漏配检查真实工具返回结构建立“敏感字段声明” Code Review 清单工具新增字段必须同步更新工具因为缺失参数而调用失败拦截器把合法参数名误认为敏感键查看sanitize_tool_args日志将误拦截字段加入白名单或改用显式 Schema 检测8. 生产环境最佳实践代码示例解决的是“机制有没有”的问题。真实生产环境里还需要从工程制度、密钥管理、监控告警等多个维度补全。8.1 凭据管理从环境变量升级到密钥管理服务示例中使用环境变量是为了演示。生产环境建议使用 Vault、KMS 或云厂商的 Secret Manager工具函数在运行时动态获取凭据不要让凭据长时间存在于进程环境变量中。同时要开启密钥轮换机制密钥泄露后可以快速吊销。8.2 工具 Schema 的声明式敏感字段TOOL_SENSITIVE_FIELDS本质上是工具返回结果的“数据契约”。建议在工具定义阶段就同步维护敏感字段清单而不是等泄露后补丁式修复。可以使用 Pydantic 模型来定义工具输出把敏感字段用标记字段标注这样静态检查和运行时校验都能生效。8.3 在测试集中加入安全红测用例不要只测“正常回答”要在回归测试中加入以下用例用户输入包含 API Key模型尝试传给工具。工具返回 PII检查模型输出是否引用。Prompt 注入带上“忽略系统提示”指令看是否会造成工具参数乱传。长文本截断场景确认截断不会把占位符截掉导致真实数据漏出。只有把这些用例跑成自动化测试安全边界才不会在迭代中退化。8.4 模型选择与部署边界对于高敏业务优先选择私有化部署的模型或使用支持数据落盘隔离的模型服务。如果使用云端 API需要在架构上假设“Prompt 内容会被模型服务商看到”从而在源头控制敏感字段。上一节的脱敏机制在架构层面让“模型看到的已经是脱敏后的内容”这是最重要的保险。8.5 审计日志只记动作不记全文真实生产环境建议记录这些审计信息用户 ID 或会话 ID调用时间工具名称工具入参的非敏感字段敏感字段的 SHA-256 哈希脱敏后的返回结果摘要这样既满足溯源需求又避免日志系统成为新的数据泄露面。8.6 安全 Code Review 检查清单每次合并 Agent 相关代码前至少核对以下几点新增工具是否声明了敏感字段工具是否在内部获取凭据工具返回值中是否存在未脱敏的调试字段日志输出是否经过 Filter测试用例是否包含敏感数据处理场景这套清单看起来简单但能从流程上防止“开发时从简、上线后背锅”的问题。9. 总结与后续学习方向回到最初的问题如何在 LLM Agent 工作流中处理敏感数据同时不破坏工具调用关键在于不要把安全边界建立在模型的自律上而要在数据进入上下文之前通过脱敏、拦截、凭据隔离等手段让模型只能看到脱敏后的数据。工具调用本身不会因为脱敏而失效因为脱敏发生在工具执行完成后、返回结果进入上下文之前。本文实现的最小安全链路包含四层脱敏规则引擎负责把常见 PII 替换为占位符。工具调用拦截器负责清洗入参、执行工具、脱敏出参。工具内部凭据注入保证密钥不进上下文。日志过滤器负责在日志侧兜底脱敏。如果你正在构建自己的 Agent建议先从这四层入手把安全中间层做成框架中的强制环节而不是可选的“增强功能”。下一步可以继续研究的方向包括基于字段级数据粒度的 PII 识别服务、Agent 上下文存储时的加密方案、以及企业级审计系统的设计。无论你的 Agent 多强大数据的可控边界永远是第一优先级。
返回列表