上一篇讲人工接管时,我列了三类必须停下等人的动作,其中一类是“越权”。
很多人会问:怎么算越权?
要回答这个,得先把一个更基础的问题说清楚:这个 Agent 到底有什么权?它替谁做事?
这半年重构 Office Agent,我越来越觉得,企业 Agent 的权限问题比 Prompt 问题更早暴露。
模型还没开始“聪明”,系统就已经要先回答一个问题:
它是一个独立账号,还是某个人的手?
我的结论先放前面:
Agent 不该有自己的超级账号。它必须以发起人的身份、在发起人的权限范围内做事。
这篇文章只讨论一件事:
企业 Agent 替人做事,但不能替系统重新定义权限。
接 CRM 的第一个技术问题
给 Agent 接 CRM 时,我一开始以为第一个技术问题是:它能不能正确地改数据。
真正卡住我的不是这个,而是另一个问题:
它以谁的身份改?
CRM 天生有数据权限。
销售只能看自己的客户,主管能看团队的,普通员工看不到别人的成单金额。很多企业系统跑了很多年,最核心的不是页面,而是这套权限和数据边界。
现在塞进来一个 Agent,它该看到什么?
如果图省事,给它配一个能看所有数据的公共服务账号,问题立刻来了。
一个销售让 Agent 帮他查“最近需要重点跟进的大客户”。如果 Agent 用公共高权限账号去查,它可能把别人名下的客户也一起拿出来。
它没有攻击系统。
它没有绕过登录。
它只是用了你给它的权限。
而你给多了。
这类问题最麻烦的地方在于,它看起来不像一个明显的安全事故。界面能跑,接口能通,模型也能解释得头头是道。
但从企业系统视角看,权限边界已经被打穿了。
我不把这个包装成“某次 CRM 泄露事故”。更诚实的说法是:在设计 CRM Agent 权限时,我很早就意识到,不能先给它一个大账号,再靠 Prompt 约束它“不要看不该看的数据”。
后来我会把这条边界拆成三个很具体的工程约束。
第一,查询层先收窄。
查询客户列表时,权限过滤必须在查询条件里完成。
Agent 拿到的结果本来就只能是当前发起人可见的客户,而不是先查全量,再让模型自己筛。
第二,技术账号不等于业务授权。
技术账号只承担系统间调用通道。
真正决定能看什么、能改什么的,仍然是发起人的身份、组织范围和业务角色。
第三,写入动作必须能追到人。
审计记录里不能只写“Agent 修改成功”。
至少要留下发起人、执行动作、影响对象、授权范围和审批结果。
Prompt 是提醒,不是权限系统。
权限必须落在系统里。
如果把这件事翻译成代码,它不应该长这样:
坏写法:只要工具能调用,就把判断交给模型。
# 错误方向:只要工具能调用,就把判断交给模型def run_agent_action(user, action, payload): result = llm.decide(action=action, payload=payload) return crm_api.execute(result)更稳的写法,是先让系统判断“这个身份在这个对象上能不能做这个动作”:
好写法:模型提出意图,系统判断边界。
# 脱敏后的最小形态:业务权限先过系统边界,再进入工具执行def can_operate(scope, entity, action): if scope.role == "admin": return True if entity == "customer": return action in {"read", "create", "update"} and scope.role in {"sales", "manager"} if entity == "opportunity": if scope.role == "sales": return action in {"read", "create", "update"} if scope.role == "pre_sales": return action in {"read", "update"} return False这里的关键不是代码多复杂,而是判断位置变了。
模型可以决定下一步想做什么。
但它不能决定自己有没有权限。
权限判断不交给模型
Agent 到底有没有自己的权限?
站在企业系统开发负责人的角度,我现在的判断很明确:
Agent 没有自己的业务权限,只有借来的权限。
张三让它做事,它就是张三的手。
张三看不到的客户,它也不该看到。
张三不能改的订单,它也不能改。
张三只能提交草案,它也不能直接让草案生效。
这句话听起来很朴素,但落到系统里,经常会被偷懒破坏。
最常见的偷懒方式,是把 Agent 当成一个“系统用户”。
为了调用方便,给它配一个权限很大的账号。所有查询都从这个账号走,所有写入也从这个账号走。业务系统只看到“Agent 做了某个动作”,看不到背后是谁发起的。
这样做短期很快。
但它会带来三个后果。
第一,原来的数据权限失效了。
销售、主管、管理员之间的边界,被一个公共账号抹平了。
第二,责任主体变模糊了。
出问题之后,你只能看到“Agent 改了数据”,却很难回答“谁让它改的”。
第三,自动化越强,风险越大。
它不只是查错一条数据,而是可能批量查、批量写、批量触发后续流程。
所以我更愿意把 Agent 理解成一种执行能力,而不是一个新的业务主体。
它可以帮人跑流程。
但它不能替系统重新定义谁能看什么、谁能改什么。
权限边界应该落在哪一层?
“借来的权限”不能只停在原则上。它至少要落成四个工程设计点。
这四个点不是架构装饰。
它们分别回答四个问题:
- 谁在发起。
- 数据在哪里被挡住。
- 工具到底能做什么。
- 事后能不能追责。
第一,身份透传。
Agent 调用业务系统时,必须带上发起人的身份和组织上下文。
这不一定意味着底层完全不用技术账号。很多系统为了集成,仍然需要服务端凭证。但那个凭证只能承担“技术通道”的角色,不能承担“业务授权”的角色。
真正决定能看什么、能改什么的,仍然应该是发起人。
谁发起,按谁鉴权。
谁批准,记谁责任。
第二,数据边界落在查询层。
销售只能看自己客户这件事,不能靠 Prompt 写一句“请不要查看其他人的客户”。
模型会忘。
提示词会被绕过。
上下文也可能被拼错。
数据边界必须落在查询本身:每一次查询天然带上权限过滤,每一次列表返回都只返回当前身份能看的数据。
换句话说,不是让 Agent 先查全量,再让它“自觉”过滤。
而是系统一开始就不把越界数据给它。
我在 CRM Agent 里更倾向于把这类规则写成工具入口的硬边界:
ALLOWED_ENTITY_SETS = { "customers", "contacts", "opportunities", "tasks",}def enforce_query_scope(request, scope): entity = extract_entity(request.path) if entity not in ALLOWED_ENTITY_SETS: raise PermissionError("entity is not declared in the CRM model") if has_template_placeholder(request.params): raise ValueError("query contains unresolved placeholder") request.params["filter"] = merge_filter( request.params.get("filter"), scope.to_customer_filter(), ) request.params.setdefault("top", 25) return request这段代码背后的思想很简单:
- 未知表不让查。
- 占位符没解析不让查。
- 没有数据范围不让查全量。
- 列表查询默认限制返回数量。
这些都不是 Prompt 能稳定兜住的事。
查询层硬边界
第三,最小权限。
Agent 的权限应该按任务给,不按想象给。
它这次只需要查客户跟进状态,就不要给它修改客户阶段的能力。
它这次只需要生成建议,就不要给它直接生效的能力。
它这次只需要处理一个客户,就不要给它批量处理全表的能力。
很多风险不是来自“恶意”,而是来自“以防万一多给一点”。
在传统后台里,多给一点权限已经危险。
到了 Agent 这里,多给一点会被自动化放大。
第四,全程审计。
企业系统最后一定会问四个问题:
- 谁发起的?
- Agent 以谁的身份做的?
- 它看了什么、改了什么?
- 谁批准它继续往下走?
如果这四个问题答不上来,这个 Agent 就还没有真正进入企业系统。
因为企业系统不是只要“能跑”,还要能追责、能复盘、能回滚。
权限设计和上一篇的人工接管在这里连起来了。
当动作进入高风险区,系统不能只记录“Agent 执行成功”。它还要记录发起人、授权范围、审批人、动作摘要和影响对象。
否则一旦出问题,所有责任都会混在一个模糊的“智能助手”里。
这在企业里是不可接受的。
我现在会先问六个问题
如果你正在把 Agent 接进业务系统,我建议先不要急着设计复杂架构。
先把每个工具、每个动作过一遍六个问题。
问题 1:谁发起这个动作?
如果系统里只记录“Agent 发起”,说明身份设计还不够。
问题 2:它能看到哪些数据?
不要回答“理论上能看全部,但 Prompt 会限制”。这个答案不合格。要回答具体的组织、团队、客户、订单、审批或任务范围。
问题 3:谁保证它只能看到这些数据?
如果答案是模型自己,那就还没有边界。真正的答案应该是鉴权层、查询层或业务系统原有的数据权限。
问题 4:它能写什么?
查询、生成草案、修改状态、触发外部流程,是完全不同的权限等级。不要把它们混成一个“调用工具”的权限。
所以工具本身也要有治理元数据。
比如一个读取报表证据的能力,应该明确告诉系统:它是只读的、给哪个业务系统可见、是否需要审批、审计标签是什么。
@tool( name="collect_report_evidence", governance=ToolGovernance( side_effect="read", approval_mode="never", visible_to_systems=("crm",), audit_tags=("crm", "report", "evidence"), ),)async def collect_report_evidence(customer_id: str, opportunity_id: str): token = await resolve_runtime_app_token() return await evidence_service.collect( customer_id=customer_id, opportunity_id=opportunity_id, access_token=token, )这里用系统 token 读取证据,并不等于 Agent 拿到了系统的无限权限。
真正重要的是:系统 token 被包在一个只读工具里,工具有可见范围,有副作用声明,有审计标签。
这才是企业系统能接受的“系统能力”。
系统 token 被工具治理包住
问题 5:超过范围时会发生什么?
是直接失败、进入人工接管,还是降级成只读建议?这件事要提前写进规则里,不能等模型临场判断。
问题 6:事后怎么查?
一次完整审计记录,至少要能看到发起人、执行身份、动作类型、影响对象、审批信息和结果。
这六个问题问完,很多 Agent 权限设计里的“方便做法”就会暴露出来。
比如:
- 给 Agent 一个全量账号,方便查询。
- 让 Agent 自己在 Prompt 里记住“不要越权”。
- 把读权限和写权限绑在同一个工具里。
- 只记录动作成功,不记录发起人和授权范围。
这些做法在 Demo 里很顺,在生产里都很危险。
真正可上线的设计,应该反过来:
- 默认没有全量账号。
- 默认按发起人身份鉴权。
- 默认查询层过滤数据。
- 默认读写权限拆开。
- 默认高风险动作进入人工接管。
- 默认每一步都能审计。
我真正开始重视这个问题,是在做开发态身份切换时。
页面上看起来已经切到了销售身份,但如果权限链路里还混着真实登录人的管理员角色,所有验证都会失真。
功能不会报错,数据也能返回。
但你验证的已经不是销售视角,而是管理员视角留下的影子。
最后,还要用测试把身份边界钉住。
我很看重这类回归用例,因为权限 bug 往往不是“功能坏了”,而是“看起来功能正常,但身份混了”。
def test_dev_switch_user_should_not_inherit_real_admin_role(): real_login = {"email": "admin@example.com", "role": "admin"} switched_user = {"id": "sales-user-1", "role": "sales"} scope = build_scope( login_user=real_login, dev_switched_user=switched_user, debug=True, ) assert scope.role == "sales" assert scope.user_id == "sales-user-1" assert "admin@example.com" not in scope.identity_candidates这个测试防的不是黑客攻击。
它防的是开发过程中最常见的权限错觉:你以为自己在验证销售身份,实际系统还夹带了管理员身份。
可以把这一整套设计压缩成一句话:
Agent 可以走技术通道,但业务授权必须回到发起人和原有权限体系。
这些规则不会让 Agent 看起来更炫。
但它们会让 Agent 像一个能进入企业系统的工程能力。
学AI大模型的正确顺序,千万不要搞错了
🤔2026年AI风口已来!各行各业的AI渗透肉眼可见,超多公司要么转型做AI相关产品,要么高薪挖AI技术人才,机遇直接摆在眼前!
有往AI方向发展,或者本身有后端编程基础的朋友,直接冲AI大模型应用开发转岗超合适!
就算暂时不打算转岗,了解大模型、RAG、Prompt、Agent这些热门概念,能上手做简单项目,也绝对是求职加分王🔋
📝给大家整理了超全最新的AI大模型应用开发学习清单和资料,手把手帮你快速入门!👇👇
学习路线:
✅大模型基础认知—大模型核心原理、发展历程、主流模型(GPT、文心一言等)特点解析
✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑
✅开发基础能力—Python进阶、API接口调用、大模型开发框架(LangChain等)实操
✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用
✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代
✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经
以上6大模块,看似清晰好上手,实则每个部分都有扎实的核心内容需要吃透!
我把大模型的学习全流程已经整理📚好了!抓住AI时代风口,轻松解锁职业新可能,希望大家都能把握机遇,实现薪资/职业跃迁~