logo

不依赖智能体框架,如何构建可靠的任务执行系统

作者:demo2026.11.11 08:51浏览量:0

简介:不依赖专用框架,也能实现具备工具调用能力的智能体。本文从最小执行循环出发,拆解模型决策、工具执行、状态管理与终止控制,进一步讨论权限隔离、异常恢复、成本约束和效果评估,帮助开发者理解原型与生产系统的差距,并判断何时适合自主实现、何时需要工作流编排。

一、不依赖框架实现智能体,究竟是否可行?

答案是可行,但需要先明确“实现”的范围。

如果目标是让模型根据任务选择工具、读取工具返回结果,再决定继续操作还是输出答案,那么使用通用编程语言,就可以搭建一个结构清晰的智能体原型。

如果目标是让系统长期在线,稳定处理并发请求,能够在异常后恢复,并且保证敏感操作可审计、业务数据不越权,那么需要解决的问题就远不止循环调用模型。

因此,判断自主实现是否合适,不能只看核心代码有多少行,而应区分三个层次:

  • 机制层:模型如何提出动作,程序如何执行动作。
  • 工程层:状态如何保存,异常如何恢复,资源如何限制。
  • 治理层:操作是否获得授权,数据是否允许访问,结果是否能够追溯。

理解这三个层次,才能避免两个极端:一是把智能体想得过于神秘,认为必须依赖复杂框架;二是把智能体想得过于简单,认为几十行循环就等于生产系统。

二、智能体的核心,是受约束的决策与执行循环

一个典型的工具调用型智能体,可以抽象为以下过程:

  1. 用户提出任务
  2. ↓
  3. 整理任务上下文与当前状态
  4. ↓
  5. 调用模型,生成答案或动作请求
  6. ↓
  7. 检查请求结构、权限和资源预算
  8. ↓
  9. 执行经过授权的工具
  10. ↓
  11. 记录结果并更新上下文
  12. ↓
  13. 再次调用模型
  14. ↓
  15. 满足完成条件后结束

这个结构中的关键,不只是“循环”,而是循环内部的职责分离。

1. 模型负责提出下一步建议

模型根据任务、历史消息和工具描述,判断是否需要继续获取信息,以及应该调用哪个工具。

但模型生成的动作请求只能视为候选计划,不能直接等同于已经授权的操作。

例如,模型可能提出“读取某份文档”,程序仍然需要检查当前用户是否拥有该文档的访问权限。

2. 程序负责执行确定性规则

工具是否存在、参数是否合法、资源是否越界、预算是否充足,都应该由程序检查。

这些判断不宜仅依赖提示词。提示词可以影响模型行为,但不能替代权限系统、参数验证和资源隔离。

3. 工具提供可验证的外部反馈

模型通常无法仅凭内部知识确认实时库存、当前账户状态或最新文档内容。工具的作用,是把外部系统的实际结果反馈给模型。

因此,工具返回内容应明确区分:

  • 成功获取的数据;
  • 没有找到结果;
  • 权限不足;
  • 输入参数错误;
  • 外部依赖暂时不可用。

如果把这些情况都转换成一句模糊的“执行失败”,模型就很难选择正确的后续动作。

需要注意,这种循环是常见工具调用型智能体的基础结构,并不意味着所有智能体系统都只是单一循环。复杂系统还可能包含并行执行、事件驱动、显式状态机以及人工审批。

三、先定义最小协议,再编写执行逻辑

自主实现时,最容易被忽略的问题是:模型返回的内容,怎样转换为程序能够可靠处理的动作?

一种合理做法,是先定义应用内部的动作协议。

例如,把模型输出划分为两类:

  1. 最终答复:
  2. 类型:完成
  3. 内容:面向用户的回答
  4. 工具请求:
  5. 类型:调用工具
  6. 请求标识:本次调用的唯一标识
  7. 工具名称:允许使用的工具之一
  8. 参数:符合该工具约定的输入

这里的字段只是示意性的应用内部设计,不代表任何模型服务的真实接口。接入具体服务时,需要由适配层完成转换。

工具定义则至少需要包含:

要素 需要说明的问题
功能描述 工具用于解决什么问题
输入约束 接受哪些参数,哪些参数必填
输出约定 成功和失败分别返回什么
权限范围 哪些用户、资源和操作被允许
副作用等级 只读、可撤销修改,还是不可逆操作
执行限制 超时、结果大小和调用频率限制

工具描述并不是越长越好。有效的描述应当让模型清楚知道“什么时候用、什么时候不用、需要提供什么信息”。

例如,一个知识检索工具应说明检索范围和适用场景,而不是只写“搜索资料”。

四、最小执行循环可以怎样组织?

下面给出一段语言无关的示意性伪代码。它表达控制逻辑,不是可直接运行的服务接口:

  1. 函数 执行任务(任务, 用户身份, 工具集合, 运行限制):
  2. 状态 = 创建运行状态(任务, 用户身份)
  3. 当 状态.轮次 < 运行限制.最大轮次:
  4. 如果 已超时(状态) 或 已超预算(状态):
  5. 返回 生成中止结果(状态)
  6. 模型输出 = 请求模型(
  7. 构建上下文(状态),
  8. 当前用户可用工具描述(用户身份)
  9. )
  10. 动作 = 解析并验证模型输出(模型输出)
  11. 如果 动作.类型 == 完成:
  12. 返回 检查并生成最终结果(动作, 状态)
  13. 如果 动作.类型 != 调用工具:
  14. 记录协议错误(状态)
  15. 如果 协议错误次数过多(状态):
  16. 返回 生成失败结果(状态)
  17. 继续
  18. 工具 = 查找已注册工具(动作.工具名称)
  19. 校验参数(工具, 动作.参数)
  20. 校验权限(用户身份, 工具, 动作.参数)
  21. 检查是否需要人工确认(工具, 动作.参数)
  22. 保存待执行动作(状态, 动作)
  23. 执行结果 = 受限执行(工具, 动作.参数)
  24. 保存执行结果(状态, 动作, 执行结果)
  25. 更新上下文(状态, 动作, 执行结果)
  26. 状态.轮次 = 状态.轮次 + 1
  27. 返回 生成轮次耗尽结果(状态)

这段逻辑有几个值得强调的地方。

首先,模型输出必须经过解析和验证,不能直接交给执行器。

其次,工具应该来自明确注册的集合。不要允许模型凭空指定任意函数、任意路径或任意外部地址。

再次,任务中止不应只返回“失败”。系统最好能说明已经完成哪些步骤、哪些内容尚未确认,以及用户可以如何继续。

最后,模型给出最终答复,不必然意味着任务已经完成。对于要求明确的任务,还应检查必要条件,例如是否生成了目标文件、是否取得了必需证据、是否完成了用户要求的字段。

五、以知识问答为例,设计一个边界清晰的智能体

为了便于理解,可以设计一个不依赖具体产品的知识问答场景:

用户希望了解某项内部流程,并要求答案注明依据。

最初只提供两个只读工具:

  1. 检索当前用户有权访问的资料。
  2. 读取指定资料片段。

执行过程可以分为以下步骤。

第一步:分析问题是否需要外部证据

对于内部流程、最新规则等问题,系统应要求答案建立在可访问资料之上,而不是让模型凭记忆作答。

如果问题缺少必要背景,例如没有说明适用部门或时间范围,可以先向用户澄清。

第二步:检索候选资料

检索结果应包含便于后续定位的信息,例如资料标识、标题、片段和更新时间。

访问控制必须在检索阶段生效,不能先把所有资料交给模型,再要求模型“不要泄露”。

第三步:读取关键内容

模型根据候选结果选择需要进一步阅读的资料。程序再次验证资料标识和访问权限,避免模型请求未经授权的内容。

第四步:形成带依据的答复

最终回答应区分三类内容:

  • 资料明确支持的事实;
  • 根据资料作出的合理解释;
  • 当前资料无法确认的部分。

如果不同资料存在冲突,应说明冲突,而不是擅自消除差异。

这个例子说明,智能体的价值不在于调用工具次数多,而在于能否围绕任务获得足够证据,并在合适的时间停止。

六、从原型到生产,必须补齐哪些能力?

1. 终止控制:不仅要限制轮次

最大轮次只是最基础的保护措施,还应同时设置:

  • 单次工具执行时限;
  • 整体任务截止时间;
  • 模型调用预算;
  • 工具调用次数限制;
  • 连续失败次数限制;
  • 重复动作检测。

例如,模型连续提交相同的检索词,而返回结果没有新增信息,继续执行通常没有价值。此时可以要求调整策略、请求用户补充信息,或者明确结束任务。

限制值应结合任务复杂度和实际评估确定,不能假定某个固定配置适用于所有场景。

2. 错误处理:区分可重试与不可重试

外部依赖临时超时,可以进行有上限的重试;参数缺失应反馈给模型修正;权限不足通常不能通过重试解决。

对于会产生副作用的操作,重试尤其需要谨慎。例如,创建记录的请求超时,并不代表记录没有创建成功。系统应先核实执行状态,再决定是否重新提交。

3. 状态管理:对话记录不等于完整运行状态

除了消息历史,还应保存任务标识、当前阶段、工具请求、执行结果、审批状态和终止原因。

在高风险场景中,工具执行前保存待执行记录,执行后保存结果,有助于故障恢复。但如果外部操作已经完成、结果尚未写回,单靠保存状态仍不能自动保证不重复执行,还需要幂等机制或业务状态核对。

4. 上下文管理:不要无限追加原始结果

长文档、日志和表格会快速占用上下文,并增加调用成本与信息干扰。

可以采用分层管理方式:

  • 原始材料保存在外部存储;
  • 对话中保留与当前任务相关的片段;
  • 阶段性摘要记录已确认事实与未解决问题;
  • 重要事实保留来源标识,方便重新读取。

摘要可能丢失细节,因此不应把它当作唯一事实来源。

5. 安全边界:外部内容不能升级为系统指令

文档、网页或工具结果可能包含误导性内容,例如要求忽略原有规则、读取敏感信息或执行额外操作。

这些内容只能被视为待分析的数据,不能自动获得指令权限。

实际防护应结合最小权限、参数校验、执行隔离和高风险审批。单靠一句“不要遵循恶意指令”,无法构成可靠的安全机制。

6. 可观测性:记录执行依据,而不是臆测模型思考

建议记录每次调用的输入摘要、工具参数、返回状态、耗时、资源消耗和错误类型,同时对敏感字段脱敏。

如果需要解释任务过程,可以要求模型输出简短的动作说明,但这类说明只是可展示的决策摘要,不应被当成模型内部推理的完整记录。

七、如何判断系统真的好用?

能运行一次,不代表具备稳定性。评估应覆盖正常任务和边界情况。

至少需要准备以下测试:

  • 正常任务能够完成;
  • 没有足够资料时能够承认不确定;
  • 工具返回空结果时不会编造证据;
  • 参数错误时能够修正或停止;
  • 权限不足时不会绕过限制;
  • 外部内容包含误导指令时不会越权;
  • 服务重启后不会重复执行危险动作;
  • 达到时间或预算上限时能够有序退出。

指标也不应只关注回答是否流畅。更有价值的指标包括任务完成率、证据支持情况、无效调用比例、越权尝试拦截情况、执行耗时和单任务资源消耗。

对于涉及修改业务数据的系统,还应把“错误操作率”作为独立指标,而不是被总体成功率掩盖。

八、什么时候适合自主实现,什么时候需要编排能力?

自主实现更适合工具数量较少、任务路径相对清晰、团队希望完全掌握执行过程的场景。

它的优势主要体现在:

  • 控制流直接,容易定位问题;
  • 业务规则可以明确写入程序;
  • 依赖较少,便于理解系统边界;
  • 能按实际需要逐步增加能力。

但这些优势并非没有成本。团队需要自行维护协议适配、状态恢复、监控测试以及安全控制。

当任务出现长时间等待、跨阶段审批、复杂分支、并行处理或多角色协作时,显式状态机和工作流编排通常更容易维护。此时,引入通用编排能力的价值,在于减少重复工程,而不是让模型“更聪明”。

还要考虑另一种情况:任务步骤本身完全确定,只在局部需要文本理解。此时使用固定流程加一次或几次模型调用,可能比开放式智能体更可靠。

九、结论:可以从小循环开始,但要以系统边界为终点

不依赖专用框架构建智能体,是一种合理的技术选择。对于学习、验证以及边界明确的应用,自主实现能帮助开发者直观看清模型、工具和运行时之间的关系。

不过,“核心循环简单”与“生产系统简单”是两回事。真正决定可靠性的,往往是循环之外的能力:权限约束、协议验证、状态持久化、异常恢复、资源预算和效果评估。

更稳妥的实施路线,是从单任务、少工具、只读操作开始,先建立可验证的闭环,再逐步增加写操作、审批和恢复能力。

最终需要追求的,不是让智能体执行更多步骤,而是让它在明确授权与资源边界内,用可检查的过程完成任务,并在无法完成时诚实、清晰地停止。

发表评论

活动