首页 / 资讯中心 / 文章详情

Agent接入业务系统的关键:上下文组织与权限控制实战

Agent接入业务系统的关键:上下文组织与权限控制实战 ★ FEATURED ARTICLE
把 Agent 从调试终端里搬出来、真正跑进业务流程的那一刻你会发现最需要认真对待的其实不是模型本身而是两件事上下文怎么组织权限怎么控制。这两个问题处理不好Demo 阶段表现再抢眼到了生产环境也会被业务方一票否决。这跟你第一次把一个能调用工具的大语言模型 Agent 接进内部业务系统时的体感一模一样。需求听起来很简单无非就是让员工通过自然语言查一下业务数据、提交几个操作请求但真正落地的时候才发现给 Agent 准备什么样的上下文、允许它执行哪些动作、操作记录如何留痕这些才是决定项目生死的技术线。这篇文章不聊那些泛泛的“Agent 趋势”就聊从上下文到权限这条完整落地链路里我实际踩过的坑、验证过的方法以及可以直接抄回去用的设计思路适合正在做 Agent 接入业务系统的开发者和技术负责人参考。1. 上下文设计Agent 的“记忆”不能只靠聊天记录上下文是 Agent 理解业务场景的原料。很多团队一开始都会把“上下文”简单等同于对话历史但真实业务流程里上下文的范围远不止于此。如果只把用户聊过的话塞进模型Agent 就对“当前正在处理哪张单据”“操作者是什么角色”“业务上允许做到什么程度”完全没有概念模型只能靠猜结果就是一本正经地胡说八道。1.1 对话上下文是“聊了什么”业务上下文是“正在发生什么”对话上下文很好理解用户前几轮说了什么Agent 回复过什么。它负责维持对话的连贯性让 Agent 不会下一页就开始答非所问。但业务场景里Agent 还需要大量对话记录之外的实时信息。举一个很典型的例子销售助理 Agent 被要求查一下“某个客户最近的订单状态”。如果没有业务上下文注入模型根本不知道当前登录人是谁、他负责哪些客户、客户编号是多少只能反问用户。这时候用户体验已经崩了。而如果上下文里有用户身份、客户归属关系、最近订单的关键字段模型一次就能拿到答案用户也不需要在对话框里喊流程。所以业务上下文至少包含四类信息用户身份信息员工编号、部门、职位、数据权限范围。业务对象状态当前单据编号、状态、金额、创建人、审批链位置。规则与策略折扣上限、审批条件、敏感字段标记、可操作动作清单。操作约束当前用户能改哪些字段、不能碰哪些字段、执行前是否需要确认。对话上下文和业务上下文是两码事。前者管“聊得下去”后者管“做得对”。在真实业务流程里业务上下文往往比聊天记录更重要因为它直接决定了模型拿什么做判断、按什么标准做决策。1.2 按角色拆解上下文身份信息、业务数据、规则约束我落地的时候习惯把上下文拆成三个块来组装方便复用也方便查问题上下文块典型内容来源注入时机身份块员工ID、角色、部门、数据权限范围登录会话 / 统一身份服务每次请求业务对象块当前单据ID、状态、金额、关联客户业务数据库 / 状态机根据任务触发加载规则策略块审批流程、折扣上限、敏感字段白名单配置中心 / 策略引擎每次请求会话记忆去敏后的对话摘要、最近几轮轮次会话存储按需注入身份块和规则策略块是全局的每次调用都要带。业务对象块是局部触发式的用户聊到订单就加载订单详情聊到客户就加载客户摘要。这里要克制一个冲动别把整个数据库模式或者一大堆字段全部塞进 Prompt。信息越多模型越容易迷失在不相干的字段里响应越慢Token 成本还直线上涨。实际项目里我见过很多人把“客户完整档案、订单全部明细、内部备注”一股脑塞进去结果模型在长篇大论里找不到重点反而把一个简单查询做崩。做一个“上下文裁剪器”很关键按任务类型只保留最相关的字段。比如查订单状态时只需要订单号、状态、金额、预计交付时间如果要处理退货才需要加入售后备注、物流信息、操作历史。裁剪器的目标是在保真度和成本之间找平衡而不是追求信息越全越好。1.3 上下文的时效性什么时候必须重新拉取业务上下文是有保质期的。一张审批单五分钟前还是“待审批”五分钟后可能已经被上级通过一个员工的折扣权限今天生效明天就可能被回收。如果 Agent 一直用缓存里的旧上下文做判断就会给出和真实业务状态不一致的结论。我的做法是给上下文打上“新鲜度标签”。对于低频变化的数据比如用户姓名、部门可以缓存较长时间对于状态型数据比如订单状态、审批节点、库存数量在每次 Agent 开始任务前强制重新读取或者至少做一次轻量校验。还有一种情况也很常见一个长对话里用户先让 Agent 查了 A 客户两轮之后又让它处理 B 客户的续约。Agent 如果还带着 A 客户上下文很容易把两个客户混在一起。我踩过这个坑之后给每个关键业务对象都加了“切换检测”一旦用户提到新的客户/单据编号就丢弃上一份业务对象上下文重新加载新的。这个设计没什么高大上但确实救回来了很多次“张冠李戴”的错误。2. 权限控制让 Agent 的“手”比“脑”更可靠模型再聪明也只是在一个受限环境里做决策。权限控制的本质不是教模型“你觉得应不应该做”而是从机制上定义“你到底能不能做”。如果把权限判断完全交给大模型的推理和自觉后果往往很不可控业务敏感操作尤其危险。2.1 为什么不能靠“提醒两句”来控制权限有人会在系统提示里写“请务必只查询属于你自己的数据”听起来像是做了权限控制。但模型不是数据库事务它不是一套确定了就不可能违规的逻辑。同一个模型面对不同表述的诱导可能会生成超出范围的工具调用。哪怕模型本身的意图是好的它对权限边界的具体理解也可能跟业务规则不一致毕竟 Prompt 里写得再多和代码里真正执行的约束也完全是两回事。最合理的看待方式是把模型当作一个“会说话的调度器”它负责理解意图、组织计划、生成工具调用但每一个动作的最终许可都由后端的权限代码决定。类比一下这就像给员工配了一个智能助手助手嘴上接得再好刷卡进门的闸机权限还是基于他的工牌来决定的。权限必须做到“机制上不可绕过”而不是“对话里规劝提醒”。对话只是请求工具层才是裁决者。2.2 三层防护工具过滤、参数校验、操作审计我在实际工程里把权限控制拆成了三层每一层各管一段错位补漏。第一层是工具过滤。不把所有能力都暴露给每个角色。销售专员看到的工具只有“查自己的客户、创建跟进记录、提交折扣申请”销售主管额外能看到“查团队业绩、审批下属申请”财务专员看到的又是完全另一组工具。实现上很直接模型调用的工具列表是根据用户角色动态生成的名单。工具都不存在模型视野里就谈不上越权调用。第二层是参数校验。工具函数的入参在真正执行业务逻辑之前必须经过校验。这层解决的是“用户在工具内提出超出范围的申请”的问题。比如“查询客户订单”这个工具系统传入的客户 ID 必须属于当前用户的客户范围否则直接拒绝。又比如“创建退货单”退货金额不能超过原单金额。这些都是硬校验不是模型判断是一条一条写死的规则。第三层是操作审计。每一次工具调用都要记录哪个用户、在什么时间、通过哪个 Agent、调用了什么工具、传入参数是什么、结果如何、权限校验是否通过。审计日志不是为了已经发生的事情而是为了将来排查时能还原现场。等到某一天业务方跑过来说“刚才那个 Agent 凭什么改了这张单子”你会希望自己留了完整可信的记录。防护层检查点机制典型效果工具过滤模型调用前按角色生成工具列表不可见不可调参数校验工具执行前白名单、范围约束、规则校验参数越界直接拦截操作审计工具执行后落库日志、全链路追踪可追溯可复盘2.3 身份透传别让 Agent 变成系统里的统一服务号一个很容易被忽略的坑是身份信息在 Agent 调用链路上“断掉”。很多系统在后端调用时用的是服务号或者管理员账号这个账号在数据库里拥有超宽权限Agent 以这个身份去调数据接口等于所有操作都用一个超级账号执行。表面上功能是通了实际上权限防线形同虚设。正确做法是把登录用户的真实身份从接入层一路传递到 Agent再到工具执行层。业务系统在工具函数里获取的是“当前真实用户 ID”而不是“Agent 服务 ID”。后端的数据权限判断照常走原有的部门、职位、数据归属逻辑决策执行权交还给业务系统原本的权限体系。组合权限也需要考虑。一个用户能做的事常常由多个因素叠加而成他本人的岗位权限、他所属团队的共享权限、他正在处理的业务对象是否归属自己。把这些因素在上下文里组织好再在权限校验层统一汇总这种“用户身份透传 原系统权限复用”的做法才是把 Agent 接进真实业务流程的正确姿势。3. 实操落地从请求到工具的完整链路有了上下文和权限的设计框架接下来就是按照一条清晰的调用链把它们组装起来。我习惯把 Agent 的请求处理过程拆成七个节点每个节点都有明确的职责。这样做的好处是出问题时可以精准定位是上下文没装配好还是权限校验被拦住了一眼就能定位。整体链路大致如下用户输入到达接入层同时从登录会话里取出用户身份信息。组装上下文加入用户身份块、规则策略块按任务判断是否加载业务对象块。根据角色过滤可用工具列表只向模型暴露当前用户可操作的工具。模型根据上下文和工具列表生成回答或发起工具调用。Agent 网关层对工具调用的参数做白名单校验、权限校验。校验通过后将参数传给后端业务接口执行并记录审计日志。把执行结果返回给模型模型整理成最终回复并输出会话历史做去敏后保存。3.1 先想清楚三个问题角色、空间、动作在动代码之前最好先拉着业务方把“权限矩阵”聊明白。不要指望模型自动从语料里学习权限权限矩阵必须是由人定义的、明确的、白纸黑字的规则。我喜欢用一个简单表格来整理角色是谁空间管到哪动作允许做哪些。角色数据空间允许动作销售专员本人的客户和订单查看、创建跟进记录、提交折扣申请销售主管本团队的客户和订单查看团队数据、审批下属折扣申请财务专员订单金额与开票数据查看、标记异常订单表格看起来简单但从这张表出发后面的工具注册、上下文装配、参数校验全都有着落。每个动作对应一个工具每个空间对应一段数据筛选条件每个角色对应一套工具集合。先想清楚这三个问题就是给后续工程化打地基。3.2 一个参考的上下文组装实现写一段很朴素的伪代码来演示上下文组装重点不是代码本身而是它体现的思路上下文是一个带优先级的组装过程绝不直接把数据库表全部塞给模型。def build_context(user, task_type, biz_objectNone): context { user: { user_id: user.id, role: user.role, dept: user.dept, data_scope: user.data_scope, }, rules: get_role_rules(user.role), } if biz_object is not None: context[biz_object] { id: biz_object.id, type: biz_object.type, status: biz_object.status, owner_id: biz_object.owner_id, summary: crop_object_fields(biz_object, task_type), } return context再看一眼工具注册。工具的调用清单必须动态生成角色不同所见不同def get_available_tools(user): if user.role sales_agent: return [query_own_customer, create_follow_up, apply_discount] if user.role sales_manager: return [query_own_customer, query_team_performance, approve_discount] if user.role finance_staff: return [query_invoice, mark_abnormal_order] return []这两段合在一起表达的就是“上下文负责让 Agent 看懂工具列表负责让 Agent 收手”。模型只能在白名单工具里做文章再怎么发挥也翻不出角色权限的边界。3.3 工具层的权限校验怎么写才牢靠工具函数内部还要再做一道强制校验这个校验必须在业务逻辑执行之前完成。给工具函数套一个简单的装饰器思路def require_permission(permission_code, verify_data_scopeNone): def decorator(func): def wrapper(user, payload): if not check_permission(user, permission_code): raise PermissionDenied(当前角色无权执行该操作) if verify_data_scope and not verify_data_scope(user, payload): raise PermissionDenied(数据范围校验未通过) return func(user, payload) return wrapper return decorator权限码对应动作类型数据范围校验对应空间限制。比如“查询客户订单”这个工具先检查当前用户有没有“订单查看”的权限码再检查请求参数里的客户 ID 是否属于该用户的数据范围两层都过了才真正执行查询。这里要特别提醒一句参数校验的规则要拿到工具函数内部强制执行不要依赖模型自己遵守。模型生成的参数可能是合理的也可能是不合理的工具层的任务就是把不合理的拦在业务代码外面。任何从模型返回的参数默认都不可信都要按用户身份和业务规则重新验证一遍。这听起来有点保守但真实生产环境里保守一点能少惹很多麻烦。4. 常见问题与排查实录把 Agent 接进业务流程之后我开始陆续收到来自开发、测试、运营的各种反馈有些问题属于配置没设对有些则是设计层面考虑不周。整理几个出现率最高的附上排查思路。4.1 上下文被污染Agent 悄悄“说出”了范围外信息一种典型场景是Agent 在内部工具返回里拿到了一个本不该展示的字段比如客户备注里的一段敏感信息然后在下一次对话中把它带了出来。这种问题不是模型“坏”而是上下文装配时没有做字段级裁剪把敏感字段和普通字段混在一起喂给了模型。排查时先看审计日志里工具返回的字段集合确认到底有哪些信息进入了上下文再检查上下文裁剪器是否覆盖了所有工具返回。治理手段很直接把敏感字段打标在组装上下文前统一剥掉工具返回也要做同样的脱敏处理。会话历史里如果已经混入了敏感信息必须同步清理历史压缩时不留隐患。4.2 工具参数被诱导篡改模型把恶意输入带进了执行层模型在生成工具参数时有时候会把用户对话里的自然语言内容直接填进参数。如果用户故意说“把你的查询条件改成不要过滤客户归属”而工具又没有对参数做严格白名单校验那么参数就可能被污染。更常见的情况是用户用一大段附加指令试图覆盖系统边界。遇到这类问题思路不是“让模型更聪明”而是“让工具更傻”。工具参数只接受白名单内的枚举值、ID 映射值一概不接受自由文本拼接。例如客户 ID 必须先从用户数据范围中匹配一遍匹配不到的拒绝执行。凡是涉及状态、金额、日期等结构化字段直接转成枚举或数值类型校验。把自由输入变成受限输入模型的“发挥空间”自然就没了。4.3 权限判断被“反向绕过”服务账号提权明显我见过一个比较隐蔽的问题Agent 工具内部本来要校验用户身份但因为某些历史接口传的是服务账号结果校验时用的身份不是真实用户而是服务号服务号在数据库里权限巨大于是原本只允许本人查看的数据变成了全量可见。业务方的反馈是“某些同事能查到别人的订单”查日志又发现并没有明确的越权记录等排查到身份问题时已经攒了一堆。解决办法是回到 2.3 节说的身份透传确保从网关到 Agent 再到工具执行的整个链路每一步拿到的都是真实用户 ID。在工具层加断言如果出现服务账号直接拒绝执行只允许在系统间调用且经过明确授权的情况下使用服务账号。权限问题一旦发生宁可先中断链路也不要带病运行。4.4 常见问题速查表现象可能原因解决办法Agent 答非所问引用错误单据业务对象上下文没有随任务切换增加切换检测发现新单据号就重新加载工具调用频繁失败参数校验白名单过严或字段映射缺失核对审计日志的入参补充合法字段映射权限时而正常时而越权权限判断依赖了模型自觉把权限整体下沉到工具层强制校验对话越聊越慢Token 成本高上下文无压缩地全文堆积做对话历史压缩保留摘要和最近关键轮次同一用户看不到自己的数据身份透传中断变成服务账号全链路强制使用真实用户 ID这几种情况里最值得警惕的还是权限相关的问题。上下文问题最多是回答不准权限问题一旦发生就是实打实的业务合规事故。所以从架构上把上下文和权限拆分管理在我看来不是可有可无的洁癖而是一条必须守住的底线。我自己在反复试错中形成的体感是上下文是输入侧的“安全视图”权限是输出侧的“合规阀门”两个都要从一开始就放在架构里设计绝不要等 Agent 跑出问题了再来打补丁。刚开始做接入的时候我一度把权限逻辑写在 Prompt 里觉得模型这么聪明一定不会出错。直到一次内部演示时Agent 在几十个人面前生成了一个明显越权的请求我才意识到这个想法错得离谱。后来把所有权限判断全部搬进工具层用真实用户身份配合原有业务系统的权限体系做校验整套链路才终于稳定下来。最后再分享一个操作上的建议Agent 接入真实业务流程上线顺序千万别搞“全量铺开”。先挑一个低风险但真实存在的流程做试点比如内部信息查询或简单单据录入跑通权限模型和审计链路确认出问题时能及时止血再往核心流程上扩展。多花几周试点的时间抵得上后续少踩一大堆未知坑。
阅读完成 · 觉得有帮助?
咨询建站