
把 Agent 理解成“会调工具的聊天机器人”,在企业里一定会踩坑。真正的问题不在对话质量,而在这些:
所以正确姿势不是“给模型接更多工具”,而是把它当成一个有权限、有预算、有审计、有确认环节的内部员工来设计:
不是所有流程都适合 Agent。适合的典型特征是:步骤多但有明确目标、输入是自然语言或半结构化、人工做起来重复且耗时、错了可回滚或有人确认。
不适合的是:强合规审批、不可逆的高风险操作、需要跨部门协商的判断、数据质量极差且无标准的流程。
一张实用的筛选表:
候选场景 | 步骤多 | 输入不规范 | 错了能回滚 | 有人复核 | 结论
工单分类分发 | 是 | 是 | 是 | 是 | 适合
差旅报销预审 | 是 | 是 | 是 | 是 | 适合
生产配置变更 | 是 | 否 | 否 | 需强审 | 谨慎
客户合同签署 | 否 | 否 | 否 | 是 | 不适合从这张表出发,第一版 Agent 应该选错了能回滚、且本来就有复核环节的流程。这样即使 Agent 判断失误,也不会造成不可逆后果。
不要写“做一个智能助手”。要写清楚它做什么、不做什么、失败怎么办:
场景:客服工单分类与分派
输入:用户工单文本 + 用户等级
输出:category / urgency / 建议处理组 / 处理建议
允许工具:
- 读取工单详情(只读)
- 查询知识库(只读)
- 写入分类标签(低风险,可回滚)
禁止:
- 修改工单状态为"已关闭"
- 直接回复用户
- 访问其他用户的工单
失败行为:
- 无法判断时输出 category=其他,转人工队列
- 工具连续失败 2 次,终止并转人工
验收:
- 200 条历史工单,分类准确率不低于人工基线
- 越权调用率 0
- 平均步数 < 5,P95 延迟 < 8s“禁止”一栏是这张卡的核心。企业 Agent 的安全边界不是靠提示词说“请不要”,而是靠工具权限在代码里拦住。
Agent 选错工具、传错参数,绝大多数不是模型笨,而是工具描述写得像谜语。
好的工具定义要包含:做什么、什么时候用、参数含义和约束、返回什么、失败怎么表示。
TOOLS = {
"get_ticket": {
"desc": "按工单ID读取工单详情。仅用于获取当前工单信息。",
"params": {"ticket_id": "字符串,格式 TK-数字,必填"},
"risk": "read",
"returns": "{title, content, user_level, status}",
},
"search_kb": {
"desc": "在知识库中检索处理方案。输入问题描述,返回最相关3条。",
"params": {"query": "字符串,10-200字"},
"risk": "read",
"returns": "[{title, snippet, score}]",
},
"set_category": {
"desc": "写入工单分类标签。仅当分类明确时调用,不确定时不要调用。",
"params": {"ticket_id": "同上", "category": "枚举值之一"},
"risk": "write_low",
"returns": "{ok: bool}",
},
}三个要点:工具数量要少(第一版别超过 5 个)、描述里写清“何时不要用”、每个工具标风险等级。风险等级是后面权限校验和人工确认的依据。
这是企业 Agent 和玩具 Agent 最本质的区别。不管模型说什么,执行前都要过一道代码层的策略检查。
ALLOWED = {"read": True, "write_low": True, "write_high": False}
def guard(tool_name: str, args: dict, ctx: dict) -> tuple[bool, str]:
t = TOOLS.get(tool_name)
if not t:
return False, "未知工具"
if not ALLOWED.get(t["risk"], False):
return False, f"高风险工具需人工确认: {tool_name}"
if tool_name == "get_ticket":
if not args.get("ticket_id", "").startswith("TK-"):
return False, "参数格式非法"
if args["ticket_id"] not in ctx["visible_tickets"]:
return False, "无权访问该工单" # 数据级权限
if tool_name == "set_category":
if args.get("category") not in {"退款", "物流", "账号", "其他"}:
return False, "枚举值非法"
return True, ""注意这里做了两层检查:工具级权限(能不能用这个工具)和数据级权限(能不能操作这条数据)。企业场景里,第二层才是事故高发区——Agent 逻辑没错,但它看到了不该看的工单。
护栏还包括:最大步数、总超时、单任务预算、同一工具重复调用上限。防止 Agent 陷入循环,把接口和费用一起烧掉。
企业里最忌讳的是“Agent 自己就把事办了”。凡是不可逆或影响外部用户的动作,都要走确认。
最小实现是一个待确认队列:
PENDING: dict[str, dict] = {}
def request_approval(task_id: str, tool: str, args: dict) -> str:
aid = f"AP-{len(PENDING)+1:04d}"
PENDING[aid] = {"task_id": task_id, "tool": tool, "args": args, "status": "pending"}
return aid
def approve(aid: str, operator: str, ok: bool):
item = PENDING[aid]
item["status"] = "approved" if ok else "rejected"
item["operator"] = operator
audit_log(aid, item)关键不是代码,而是流程:谁有审批权、审批要看到什么信息、拒绝后 Agent 怎么继续。建议审批界面必须展示“Agent 想做什么、依据是什么、影响范围是什么”,否则审批就是走过场。
企业环境里,“Agent 做错了”不是最可怕的,“说不清它为什么这么做”才是最可怕的。
每条审计记录至少包含:任务 ID、时间、模型版本、提示词版本、每一步的工具调用和参数、护栏判定结果、人工审批记录、最终输出、耗时与 toke
def audit_log(event_id: str, payload: dict):
record = {"event_id": event_id, "ts": now_iso(), **payload}
with open("audit.jsonl", "a", encoding="utf-8") as f:
f.write(json.dumps(record, ensure_ascii=False) + "\n")审计日志的价值在于三个场景:事故复盘、合规检查、评估集建设。尤其是第三点——线上被护栏拦下的案例,是最好的评估集来源。
“试了几个问题感觉不错”不能作为上线依据。至少要有一份固定任务集:
评估指标不只是“答得对不对”,更重要的是:任务完成率、越权拦截率、平均步数、人工转接率、成本。其中越权拦截率必须是 100%,这一项不达标就不能上线。
每次改提示词、换模型、加工具,都要跑一遍。回归不通过,不许发布。
企业 Agent 的上线建议:
转人工率突然升高通常意味着上游数据变了,或者模型版本变了。这个指标比“准确率”更早发出预警。
一个实用的审查提示词:
请审查下面 Agent 工具调用代码,只输出问题表格:
问题类型 | 位置 | 风险说明 | 修改建议
重点检查:是否有工具级权限校验、是否有数据级权限校验、
高风险动作是否强制人审、是否有步数和预算上限、是否记录审计日志。
不要重写代码,不要评价模型效果。企业 AI Agent 的正确姿势,不是“给它更多工具和更大自主权”,而是把它当成有权限、有预算、有审计、有确认环节的内部成员:场景边界清楚、工具少而清晰、权限分级且代码强制、高风险动作人审、每一步可审计、固定评估集常跑、灰度上线持续复盘。
代码可以很少,但权限不能只写在提示词里,审计不能省,确认环节不能跳。记住一句话:Agent 的能力上限由工具决定,可信下限由护栏和审计决定;企业敢用的不是最聪明的 Agent,而是最可控的 Agent。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。