当一个复杂任务需要多个 Skill 协作完成时,编排逻辑应该放在哪里?Agent 核心还是 Skill 内部?
面试官:“当一个复杂任务需要多个 Skill 协作完成时,编排逻辑应该放在 Agent 核心还是 Skill 内部?你怎么设计?”
候选人:
“这是我设计多 Skill 协作时反复权衡过的问题。结论是:宏观的流程编排一定要放在 Agent 核心,Skill 内部只保留自己粒度的微观步骤。 如果反过来,让 Skill 之间互相调用做串联,短期看似灵活,长期一定会失控。
我分三层把这个决策逻辑讲清楚。
一、为什么编排不能下沉到 Skill 内部?
如果把编排逻辑写死在 Skill 内部,比如“机票预订 Skill”里硬编码调用“酒店预订 Skill”和“支付 Skill”,会有三个致命问题:
-
可复用性崩塌:同一个“支付 Skill”,在订机票、点外卖、买电影票时都要被编排,如果每个上游 Skill 都自己写调用逻辑,代码重复且不一致。支付 Skill 改了接口,所有调用它的 Skill 都得改。
-
维护成本爆炸:编排链路的修改(比如双十一要在预订机票前增加“风险校验”)如果是 Skill 内部硬编码,就需要找到并修改所有相关 Skill,而它们可能由不同团队维护,改一个流程动全身。
-
缺乏全局视野:Agent 无法在宏观层面看到完整的任务执行图,不能做全局优化(比如并行调用多个无关 Skill、提前预加载资源),也无法统一处理异常和超时。错误恢复逻辑散落在各个 Skill 里,容易遗漏或相互冲突。
二、正确的分层:Agent 核心做指挥,Skill 做执行
我推荐的架构是:Agent 核心内建一个“编排引擎”,它负责将复杂意图分解成 Skill 调用 DAG,并调度执行。Skill 只暴露自己的能力和参数,完全不关心自己会被谁调用、在什么顺序中被调用。
这个编排引擎的工作流程如下:
-
意图解析与规划:收到用户复杂意图(如“帮我规划一个三天上海出差行程”),编排引擎调用大模型或规则引擎,将意图分解成一系列子任务,每个子任务对应一个 Skill。生成一个有向无环图(DAG),节点是 Skill,边是依赖关系(如“订酒店”依赖“确认机票时间”)。
-
动态调度与并行:编排引擎根据 DAG 拓扑排序执行。无依赖的 Skill 自动并行调用(比如同时查天气和查疫情政策),有依赖的串行。这是 Skill 内部做不到的全局优化。
-
异常处理与补偿:编排引擎在 DAG 每个节点上挂载统一的异常处理策略(重试、降级、跳过、人工介入)。如果某个 Skill 失败,引擎根据 DAG 决定是否执行补偿 Skill(如“取消已订的机票”)。这种跨 Skill 的补偿逻辑,放在任何一个 Skill 内部都不得体。
-
上下文传递与状态持久化:编排引擎维护一个全局的“任务上下文”对象,上游 Skill 的输出自动成为下游 Skill 的输入的一部分,不需要 Skill 之间直接传参耦合。这个上下文可以被持久化,支持长任务暂停和恢复。
三、Skill 内部的“微观编排”
Skill 内部当然也可以有自己的步骤,比如“支付 Skill”内部可能包含“风控检查 → 扣款 → 发送账单”等子步骤。但这种编排是该 Skill 自己业务域内部的流程,不涉及其他 Skill。它的边界是:只编排自己域内的工具和 API,绝不直接调用另一个 Skill。
用一句话区分:Agent 编排“谁来做”,Skill 编排“怎么做”。
两种编排模式对比¶
| 维度 | 编排在 Skill 内部(去中心化) | 编排在 Agent 核心(中心化) |
|---|---|---|
| 复用性 | 差,每个 Skill 重复写调用逻辑 | 好,Skill 只暴露能力,被任意编排 |
| 全局优化 | 无,各 Skill 各自为政 | 可并行、预加载、全局超时控制 |
| 异常处理 | 分散,易遗漏 | 统一重试、降级、补偿策略 |
| 可维护性 | 改流程需改多个 Skill | 只需调整编排 DAG 配置 |
| 动态适应性 | 无法根据上下文改变流程 | 可根据用户画像、历史动态调整 DAG |
| 开发体验 | Skill 开发者需了解全局 | Skill 开发者只关心自己域 |