先讲一个早上。
8:30 销售总监在群里问:“帮我拉一下上个月华北区的签单数据,按客户规模排个序。”
8:32 运营专员艾特同一个Agent:“发一下上周的工单处理时长报表,按客服分组。”
8:34 人事助理说:“新员工李华今天入职,帮我在飞书开通账号,加到‘研发部-新人培训’群。”三个请求,同一个Agent,三套完全不同的系统——CRM、工单系统、HR系统。
如果给每个部门单独做一个Agent,销售Agent只懂CRM,运营Agent只懂工单,人事Agent只管入职。那就有三个机器人,员工得记住分别@谁,团队协作反而变乱了。
一个Agent,同时服务多个部门,才是更优雅的方案。
但我们很快就撞上了三个现实难题:
- 意图冲突:销售说“客户”,运营说“客户”,人事也说“客户”,但三个人指的完全是不同意思。
- 权限隔离:人事能看到薪资,销售不能;运营能看到工单敏感内容,人事不需要。
- 知识库打架:销售的知识库里有“话术模板”,运营的有“SLA标准”,混在一起Agent会乱套。
这篇文章,我带你走过一条从“混乱”到“清晰”的架构演进之路。不是空谈理论,而是一个真实Agent从V1到V3的迭代故事。
一、V1:一个大脑 + 一堆工具 = 灾难
一开始我们的设计很简单:一个核心Agent,挂载所有部门的工具和知识库。用户说话,Agent自己判断该调哪个API。
结果几天就崩了。
场景重现:
销售问:“帮我看看客户‘华胜科技’的合同状态。”
Agent去CRM查,没找到(因为客户名字在运营系统里叫“华胜-2024-001”)。运营系统的知识库里有记录,但Agent错误地调用了工单API,返回了一个跟合同无关的故障单号。销售一脸懵:“这Agent是不是傻?”更糟的是,有个人事问:“小张的绩效分是多少?”Agent从销售系统里拉来了“小张上个月的签单额”——那是另一个同名的小张。
根本原因:不同部门的语义空间不一样。同一个词,在不同部门代表不同实体;同一个实体,在不同部门有不同的叫法。一个Agent试图用一个大脑理解所有人,就像你同时听三个人用三种方言说话。
二、V2:部门路由 + 上下文隔离 —— 把“大脑”拆成“前厅”和“后厨”
我们反思后做了第一次架构调整:先分流,再处理。
2.1 路由层:用户说了第一句话,就给他贴上“部门标签”
每个用户在系统里有部门属性(销售/运营/人事/…)。这个属性在第一次对话时就被记录在session里。
路由逻辑很简单:
if user.department == 'sales':
router -> sales_agent_instance
elif user.department == 'ops':
router -> ops_agent_instance
elif user.department == 'hr':
router -> hr_agent_instance
注意:这里不是三个物理上独立的Agent,而是同一个Agent程序,启动三个配置不同的实例。每个实例加载不同的工具集和知识库。
• 销售实例:只挂CRM工具、销售知识库、合同模板。
• 运营实例:只挂工单系统、SLA规则库、客服话术。
• 人事实例:只挂HR系统、员工手册、入职流程。
这样一来,销售问“客户”,销售实例知道去CRM查客户表;运营问“客户”,运营实例知道去工单系统查客户投诉记录。两个实例各查各的,互不干扰。
2.2 但有一个漏洞:跨部门协作怎么办?
市场营销部的Amy需要问“上周销售部的签单数据”。她是运营岗,但需求涉及销售系统。按上面逻辑,运营实例访问不了销售CRM。
我们的解决方案是:显式跨部门授权。
当Agent识别到用户需要访问其他部门数据时,不会自动切换,而是发一条确认:
“你正在访问销售部门的数据,是否确认?这将记录在审计日志中。”
用户点击确认后,这次会话临时获得一个只读的跨部门令牌,调用销售实例的只读接口。操作完成后令牌立即失效。
这样既满足了协作需求,又不会造成权限混乱。
三、V3:分层知识库 —— 公共知识 + 部门私有 + 个人记忆
路由解决了“该用哪个工具”,但知识库的问题更隐蔽。
公司有一个全局知识库(考勤制度、报销标准、IT支持),销售有销售话术库,运营有SOP手册,人事有入职指南。如果把这些全塞进一个向量数据库,用户问“年假怎么算”,Agent可能从销售话术里找到一句“年假期间也要跟进客户”,那可就闹笑话了。
我们的架构采用了三层知识隔离:
3.1 公共层(Global Knowledge)
存放全员通用的内容:公司制度、行政指引、办公软件使用手册。所有部门实例都可以检索这一层,但只能读,不能写。
3.2 部门层(Dept Knowledge)
每个部门一个独立的向量库。销售实例只能检索销售库,运营实例只能检索运营库。这一层的内容由各部门自己维护,Agent只做索引和检索。
3.3 个人层(Personal Memory)
这一层比较特殊。每个用户的短期会话记忆、个人常用短语、历史偏好,存在以user_id为key的Redis或向量库中。它不跨部门共享,但长期跟随用户。
举例:销售李雷每次问“本周签单”,习惯按“金额降序”看。Agent记住这个偏好,下次直接按这个格式返回。这些记忆不会泄露给其他销售,更不会跨部门。
检索时的优先级:
个人层(最近10条偏好) > 部门层 > 公共层这样保证:用户最先拿到跟自己最近、最相关的内容,部门级知识次之,公司级通用知识兜底。
四、三个“避坑”的实战经验
下面三条,是我们在V2到V3过程中摔得最疼的地方。
4.1 坑一:不要在路由层做“智能判断”
我们一开始试图让Agent自己判断“用户可能是哪个部门的”——比如根据关键词“签单”猜是销售,“绩效”猜是人事。结果一塌糊涂。销售说“绩效”问的是销售业绩达成率,人事说“绩效”问的是考核分数,Agent猜不准,经常切错实例。
解决:放弃猜测,显式路由。用户第一次对话时主动问一句:“请问你属于哪个部门?”或者直接从企业通讯录的部门字段读取。不要相信模型的分词。
4.2 坑二:部门实例之间不要共享内存
初期我们为了节约资源,让所有实例共用同一个会话缓存。结果销售A问了一个客户名字,被缓存在全局层,运营B接着问同一个名字,返回了客户投诉信息——隐私泄露了。
原则:不同部门的实例,内存、缓存、会话状态必须物理隔离。哪怕用同一个Redis,也要用不同的key前缀(sales:session: vs hr:session:)。
4.3 坑三:跨部门查询要审计,而且要可读
我们要求所有跨部门数据访问都生成一条审计日志。但早期日志写的是cross_dept_access: user=xxx, target=yyy,根本看不出查了什么敏感字段。
后来改成:
{
"user": "amy@ops",
"target_dept": "sales",
"action": "query_contracts",
"filter": "customer='华胜科技'",
"result_count": 3,
"reason": "市场活动需要"
}
对方审计时一目了然:谁、什么时候、为什么、查了什么、查到了多少条。
五、一个完整的跨部门协作案例(从混乱到丝滑)
用个完整例子把上面所有点串起来。
场景:人事部门的Lisa需要在飞书里快速创建下周的新员工入职账号,同时通知IT配置笔记本和邮箱。
旧流程:Lisa打开HR系统→手动填写入职信息→再发消息给IT群→IT手动创建账号→来回确认→耗时至少30分钟。
新流程(Agent介入):
- Lisa在群里@通用Agent:“新人王芳,下周一入职,研发部前端,帮她开通飞书、邮箱、领笔记本。”
- Agent读取Lisa的部门=”hr”,启动人事实例。
- 人事实例识别意图=”入职办理”,需要调HR系统创建员工记录(写权限)和IT系统的工单创建(跨部门)。
- Agent返回确认请求:“需要跨部门访问IT系统创建工单,是否继续?”
- Lisa点击确认。
- Agent调用HR API创建档案,返回employee_id;再用这个id调用IT工单API,创建一条“新员工设备申请”工单,自动指派给IT支持组。
- 完毕后,个人记忆层记录:Lisa最近一次入职操作使用了“研发部-前端”这个模板。
- 审计日志写入:user=Lisa, action=hr.create_employee, cross_dept=it.create_ticket, result=success。
- 10秒后,Agent回复:“已创建王芳的入职档案(ID 2345),笔记本工单已派单,预计今天下班前回复。”
总耗时:不到1分钟。Lisa节省了29分钟的手工操作和跨群沟通。
六、总结:一个Agent服务多部门的四个核心设计
如果你也想搭建这样一套架构,记住这四个核心点: - 路由优先,部门隔离:入口按用户部门分流,不同部门跑不同实例,各实例工具和知识库互不干扰。
- 知识分层:公共知识、部门知识、个人记忆三层分离,检索优先级清晰。
- 跨部门有闸门:涉及访问其他部门时,必须显式确认并记录审计日志,不搞“隐身跨越”。
- 记忆不外泄:每个部门的缓存、会话、向量检索空间物理隔离,防止语义交叉污染。
最后说一句:不要试图做一个“万能大脑”。一个Agent能同时服务多个部门,不是因为它什么都懂,而是因为它知道什么时候该用哪个“分身”。就像一个大公司有前台、有后台、有不同事业部,各司其职,才不乱。
你的企业微信或飞书里,可能现在就有一个正在被三个部门同时使用的Agent。如果它还没出过乱子,那恭喜你架构合格;如果已经开始串数据、答非所问,不妨试试上面这套设计——把Agent从“一个什么都会的麻烦精”,变成一个“分工明确的靠谱助手”。