很多 Agent 项目从函数调用起步:定义一个 Tool Schema,把参数、返回值交给模型,然后等待它选对函数。对于查询时间、计算哈希这类单步操作,这套方式足够直接;但业务流程一旦要求“先检索知识库,再判断是否创建工单”,单纯增加工具数量很快就会失控。
Solon AI 给出的分层思路是:Tool 负责执行一个动作,Talent 负责完成一类业务任务。Talent 不只是工具集合,还包含 SOP 和激活规则,因此更接近可以交付、测试和治理的产品单元。
Tool 解决动作,Talent 约束过程
可以先用一句话区分两者:
- Tool 约等于函数:输入明确、输出明确,通常不决定业务流程。
- Talent 约等于领域专家:围绕一个目标组织工具,并规定调用顺序、前置条件和停止条件。
例如,get_time、hash_string 和 create_ticket 都适合作为 Tool。它们只需要准确执行动作,不必理解完整业务背景。
“处理客户的产品故障”则更适合成为 Talent,因为它通常包含一段 SOP:
- 提取产品、版本和错误现象。
- 检索知识库,寻找已知解决方案。
- 判断检索结果是否足以回答。
- 无法解决时,整理证据并创建工单。
- 把答案或工单编号返回给用户。
这里最重要的差别不是工具数量,而是流程约束是否被显式表达。如果只把 search_kb 和 create_ticket 同时暴露给模型,模型可能跳过检索直接创建工单。Talent 则可以把“创建工单前必须完成检索”写进 SOP,并将其纳入测试。
为什么把所有 API 塞进上下文会出问题
当系统只有三五个函数时,模型还能较稳定地区分用途。工具增长到几十甚至上百个后,会出现几类工程问题:
- Schema 占用大量上下文,挤压用户历史、知识片段和任务状态。
- 名称相近的 API 增加误选概率,例如
create_case、create_ticket和open_incident。 - 业务规则散落在 Tool 描述或系统提示词中,难以审查和版本化。
- 每次增加 API 都可能影响其他任务,回归测试范围持续扩大。
Talent 可以充当能力路由层。入口阶段只选择“售后支持”“退款审核”或“账号恢复”等少量 Talent;激活后,再向模型提供该 Talent 允许使用的工具和 SOP。这样做并不能消除模型的不确定性,但能缩小决策空间,也让权限控制更清晰。
一个实用判断是:如果能力能通过一次函数调用完成,就优先使用 Tool;如果任务包含多个步骤、业务前置条件、失败分支或审计要求,就考虑 Talent。
可以这样实践:用配置描述一个支持类 Talent
下面是一个可改造的 YAML 示例。它不是来源摘要中公开 API 的复刻,而是根据“工具 + SOP + 激活规则”这一概念设计的最小配置。可以把字段映射到自己的 Agent 框架。
id: product_support
name: 产品故障处理
activation:
any_intent:
- product_error
- cannot_start
- unexpected_behavior
required_context:
- product_name
sop:
- id: collect_context
instruction: 收集产品版本、错误信息和复现步骤
- id: search_knowledge
tool: search_kb
required: true
- id: answer_if_supported
condition: search_knowledge.confidence >= 0.80
instruction: 根据知识库结果回答,并引用命中的文档标题
- id: escalate
condition: search_knowledge.confidence < 0.80
tool: create_ticket
requires:
- search_knowledge
allowed_tools:
- search_kb
- create_ticket
- get_ticket_status
limits:
max_tool_calls: 5
require_confirmation_before_write: true
运行前需要根据实际系统修改意图名称、置信度定义和工具标识。尤其不要把模型自报的 confidence 直接当作可靠概率;更稳妥的做法是结合检索分数、结果数量和规则判断。
还可以在执行层增加一道确定性校验,避免模型绕过 SOP。下面的 Python 示例可直接运行,演示“检索完成前禁止创建工单”的守卫逻辑:
from dataclasses import dataclass, field
@dataclass
class TalentState:
completed_steps: set[str] = field(default_factory=set)
class PolicyError(RuntimeError):
pass
def search_kb(query: str, state: TalentState) -> list[str]:
state.completed_steps.add("search_knowledge")
return [] if "unknown" in query.lower() else ["Restart the service and retry."]
def create_ticket(summary: str, state: TalentState) -> str:
if "search_knowledge" not in state.completed_steps:
raise PolicyError("Knowledge-base search must run before ticket creation")
return "TICKET-1042"
def handle_issue(query: str) -> str:
state = TalentState()
articles = search_kb(query, state)
if articles:
return articles[0]
return create_ticket(query, state)
if __name__ == "__main__":
print(handle_issue("unknown startup error"))
执行命令:
python talent_guard.py
预期输出为 TICKET-1042。如果直接调用 create_ticket 而没有执行 search_kb,程序会抛出 PolicyError。这类约束应该落在运行时,而不是只写在提示词里。
Talent 也需要版本、测试和权限边界
把 SOP 封装成 Talent 后,治理问题并不会自动消失。团队仍需把它当成产品代码维护。
建议至少覆盖以下测试:
- 激活测试:哪些请求应该或不应该进入该 Talent。
- 顺序测试:写操作前是否执行了必需的读取、检索或校验。
- 工具白名单测试:Talent 是否只能访问声明过的 Tool。
- 失败分支测试:超时、空结果、参数缺失时是否停止或转人工。
- 回归测试:修改 SOP 或工具描述后,历史任务是否仍能通过。
权限也应按 Talent 收敛。查询类 Talent 通常不需要写权限;创建退款、删除资源或修改账号的 Talent,则应要求用户确认、幂等键和审计日志。即使模型选择正确,也要防止重试造成重复写入。
采用时的决策清单
不必把所有 Tool 立即包装成 Talent。可以从那些已经出现流程事故、工具混淆或提示词膨胀的任务开始:
- 单步、无副作用、参数稳定:保留为 Tool。
- 多步、有前置条件或失败分支:封装为 Talent。
- 涉及写操作和外部副作用:在 Talent SOP 之外增加代码级守卫。
- 工具数量快速增长:先路由 Talent,再按需加载 Tool Schema。
- 业务规则经常变化:为 Talent 配置建立版本号、评测集和发布记录。
Tool 是 Agent 的手,Talent 更像带操作规程的岗位。真正可靠的系统不会只期待模型“理解应该怎么做”,而会把工具范围、步骤依赖和安全边界共同编码进可测试的执行单元。