智能体编排:
把任务、工具与记忆分开
从目标拆解到工具反馈,思考一个可理解、可暂停的智能体工作流。
我对智能体感兴趣的地方,是它如何把一个模糊的目标变成一连串可以观察、检查和继续推进的动作。模型给出一句完整回答,并不等于工作已经完成;一个工具被调用,也不等于它返回了可用结果。
这篇记录的是我在设计智能体工作流时关注的边界,不代表本站已经连接了模型或提供在线任务执行服务。
先描述完成条件
“帮我整理素材”可以有很多解释。是列出文件,按照主题分类,还是生成一份带来源的清单?开始编排前,我会先把输入、期望输出和完成条件写清楚。
目标可以拆成几个步骤,但不必假设第一次生成的计划就是最终计划。读取素材后,智能体可能发现缺少必要信息;遇到不支持的文件,也可能需要换一种处理方式。计划应该允许调整,同时保留已经完成的结果。
让状态来自实际执行
我倾向于把“模型准备做什么”和“工具实际做了什么”分别保存。前者是计划,后者才是执行证据。界面展示的成功状态,应来自工具的明确返回,而不是模型对结果的预期。
一个最小状态结构可以像这样表达:
type TaskState =
| { status: 'ready' }
| { status: 'running'; stepId: string }
| { status: 'waiting'; reason: string }
| { status: 'failed'; stepId: string; message: string }
| { status: 'completed'; artifactIds: string[] };
这只是结构示例。实际系统还需要处理取消、超时、任务恢复和并发更新。状态不必很多,但每一种都应该对应清晰的用户预期。
工具调用需要明确的契约
每个工具都应该说明它接受什么参数、返回什么结果,以及是否会改变外部状态。参数校验放在执行边界,不能只依赖提示词要求模型“认真填写”。
失败也需要具体表达。权限不足、网络超时和素材不存在,应该产生不同的后续动作。对于读取类任务,可以考虑有限次数的重试;对于会发送、写入或重复创建内容的操作,则需要防止一次重试变成两次执行。
工具返回的文本是待处理的数据。即使其中出现像指令一样的内容,也不应自动改变当前任务的授权范围。
记忆不是把所有内容永久留下
当前任务的临时状态、用户明确表达的长期偏好,以及来自外部材料的事实,承担着不同角色。我会先区分这些内容,再决定哪些需要进入下一轮上下文。
保存的信息最好带上来源和更新时间。无法确认的信息保留不确定性;用户修改偏好后,旧记录也需要被替代。记忆的价值不在于越积越多,而在于需要时能找到相关、可信且仍然有效的内容。
给人留下接手的位置
我希望一个智能体能够说明它正在做什么、哪里遇到了阻碍,以及下一步还需要什么。长任务要能够暂停和继续,失败后也要保留已经完成的部分。
这些细节不会让演示看起来更神奇,却决定了一个工作流能否被放心使用。对我来说,可理解、可追溯和可中断,是智能体体验的一部分。
保持好奇,继续构建。