业务助手Agent项目
为什么做它
客服场景只覆盖了产品外围。用户天天用的核心操作,写跟进记录、总结客户、起草回复,这些 AI 还没碰。
第二家客户是销售管理 CRM。销售每天最烦的事不是"没信息",是"信息要自己整理":打开客户的沟通历史,翻十几条记录,提炼重点,再写跟进。一天几个客户下来,半天就没了。
🔔
业务助手的做法很朴素:在客户详情页加一个按钮,点击后:
总结客户:拉取该客户的工单、邮件、通话记录,生成一页摘要
生成跟进草稿:结合客户阶段和最近动态,生成跟进记录草稿,销售改完再保存
起草回复:针对客户最近的邮件/消息,生成回复草稿
三个动作都不复杂,但都嵌在真实工作流里,销售每天用。这才是"给 SaaS 加 AI"和"做了一个 AI 功能"的区别。
标准过一遍:高频(每天用)、数据现成(CRM 里全有)、错误可容忍(草稿,人确认后才生效)、不碰核心决策(AI 只出草稿,人拍板)。可以做。
架构:业务 API + 权限校验 + 写操作二次确认
客服场景只需要读文档。业务助手要碰业务数据,架构上多了三样东西:
代码块
JavaScript
前端按钮 → 后端助手服务
│
├─ ① 工具注册表:每个工具声明参数、需要的权限、是否写操作
├─ ② 权限校验:服务端统一校验,注入用户上下文(租户、角色、数据范围)
└─ ③ 写操作一律返回草稿,用户确认后才落库
工具注册表是核心。LLM 不直接调业务 API,它只决定"调用哪个工具、传什么参数",真正执行的是后端代码。每个工具声明自己的权限要求,服务端统一校验。
权限校验必须在服务端做,不能在 prompt 里做。 这个后面细说,是我们踩过的最深的坑。
写操作二次确认。 AI 生成的内容一律以草稿形式返回前端,用户点"确认保存"才写入。这个设计看起来多了一步,但挡住了几乎所有 AI 事故。
核心代码
代码块
Python
# assistant.py - 业务助手:工具注册 + 权限校验 + 草稿机制
from functools import wraps
class ToolRegistry:
"""工具注册表:LLM 只能看到这里注册的工具"""
def __init__(self):
self._tools = {}
def register(self, name, requires_perm=None, is_write=False, description=""):
"""注册工具。requires_perm 是权限标识,is_write 标记写操作"""
def decorator(fn):
fn.meta = {
"name": name,
三个设计点,每个背后都有一次事故:
LLM 只看到有权限的工具。 list_for_llm 按用户权限过滤工具列表。LLM 根本不知道有 draft_followup 这个工具,就不会去调它。这比"让 LLM 调了再校验"安全得多,问题在源头就被挡住了。
服务端强制过滤数据。 summarize_customer 查询时强制带 tenant_id 和 data_scope。这不是可选参数,是服务端拼进去的,前端和 LLM 都传不了。数据隔离只能靠服务端,不能靠 LLM 自觉。
写操作返回草稿。 所有 is_write=True 的工具,结果以 draft 形式返回,前端展示确认按钮。用户点确认,后端才执行真正的写入。AI 永远没有"直接改数据"的能力。
踩坑:权限是命门,写操作必须人确认
坑一:权限校验放错了地方。
第一版我们把权限检查写在 prompt 里:"你只能访问当前用户有权限的数据。"看起来没问题,直到一个测试账号问到了别的团队的客户数据。
原因不复杂:助手服务端调用业务 API 时用的是服务端服务账号的权限,而不是发起请求的用户的权限。LLM 生成的工具调用,传什么参数就查什么数据,prompt 里的"你只能……"根本拦不住。
修复方案就是上面的代码:工具查询强制拼 user_ctx(租户 + 数据范围),服务端统一校验,权限在代码里,不在 prompt 里。
这件事之后我们定了一条铁律:AI 功能的权限模型和原产品完全一致,不允许有第二套。 AI 只是给用户多了一个入口,不代表用户多了权限。
坑二:让 AI 直接写数据。
有段时间我们让 draft_followup 直接落库,理由是"草稿还要人确认,多此一举"。结果一次测试中,AI 把客户的销售阶段从"已报价"改成了"已签约"。原因很简单,客户的历史消息里有一句"我们下周签约"。
信息没错,但"下周签约"和"已签约"是两个状态。AI 分不清预测和事实。从此所有写操作一律走草稿确认流程,一条例外都没有。
坑三:token 成本开始显形。
客服场景的成本可以忽略,因为 FAQ 命中率六成,真正走 LLM 的不多。业务助手不一样:每个销售每天用十几二十次,每次调用要带客户历史,几千 token 起步。第一个月账单出来,客户问了一句"这个费用是怎么回事"。
我们的对策:
• 小任务用小模型。 总结、草稿这类任务,换成参数小一档的模型,质量几乎无差,成本低一截。只有复杂任务才用大模型。
• 缓存总结。 客户历史摘要按客户 ID 缓存,当天内重复生成直接返回缓存,不重复调 LLM。
• 截断历史。 只带最近 N 条记录,不是全量历史。全量历史又贵又容易让模型抓不住重点。
成本要省,得在设计阶段就考虑。后面 ChatBI 场景就是按这个思路做的。