☰
智能体开发实战:工具调用与任务回执机制全解析
2026/10/9 8:56:58 网站建设 项目流程

这期 GitHub 日报,本来想挑几个新的智能体仓库聊聊,结果翻了一圈发现,大量开源项目还是停留在“能聊天”的阶段:用户问一句,大模型回一句,交互看起来丝滑,但真要让它去查库存、发消息、改配置,就卡住了。问题不是模型不会说话,而是没把“手”和“回执”接上。本文就从智能体开发的角度,拆解“会说话”之外最关键的两块能力:工具调用和任务回执,并结合 GitHub 上常见的开源框架,给出一套可复用的实战方案。

先说明,这篇文章不是单纯测评某一个人的项目,而是以 GitHub 上智能体仓库的共性问题为入口。无论你是刚开始接触智能体开发,还是已经在用 Dify、Coze、FastGPT 这类平台搭过 Agent,只要你想让智能体真正完成业务动作,这篇文章都值得看完。读完你会理解 Function Calling 的运行机制,能自己写一个带工具执行和状态回执的最小智能体,也知道怎么把同样的思路迁移到 Dify、Coze 等平台上。

1. 智能体“会说”之外,还缺什么

1.1 “手”:把对话变成动作

先来想一个很常见的场景:用户对智能体说“帮我查一下最近一小时的服务器错误日志”。纯对话模型只能给出一个笼统的回答,比如“你可以先去日志平台查看”,因为它只负责生成文本,不具备访问日志系统的能力。要让智能体真正完成这个动作,必须让它可以调用外部工具,比如查询日志的 API、执行命令的脚本、操作数据库的 SQL 接口。这个能力,就是智能体的“手”。

在技术圈,这个能力有一个更正式的名字:Function Calling,也叫 Tool Use、Tool Calling。它指的是大模型在生成回复时,不是直接输出最终文本,而是先输出一个“我要调用某个工具,参数是什么”的结构化指令,再由外部系统执行这个指令,把执行结果返回给模型,模型再基于结果生成最终回复。可以把它理解成:模型的大脑负责分析任务、拆解步骤、判断调哪个工具;工具执行层负责真实世界里的动作。没有这层“手”,模型永远只是一个“嘴替”。

在 GitHub 上搜索 agent、智能体相关仓库时,最常见的现象是:演示里全是多轮对话、角色设定、Prompt 优化,但一涉及真实业务系统就要自己补工具层。另一些成熟项目则会晒出 Tools、Plugins、Actions 这类目录,把可执行的函数和 API 接口集中在固定的地方。判断一个智能体是否具备生产能力,首先就要看它有没有一把靠谱的“手”。

1.2 “回执”:让每次执行都有结果可追踪

有了“手”之后,第二个问题马上出现:手伸出去,做事成没成,结果是什么,原因是什么,总得有一个反馈。很多开发者在初学智能体时,会直接把工具返回的原始内容丢回给大模型,让模型“看着办”。这在 Demo 阶段没有太大问题,但一旦进入生产环境,就会遇到几个麻烦:某个工具调用失败时,系统分不清是网络问题还是参数问题;异步任务执行了几分钟,用户不知道进度;多个智能体协作时,上游智能体也不知道下游节点到底完成没有。

所以我们还需要“回执”。这个词有点像快递单号回执,指的是每次工具执行之后,以结构化数据形式返回的一份执行结果记录。它至少应该包含:任务标识、执行状态、返回数据、错误信息、执行耗时等。有了回执,智能体才能准确判断“接下来是继续执行、换一个工具,还是直接告诉用户失败原因”;有了回执,平台才能做日志审计、指标监控和失败重试;有了回执,多智能体之间才有可靠的协作依据。

“会说”是智能体的表达层,“手”是智能体的行动层,“回执”则是行动层和表达层之间的反馈闭环。很多团队的智能体项目迟迟无法落地,不是模型选得不好,而是“手”和“回执”没有接上。接下来,我会用最简单的代码把这条链路串起来。

2. 环境准备与版本说明

2.1 运行环境

为了让这篇文章里的代码能直接运行,我们不依赖任何收费的大模型 API,也不需要额外安装第三方 SDK,只使用 Python 标准库。这样你可以把关注点完全放在工具调用和回执机制本身,而不是被环境配置卡住。

  • 操作系统:Windows 10/11、macOS、Linux 均可
  • Python 版本:3.10 及以上
  • 依赖:无第三方依赖,只需要标准库json、time、uuid
  • 建议 IDE:VS Code、PyCharm,或者直接使用命令行运行

如果你希望把下面的代码改成连接真实大模型,需要准备一个支持 Function Calling 的 API 服务。比较常见的方式是使用 OpenAI 兼容接口,或者使用 Dify、Coze、FastGPT 这类平台的开放接口。文末会给出迁移思路。

2.2 示例项目结构

实战部分我们用一个极简的 Mini Agent 项目来演示。先创建文件夹,目录结构如下:

mini-agent/ ├── agent.py # 智能体主逻辑 ├── tools.py # 工具注册与工具实现 ├── receipt.py # 回执数据结构 └── main.py # 入口运行文件

如果你不想手动创建目录,也可以直接把所有代码写进一个文件里。为了让逻辑更清晰,我更推荐按上面的结构拆分。下面的代码片段都会标注文件路径,复制时注意文件对应关系。

3. 核心知识拆解:工具调用与回执

3.1 Function Calling 的基本流程

先来看一个标准 Function Calling 的完整流程。这个流程无论是底层大模型 API,还是 Dify、Coze 这类平台,本质上都是一样的。下面用编号把这个链路拆开:

  1. 用户输入自然语言指令,比如“帮我查一下订单 10086 的状态”。
  2. 大模型判断需要调用某个工具,并输出一个结构化的工具调用请求,里面包含工具名称和参数。
  3. 外部系统根据工具名称找到对应的处理函数,把参数传进去执行。
  4. 外部系统拿到真实结果后,生成一份回执,返回给大模型。
  5. 大模型读取回执内容,结合用户原始问题,生成一段最终回答,例如“订单 10086 已发货,预计三天后送达”。
  6. 如果是多轮任务,模型可能会基于回执继续发起下一个工具调用,重复 2 到 5 步。

这里最容易被忽略的是第 4 步。很多人直接让工具函数打印一行日志,然后把日志返回给模型。这样不是不行,但在复杂场景下,日志和结构化回执是两回事。日志是给人看的,回执是给程序和大模型协同用的。比如日志会写“查询成功”,但程序可能还需要一个status=success字段来触发后续逻辑,还需要一个trace_id来关联日志和请求。所以回执的标准化非常重要。

3.2 回执数据结构

我建议在智能体项目里统一使用一个回执结构。下面是一个精简但实用的 JSON 示例:

{ "trace_id": "a1b2c3d4-1234-5678-9abc-abcdef123456", "tool_name": "query_order", "status": "success", "data": { "order_id": "10086", "state": "shipped", "eta": "3 days" }, "error": null, "duration_ms": 26 }

各字段的作用:

字段含义是否必填说明
trace_id追踪 ID是每次调用生成一个唯一 ID,用于关联日志和任务
tool_name工具名称是标识本次执行了哪个工具
status执行状态是建议取值:success、failed、running、timeout
data成功返回的数据否工具执行成功时返回结构化结果
error错误信息否工具执行失败时返回错误码和错误描述
duration_ms执行耗时否单位毫秒,用于性能分析和重试判断

为什么status要设计成枚举值而不是简单的 true/false?因为一个真实工具可能被异步触发,需要先返回running,后续再通过回调更新为success或failed。比如要启动一个分布式任务,调用接口后任务在后台排队,如果只返回“成功”或“失败”就覆盖不了这种情况。回执本身就是任务状态的一种快照。

3.3 平台中的“手”和“回执”

如果你使用 Dify 这类智能体平台,会发现它已经替你封装了整套流程。Dify 里有一个“工具”模块,可以接入 HTTP 请求、代码执行、数据库查询,也可以自定义 OpenAPI 插件。工作流里把工具节点放在大模型节点前后,实际上就是在编排“手”。而节点之间的输入输出变量,就是“回执”的载体。Dify 中每个工具节点都有输入和输出定义,输出会被保存为结构化字段,供后续节点读取。

Coze 也是类似的设计。Coze 的插件和个人 API 接入,本质上是把外部能力注册成可被大模型调用的工具。在工作流模式里,每个节点执行完成后会输出一个结果对象,这个对象相当于回执。不同的是,Coze 更适合快速搭建面向 C 端的 Bot,而 Dify 更适合企业内部的流程型应用。

不管用什么平台,“手”和“回执”的核心是相通的:提前定义好工具有哪些参数、会返回什么字段、失败时怎么表达。下面我们直接用代码写一套最小可运行的实现。

4. 实战:写一个带手和回执的 Mini Agent

4.1 定义工具注册表

第一步先定义一个工具注册表。这样做的目的,是让智能体的“手”变得可插拔。以后想增加一个工具,只需要在注册表里登记一下,不需要改动主流程。

文件路径:mini-agent/tools.py

# -*- coding: utf-8 -*- """工具定义与注册表。""" from typing import Any, Callable, Dict class ToolRegistry: """工具注册表,维护工具名到具体函数的映射。""" def __init__(self): self._tools: Dict[str, Callable] = {} def register(self, name: str, schema: Dict[str, Any]): """注册一个工具。 Args: name: 工具名称,智能体调用时使用。 schema: 工具的元信息描述,包括参数说明。 """ if name in self._tools: raise ValueError(f"Tool '{name}' already registered.") self._tools[name] = schema def get(self, name: str) -> Dict[str, Any]: """根据名称获取工具信息。""" if name not in self._tools: raise KeyError(f"Tool '{name}' not found.") return self._tools[name] def list_tools(self) -> Dict[str, Any]: """返回全部工具信息,供大模型理解可用能力。""" return self._tools def register_default_tools() -> ToolRegistry: """注册一些默认的示例工具。""" registry = ToolRegistry() # 工具1:查询订单状态 registry.register( name="query_order", schema={ "description": "根据订单号查询订单状态", "parameters": { "order_id": { "type": "string", "description": "订单号,例如 10086", } }, }, ) # 工具2:发送通知消息 registry.register( name="send_notification", schema={ "description": "发送一条通知消息给用户", "parameters": { "message": { "type": "string", "description": "通知内容", } }, }, ) return registry

这里ToolRegistry本质上是一张“手”的名录。为什么还要单独定义 schema?因为真实大模型在 Function Calling 中,会先读取工具的 schema,然后决定调用哪个函数、填充什么参数。Schema 越准确,模型生成的参数就越可靠。虽然我们下面的代码用的是模拟模型,但真实场景中这一步非常关键。

4.2 实现执行器与回执生成

第二步实现工具执行器和回执生成逻辑。这个模块负责真正调用工具函数,并把结果包装成统一的回执。

文件路径:mini-agent/receipt.py

# -*- coding: utf-8 -*- """回执数据结构与生成函数。""" import time import uuid from typing import Any, Dict def generate_trace_id() -> str: """生成唯一追踪ID,用于关联一次工具调用。""" return str(uuid.uuid4()) def success_receipt(tool_name: str, data: Any, duration_ms: float) -> Dict[str, Any]: """生成成功回执。""" return { "trace_id": generate_trace_id(), "tool_name": tool_name, "status": "success", "data": data, "error": None, "duration_ms": round(duration_ms, 2), } def failed_receipt(tool_name: str, error: Any, duration_ms: float) -> Dict[str, Any]: """生成失败回执。""" return { "trace_id": generate_trace_id(), "tool_name": tool_name, "status": "failed", "data": None, "error": { "code": "TOOL_EXECUTION_ERROR", "message": str(error), }, "duration_ms": round(duration_ms, 2), }

接下来是工具执行器,它负责从注册表里找到工具并执行。这里有一个容易踩坑的点:实际工具函数往往比注册表里的 schema 要复杂,有参数校验、依赖注入、网络请求等。我们不希望执行器代码变得臃肿,所以把工具真实逻辑单独写在tools.py里。

文件路径:mini-agent/tools.py(在原有代码上追加)

def query_order(order_id: str) -> dict: """模拟查询订单状态。""" # 模拟网络耗时 time.sleep(0.1) if order_id == "10086": return {"order_id": order_id, "state": "shipped", "eta": "3 days"} return {"order_id": order_id, "state": "unknown"} def send_notification(message: str) -> dict: """模拟发送通知消息。""" # 模拟写入消息队列 time.sleep(0.05) return {"message_id": uuid.uuid4().hex, "content": message}

然后在执行器里做参数绑定。为了简单,这里直接用工具名映射到实现函数:

# 在 tools.py 最后追加 TOOL_IMPLEMENTATIONS = { "query_order": query_order, "send_notification": send_notification, } def execute_tool(tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]: """执行工具并返回回执。""" start = time.time() try: func = TOOL_IMPLEMENTATIONS[tool_name] data = func(**arguments) return success_receipt(tool_name, data, (time.time() - start) * 1000) except KeyError: return failed_receipt(tool_name, f"Tool '{tool_name}' is not implemented", (time.time() - start) * 1000) except Exception as exc: # noqa: BLE001 return failed_receipt(tool_name, exc, (time.time() - start) * 1000)

执行器把所有异常都捕获并转换成了回执,这是非常重要的一点。因为智能体在大模型决策循环中,不应该因为某个工具报错就整体崩溃。工具执行失败本身就是一个有效信息,应该交给大模型去判断是换一种说法还是换一个工具。所以回执里status=failed不是“程序错误”,而是业务流程中的正常反馈。

4.3 模拟智能体决策循环

第三步写智能体的决策循环。真实的大模型会输出结构化的工具调用指令,这里为了让你在没有 API Key 的情况下也能运行,我用一个“模拟模型”代替。它根据用户输入里的关键词,决定调用哪个工具,并生成参数。

文件路径:mini-agent/agent.py

# -*- coding: utf-8 -*- """Mini Agent 决策循环。""" import json from typing import Dict, Any from tools import ToolRegistry, execute_tool, register_default_tools def mock_llm_reason(user_input: str, tools: Dict[str, Any]) -> Dict[str, Any]: """模拟大模型的工具调用决策。 真实场景中,这里会调用支持 Function Calling 的大模型 API, 并传入 tools 描述信息,模型返回一个 tool_call 结构。 """ if "订单" in user_input or "订单号" in user_input: # 简单从文本中提取订单号,真实场景由模型抽取 order_id = "10086" for token in user_input.split(): if token.isdigit(): order_id = token return { "tool_name": "query_order", "arguments": {"order_id": order_id}, } if "通知" in user_input or "发送" in user_input: return { "tool_name": "send_notification", "arguments": {"message": user_input}, } return None def run_agent(user_input: str, registry: ToolRegistry) -> str: """智能体主流程。""" tools = registry.list_tools() decision = mock_llm_reason(user_input, tools) if decision is None: return "我现在只能处理订单查询和消息发送,你可以试着换个说法。" tool_name = decision["tool_name"] arguments = decision["arguments"] # 执行工具,拿到回执 receipt = execute_tool(tool_name, arguments) # 构造给用户的最终回复 if receipt["status"] == "success": data = receipt["data"] if tool_name == "query_order": return ( f"订单 {data.get('order_id')} 当前状态是 {data.get('state')}," f"预计到达时间 {data.get('eta')}。回执ID:{receipt['trace_id']}" ) if tool_name == "send_notification": return f"通知已发送,消息ID:{data.get('message_id')}。回执ID:{receipt['trace_id']}" else: return f"工具执行失败:{receipt['error']['message']},追踪ID:{receipt['trace_id']}" return "执行完成。"

这个循环虽然简单,但已经具备真实智能体决策的骨架:理解用户输入、判断工具、执行工具、读取回执、生成最终回复。你可以把它想象成一个最简版的 ReAct 模式。

4.4 运行与验证

最后写入口文件,把整个流程跑起来。

文件路径:mini-agent/main.py

# -*- coding: utf-8 -*- """程序入口。""" from agent import run_agent from tools import register_default_tools def main(): registry = register_default_tools() test_queries = [ "帮我查一下订单 10086 的状态", "给用户发送一条通知:您的订单已发货", "今天天气怎么样", ] for query in test_queries: print(f"用户:{query}") response = run_agent(query, registry) print(f"智能体:{response}") print("-" * 40) if __name__ == "__main__": main()

在mini-agent目录下运行:

python main.py

预期输出大致如下:

用户:帮我查一下订单 10086 的状态 智能体:订单 10086 当前状态是 shipped,预计到达时间 3 days。回执ID:xxxx ---------------------------------------- 用户:给用户发送一条通知:您的订单已发货 智能体:通知已发送,消息ID:xxxx。回执ID:xxxx ---------------------------------------- 用户:今天天气怎么样 智能体:我现在只能处理订单查询和消息发送,你可以试着换个说法。 ----------------------------------------

到这里,你就已经拥有一个具备“手”和“回执”的最小智能体了。代码里处处是回执的痕迹:每次工具调用都会产生一个trace_id,失败时也有结构化的error信息。这种设计可以直接迁移到真实项目中。

5. 把“手和回执”接到 Dify / Coze 等平台上

5.1 Dify 中的工具与回调

如果你不想从零实现,Dify 是快速上手的方案。Dify 中接入工具的思路如下:在“工具”页面添加一个自定义工具,填写 OpenAPI 规范或直接添加代码函数。之后在应用编排里,把工具节点拖到大模型节点之后。大模型节点负责判断需要调用哪个工具,工具节点负责执行,执行结果会保存为节点变量,下一步的大模型节点可以读取这些变量,从而生成最终回复。

这个过程中“回执”并没有强制要求你定义status字段,但 Dify 的节点本身是有错误处理能力的。你可以给工具节点设置错误分支,比如执行失败时跳转到“失败处理”节点。这是最典型的回执应用:不只是把失败信息堆给用户,而是让工作流根据失败状态做出不同分支。类似地,在 HTTP 请求节点里,响应的状态码、响应体、错误信息都会以结构化方式返回,这就是回执的实体。

5.2 Coze 插件与任务状态

Coze 的做法是把能力封装成插件。插件可以是一个普通 API,也可以是一个工作流。在 Bot 里打开“插件”开关,Coze 的大模型会在对话中根据用户需求自动调用插件。如果你需要更精细的控制,可以使用“工作流”节点:工作流里可以配置多个步骤,每个步骤的输出都带success或error信息。Coze 还支持消息回调,当异步任务完成时,可以通过 Webhook 把状态推送给外部系统。

这里要特别说明:Coze 这类平台虽然降低了开发门槛,但如果你要接入公司内部系统,往往还是需要一个中间层。因为平台的“回执”是给平台内节点用的,外部业务系统可能需要转换成自己的协议。常见做法是搭建一个适配器服务,平台调用适配器,适配器再调用内部系统,最终把内部系统的返回结果包装成平台可识别的字段。

5.3 多智能体协作时的回执传递

当多个智能体协作时,回执的作用会更加明显。比如一个“调度智能体”负责拆分任务,把“查订单”发给订单智能体,把“发通知”发给消息智能体。调度智能体必须等待每个子智能体返回回执,才能判断是否进入下一步。如果子智能体返回status=success,则继续;如果返回status=failed,则选择重试或换一个智能体。这个场景在 GitHub 上的多智能体框架中非常常见。

在实现上,多智能体的回执通常是一个事件对象,包含task_id、agent_name、status、output等字段。子任务完成后,通过消息队列或事件总线把回执发给调度器。调度器维护一张“任务状态表”,只有所有必要子任务都到达终态,才会标记整体任务完成。如果你正在设计多智能体系统,建议一开始就定义好回执规范,否则后期联调会非常痛苦。

6. 常见问题与排查思路

6.1 高频问题表

下面这些问题是智能体接入“手和回执”时最常见的,我整理成表格,方便你快速定位。

问题现象常见原因解决思路
模型总是调用错误的工具工具描述不清楚,或参数命名有歧义优化工具 schema 描述,增加示例参数
工具执行成功但模型回答错误回执数据没有完整传给模型,或模型丢失上下文把回执作为新消息发给模型,保留工具名和原始参数
工具调用一直超时外部接口响应慢,或没有设置超时时间设置请求超时,并返回status=timeout回执
异步任务执行不了把异步任务当成同步等待先返回running回执,通过 Webhook 或轮询更新状态
回执数据格式混乱不同工具返回不同结构统一使用回执包装函数,规范 status 和 data 字段
智能体重复调用同一个失败工具没有读取回执中的失败原因失败回执里补充错误码,让模型根据错误码调整策略
GitHub 上项目下载慢或打不开网络波动或资源加载不稳定优先通过 Releases 下载离线包,把仓库克隆到本地阅读,避免依赖在线预览

6.2 排查步骤

如果你在线上的智能体遇到了“工具执行没反应”的问题,可以按下面的顺序排查:

  1. 先看有没有生成工具调用请求。打开智能体日志,确认大模型是否真的输出了tool_name和arguments。如果没有,问题出在模型侧,需要优化工具描述。
  2. 再看工具是否被正确执行。打印工具函数入口日志,确认工具名称是否存在于注册表,参数是否完整。
  3. 接着看回执是否正确返回。检查执行器是否捕获了异常,回执中的status和error是否符合预期。
  4. 最后看模型是否读取了回执。把回执内容以新的 system 或 user 消息追加到对话中,确认模型最终回答引用了回执中的关键数据。

这一步看起来基础,但很多线上事故都是因为中间环节断了而没有报警。回执是定位问题的最好抓手。

7. 最佳实践与工程建议

7.1 工具与回执设计

工具设计方面,建议每个工具只负责一个原子操作,不要把一个工具写成几百行的“万金油”。比如query_order只查订单,update_order_state只更新状态。拆分越细,大模型越容易理解,复用性也越高。工具的命名要动词开头,例如send_email、get_weather、create_ticket,避免使用模糊名词。

回执设计方面,建议由统一函数生成,不要直接在工具函数里拼 JSON。回执中的status建议使用枚举常量,例如SUCCESS、FAILED、RUNNING、TIMEOUT,避免字符串拼写不一致。trace_id必须全局唯一,用于追踪一次完整的任务链路。error字段不要只存一句话,最好包含错误码和可读信息,方便模型自我纠错。

7.2 日志与可观测性

智能体系统比传统接口复杂在“决策链路易断”,所以日志是刚需。每次工具调用至少要记录以下信息:请求ID、工具名称、输入参数、回执内容、耗时、最终回复。建议把回执对象原样写入日志文件,方便事后回溯。如果使用集中式日志平台,可以把trace_id作为索引字段,把同一次任务的所有日志串起来。

性能上,工具调用往往比模型生成更耗时,建议对每个工具设置独立的超时阈值,并在回执中记录耗时。当耗时超过阈值时,可以在调用前先返回running回执,避免用户端长时间无响应。异步任务的回执更新,可以通过 Webhook 把新的回执推送给调度方,也可以在数据库里持久化任务状态。

7.3 安全边界

让智能体调用工具,相当于给大模型开放了系统操作权限,安全必须前置。第一,所有工具调用都需要鉴权,不能允许模型绕过权限体系直接执行敏感操作。第二,遵循最小权限原则,给每个工具分配独立的密钥或凭证,让一个工具的泄露不至于影响全局。第三,对工具参数做白名单校验,尤其是文件路径、URL、SQL 语句等高风险参数。第四,保存每次工具调用的审计日志,危险操作需要人工复核。

如果工具涉及生产环境的修改操作,建议增加二次确认机制:智能体先返回“准备执行变更”的提示,由用户在对话中确认后,智能体才真正调用工具。这种设计虽然多了一步交互,但能显著降低误操作风险。涉及数据库删除、配置修改、资金操作时,一定要在测试环境充分验证后再接入生产。

8. 本期 GitHub 日报:值得关注的智能体学习方向

8.1 开源项目怎么挑

回到这期 GitHub 日报的主题。现在每天都有大量智能体项目被创建,但真正适合生产参考的并不多。我的挑选标准很明确:第一,看它是否提供了清晰的工具接入层,而不只是对话界面;第二,看它有没有回执或状态管理的设计;第三,看它的代码是否能离线运行和调试。

如果你在 GitHub 上看到一些项目介绍很亮眼,但仓库里只有 Prompt 文件,没有工具实现,那基本属于“会说话”的范畴。相反,如果一个项目有明确的tools/、actions/、plugins/目录,并且提供了工具执行后的失败处理逻辑,就值得花时间读一读。GitHub 上的智能体框架更新很快,入门时不要贪多,先挑一个小而美的项目,把“手和回执”的代码读透,再去看复杂架构。

如果遇到 GitHub 访问不稳定,可以优先下载仓库压缩包或 Releases 离线包到本地阅读,也可以使用镜像站浏览,但一定要在合法合规的前提下,不要使用任何非正规途径访问受限内容。代码研究这件事,本地环境才是最高效的。

8.2 下一步学习路线

如果你刚完成了本文的 Mini Agent,下一步可以按这个顺序继续深入:

  1. 接入真实大模型:找一个支持 Function Calling 的 API,把mock_llm_reason替换成真实模型调用,观察模型输出的结构化工具调用。
  2. 增加工具类型:尝试接入 HTTP API、数据库查询、文件读写,扩展现有注册表。
  3. 引入异步回执:把某个工具改成异步任务,先返回running,再通过 Webhook 更新状态。
  4. 实现多智能体协作:用两个小智能体分别处理“理解任务”和“执行任务”,用回执传递结果。
  5. 对比研究开源框架:选择 Dify、Coze、FastGPT 中的一个,在平台上搭一个带工具调用的应用,体验平台版“手和回执”。

这套路线从代码到平台,从同步到异步,基本覆盖了智能体工程化的关键节点。如果你在实践过程中遇到了具体的回执格式问题,欢迎在评论区留言,一起讨论。希望这篇 GitHub 日报,能让你的智能体不仅会说,而且真的把事办成。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询