☰
FastAPI + LangGraph:构建生产级自主Agent服务实践
2026/10/3 9:06:40 网站建设 项目流程

1. 先搞清楚这本书到底解决什么问题

最近很多朋友在后台问我,FastAPI和LangGraph这波组合到底是不是“又要封装一个框架”的噱头。刚好我花了一周时间把《FastAPI and LangGraph 开发生产级自主 Agentic AI 系统架构设计与应用实现》的下半部分啃完了,说实话,这类书最怕两种:一种是通篇贴官方文档,另一种是给你一堆伪代码让你自己猜。这本书属于少见的、真正站在“让 AI 下地干活”视角写的,尤其是下半部分把多 Agent 协作、状态持久化、流式接口、异常恢复这些生产级问题全部串了起来。

如果你现在还在“AI 对话 Demo 能跑通”的阶段,或者已经做了几个 ChatBot 项目却发现一上生产就到处崩,那这本电子书可以说踩在了你的痒处上。它的价值不在于教你 LangGraph 的 API 怎么调用,而在于告诉你怎么用 FastAPI 把这套 Agent 编排能力暴露成可上线、可观测、可排障的服务。注意,它说的是“生产级自主 Agentic AI”,不是“写一个能聊天的机器人”。自主意味着系统要自己决策、自己调工具、自己处理中间态,这跟普通的一次性 Prompt 调用完全是两个层面的问题。

我自己读完下卷之后的整体感受是:这本书的下册把“从单个 Agent 到多 Agent 协作”的演进路径解释得很清楚,同时没有回避生产环境里那些脏活累活。它会花篇幅去讲 LangGraph 的 checkpointer、短期记忆和长期记忆怎么取舍,也会讲 FastAPI 的 BackgroundTasks、StreamingResponse、WebSocket 这些知识怎么和 Agent 的异步执行模型结合。这正好解决了我之前带团队做 Agent 服务时踩过的大部分坑。

对于不同基础的读者,我说下我的建议。如果你是刚接触 FastAPI 的新手,建议先把 FastAPI 的依赖注入、Pydantic 模型、异步路由这几个基础点过一遍,再来看这本书;如果你已经熟悉 LangChain 但没用过 LangGraph,那这本书下半部分的图结构状态机模型会帮你把思路彻底捋顺;如果你本身就在做 Agent 相关项目,想找一份可以参考的工程化方案,那这本书里的项目目录结构、接口设计、异常处理逻辑都值得直接抄作业。

2. 架构选型思路:FastAPI 和 LangGraph 的职责边界

2.1 FastAPI 在 Agent 服务层扮演的角色

很多人有个误区,觉得 FastAPI 就是用来替代 Flask 写 HTTP 接口的。但在 Agentic AI 系统里,FastAPI 承担的职责远不止“接收请求、返回 JSON”这么简单。它是整个 Agent 系统的对外门户,负责把 LLM 推理、工具调用、状态持久化这些内部复杂度全部封装在服务边界之内。

为什么选 FastAPI 而不是 Flask 或 Django?我基于实际项目经验总结出三个关键点。

第一是原生异步支持。Agent 系统最大的特点就是慢,一次复杂任务可能涉及多轮 LLM 调用和工具调用,单次请求耗时轻松超过十秒甚至几分钟。如果用同步框架,一个 Agent 请求就把 worker 线程占死了,一旦并发量上来服务直接雪崩。FastAPI 基于 asyncio,你可以把 Agent 运行放在async def路由里,也可以配合run_in_executor把 CPU 密集型或同步的 LangGraph 运行时丢到线程池,Web 层不会被阻塞。

第二是 Pydantic 模型带来的输入输出约束。Agent 项目最怕的就是“输入不可控”,用户传什么你都收,结果 Prompt 被注入或者参数类型对不上。FastAPI 的路径参数、查询参数、请求体都走 Pydantic 校验,这让你的 Agent API 在入口就完成了一次数据清洗。我在实际项目里甚至会把 Agent 的最终输出也用 Pydantic model 约束一遍,避免模型返回乱七八糟的 JSON 结构。

第三是 OpenAPI 文档带来的调试便利。Agent 系统的接口往往不是一个人维护的,前端要调你的流式接口,测试要模拟多轮对话,算法工程师要单独验证工具调用。FastAPI 自动生成的 Swagger UI 让你在开发阶段就能直接点按钮触发 Agent 流程,这在联调阶段省了大量沟通成本。

2.2 LangGraph 解决了什么核心问题

LangGraph 本质上是一个用图结构来编排 Agent 流程的状态机框架。它的核心抽象是State、Node、Edge三个概念。Node 是业务逻辑的执行单元,Edge 是 Node 之间的流转条件,State 是贯穿整张图的数据载体。

我之前用 LangChain 的 AgentExecutor 写过多轮工具调用,最头疼的是状态管理完全黑盒。Agent 内部到底调了几次工具、每一步的中间输出是什么、为什么最后决策错了,你完全没有办法观测和干预。LangGraph 把整个链路显式建模成一张图,每个节点执行完都能看到 State 的变化,这相当于给 Agent 装了一个“行车记录仪”。排查问题时你可以定位到具体是哪个节点产生了错误决策,这在生产环境是可观测性的关键。

另一个重要设计是checkpointer,也就是状态检查点。LangGraph 允许你在图的每一步把当前 State 持久化到存储介质,比如 SQLite、PostgreSQL、Redis。这一步解决了两个问题:一是服务重启后可以恢复现场,二是支持interrupt机制实现人机协同。比如 Agent 准备执行高风险操作前,可以先中断并把状态存下来,等人工审批通过后再从断点继续执行。这在自动化脚本、金融交易、后台运维等场景几乎是刚需。

书里下半部分反复强调的一个观点我非常认同:Agent 系统的复杂度一旦超过单个节点能承受的范围,就应该用图来组织逻辑,而不是一味地往 Prompt 里塞约束。Prompt 能控制模型的行为,但控制不了代码的执行路径;LangGraph 则把执行路径本身变成了可编写、可测试、可回放的代码。

2.3 为什么是这两者组合,而不是其他方案

市面上也有不少 Agent 框架,比如 Autogen、CrewAI,甚至有人直接用 LangChain 的 AgentExecutor。但 FastAPI + LangGraph 这套组合的特殊之处在于,它把Web 服务框架和Agent 编排框架做了非常清晰的职责划分。FastAPI 管外部通信,LangGraph 管内部智能,两者之间只通过接口和状态交换。这样你在替换或升级其中任何一层时,不会牵连到另一层。

如果你只想快速做一个 Demo,可能用 Flask 加 LangChain 更省事。但是一旦你考虑并发流量、流式响应、链路追踪、故障恢复、多租户隔离这些问题,FastAPI 和 LangGraph 的组合优势就会非常明显。书里的例子也很有意思,它不是给你一个理论架构图就完事,而是真的带着你把一个带记忆、带工具调用、带多 Agent 协作的完整服务一步步写出来。

3. 项目目录结构:照着抄也能不烂尾

3.1 为什么是 fastapi 项目目录结构的热搜问题

如果你搜过相关话题,会发现fastapi 项目目录结构是一个经久不衰的问题。因为 FastAPI 本身不强制目录规范,新手很容易把所有路由写在一个 main.py 里,等项目膨胀到几千行才意识到要拆分,这时候重构成本已经很高了。我根据这本书里推荐的工程组织方式,结合自己带项目的经验,给你一套适用于 Agent 服务的目录模板。

agent_service/ ├── app/ │ ├── __init__.py │ ├── main.py # FastAPI 入口,创建 app 实例,注册路由 │ ├── config.py # 配置项,读取环境变量 │ ├── api/ │ │ ├── __init__.py │ │ ├── routes/ │ │ │ ├── __init__.py │ │ │ ├── chat.py # 对话类接口 │ │ │ └── task.py # 异步任务类接口 │ │ └── schemas/ │ │ ├── __init__.py │ │ ├── request.py # 请求体模型 │ │ └── response.py # 响应体模型 │ ├── agent/ │ │ ├── __init__.py │ │ ├── graph.py # LangGraph 图定义 │ │ ├── nodes.py # 图节点函数 │ │ ├── edges.py # 条件边逻辑 │ │ ├── tools/ │ │ │ ├── __init__.py │ │ │ ├── search.py │ │ │ └── calculator.py │ │ └── state.py # 状态模型定义 │ ├── core/ │ │ ├── __init__.py │ │ ├── llm.py # LLM 客户端封装 │ │ └── memory.py # 记忆持久化封装 │ └── services/ │ ├── __init__.py │ └── agent_service.py # Agent 服务层,协调 graph 与外部依赖 ├── tests/ │ ├── __init__.py │ ├── test_chat.py │ └── test_graph.py ├── pyproject.toml ├── docker-compose.yml └── README.md

这套结构的核心思想是分层。API 层只负责解析 HTTP 请求和序列化响应,不包含任何 Agent 逻辑;Agent 层只负责图和节点的定义,不直接感知 HTTP 的存在;Services 层才是两边的桥梁。如果业务足够复杂,你还可以在 services 下面再拆出 repository 层,用来统一操作数据库和 Redis。

3.2 核心代码骨架:FastAPI 如何暴露 LangGraph 服务

书里下半部分的代码非常值得细读,我用自己的方式把核心流程精简出来,你可以照着思路去匹配原书的具体实现。

首先定义一个简单的 LangGraph 状态模型。这里的 State 就是一个 TypedDict 或者 Pydantic 模型,用来在节点之间传递数据。

from typing import Annotated, TypedDict, List from langgraph.graph import add_messages class AgentState(TypedDict): messages: Annotated[List[dict], add_messages] tool_calls: List[dict] current_node: str

add_messages是 LangGraph 提供的一个合并操作,它会把新节点产生的消息追加到 State 里的历史消息列表中,而不是直接覆盖。这是实现多轮对话记忆的关键机制。

接着定义一个包含“大模型节点”和“工具节点”的图:

from langgraph.graph import StateGraph, END from langgraph.checkpoint.sqlite import SqliteSaver def call_llm(state: AgentState): # 调用大模型,返回新的消息 return {"messages": [llm.invoke(state["messages"])]} def call_tool(state: AgentState): # 执行工具调用,把结果作为消息返回 return {"messages": [execute_tool(state["tool_calls"])]} graph = StateGraph(AgentState) graph.add_node("llm", call_llm) graph.add_node("tools", call_tool) graph.add_edge("llm", "tools") graph.add_condition_edge("tools", lambda state: "llm" if state["tool_calls"] else END) graph.set_entry_point("llm")

实际生产项目里的条件边会复杂得多,比如判断是否需要用户确认、是否需要切换上下文、是否需要启动子 Agent,但骨架是一样的。

然后在 FastAPI 里暴露这个图:

from fastapi import FastAPI from fastapi.responses import StreamingResponse from langgraph.checkpoint.sqlite import SqliteSaver app = FastAPI() # 原书推荐的持久化方式,生产环境可换成 PostgresSaver checkpointer = SqliteSaver.from_conn_string("agent_state.db") compiled_graph = graph.compile(checkpointer=checkpointer) @app.post("/agent/run") async def run_agent(request: AgentRequest): config = {"configurable": {"thread_id": request.thread_id}} async def event_stream(): async for event in compiled_graph.astream_events( {"messages": request.messages}, config=config, version="v2", ): if "on_chat_model_stream" in event["event"]: yield f"data: {event['data']['chunk'].content}\n\n" return StreamingResponse(event_stream(), media_type="text/event-stream")

这里有一个细节值得重点说:astream_events是 LangGraph 提供的事件流接口,它可以逐 token 把大模型的输出推给前端,这是实现“打字机效果”的关键。但它的输出事件类型非常多,如果你直接把所有事件都透传给前端,会把 DAG 的内部执行细节全部暴露给客户端。所以我一般在event_stream里做一层过滤,只保留on_chat_model_stream和on_tool_start/end这类用户关注的事件。

3.3 工具调用的生产级处理方式

langgraph 工具调用是很多人在教程里看得懂、落实到项目里却经常出错的环节。书里给出了一个很清晰的思路:把启用的工具列表传给 LLM,然后从 LLM 返回的内容里解析tool_calls,再根据名称分发到对应的 Python 函数。

管理层面上,我建议把所有工具函数统一注册到一张路由表:

TOOL_REGISTRY: dict[str, Callable] = { "web_search": web_search, "calculator": safe_calculator, "db_query": db_query, } def execute_tool(tool_calls: list[dict]) -> list[dict]: results = [] for call in tool_calls: name = call["name"] args = call["arguments"] try: result = TOOL_REGISTRY[name](**args) results.append({"role": "tool", "tool_call_id": call["id"], "content": str(result)}) except Exception as exc: results.append({"role": "tool", "tool_call_id": call["id"], "content": f"Error: {exc}"}) return results

这个设计的价值在于,任何时候不管大模型怎么变换工具名称,你代码里的注册表都是唯一事实来源。工具变更、版本升级、权限控制,全部在这张表上做文章。生产环境中还要注意工具返回内容的大小限制,因为工具结果会作为上下文继续发送给 LLM,如果查询返回了 10 万行数据,轻则 token 超限,重则把成本直接拉爆。所以一定要在工具内部做结果瘦身,只返回摘要或分页数据。

4. 多 Agent 协作与流程控制:从“单打独斗”到“团队作战”

4.1 主从结构与监督者模式

书里下半部分我最喜欢的一章是多 Agent 协作。很多教程里的多 Agent 只是把两个 Agent 串在一起,实际上真正的多 Agent 协作需要解决任务分配、上下文隔离、结果汇总、冲突消解这些问题。书中重点讲了两种模式:一种是Supervisor 监督者模式,由一个主 Agent 负责任务拆解,把子任务分给不同的专家 Agent;另一种是Pipeline 模式,多个 Agent 按固定顺序依次处理,适合流水线任务。

我在实际项目里更多用的是监督者模式。主节点收到用户需求后,先通过 LLM 判断任务类型,然后调用条件边路由到对应子图。比如一个智能客服系统,可能需要一个退款 Agent、一个查物流 Agent、一个转人工 Agent,它们各自有自己的工具和 Prompt。主节点不直接处理具体业务,只做路由决策。

LangGraph 在 0.2 版本之后对这类场景支持得很好,你可以用StateGraph构建一个主图,主图里可以嵌套子图。子图的 State 和主图不一定相同,但需要注意边界上的字段转换。

from langgraph.graph import StateGraph builder = StateGraph(MainState) builder.add_node("supervisor", supervisor_routing) builder.add_node("refund_agent", refund_subgraph) builder.add_node("logistics_agent", logistics_subgraph) builder.add_conditional_edges("supervisor", route_to_agent, { "refund": "refund_agent", "logistics": "logistics_agent", "END": END, })

这里面容易踩的坑是子图返回的状态合并。如果子图内部修改了字段但没在子图结果里声明,主图是拿不到对应变化的。多 Agent 项目排障时,七八成的诡异问题都出在状态字段没有正确声明和合并上。

4.2 让 AI 真的下地干活的关键:召回、评估和兜底

“让 AI 真的下地干活”这个话题最近特别火。书里给出的答案很接地气:自主 Agent 的核心能力不是“生成文本”,而是“对工具系统做了一次安全可控的操作”。要让它在生产环境里干活,你必须考虑三件事。

第一是信息召回。真实业务里 Agent 往往需要从一个知识库或数据库里拿到上下文,不同用户不同会话都要能精准召回。你可以用 LangGraph 在进入主流程之前加一个“检索节点”,用向量数据库召回相关片段,然后塞进 Prompt。这个节点和主节点在 State 上的字段要区分清楚,避免检索结果污染 Agent 自身的决策痕迹。

第二是结果评估。书里提到一个做法,在 Agent 完成一次工具调用后,加一个“验证节点”,用规则或另一个轻量模型判断结果是否符合预期。听起来简单,但这在工程上是质变。你可以理解成给 Agent 写了一个自动化测试用例,每次执行都会自检。

第三是兜底。生产环境里 Agent 一定会犯错,关键是犯错了怎么办。书里的思路是设置最大重试次数、超时阈值、以及一条人工兜底链路。当 Agent 连续失败或者模型输出不符合 Pydantic 校验时,自动把会话转入人工队列。这比让用户对着一堆错误重试要亲得多。

4.3 长时任务与 FastAPI 的异步模型结合

Agent 系统里有一种常见的场景:用户提交一个任务后,不需要一直等待流式输出,而是希望任务在后台跑,完成后通过 Webhook 或轮询通知结果。这时候 FastAPI 的BackgroundTasks和 LangGraph 的异步执行能力就要结合使用。

from fastapi import BackgroundTasks def run_graph_in_background(thread_id: str, message: str): config = {"configurable": {"thread_id": thread_id}} compiled_graph.invoke({"messages": [{"role": "user", "content": message}]}, config) @app.post("/agent/async") async def run_agent_async(request: AgentRequest, background_tasks: BackgroundTasks): background_tasks.add_task(run_graph_in_background, request.thread_id, request.message) return {"status": "accepted", "thread_id": request.thread_id}

这里必须注意两个坑。第一个是BackgroundTasks默认是在响应发送完之后同步执行的,如果你的 Agent 逻辑里包含大量 I/O,会导致事件循环被阻塞。我建议在后台任务函数里用asyncio.create_task或者丢进独立的线程池执行。第二个是 LangGraph 的invoke是同步接口,它会阻塞当前线程,所以在异步路由里直接调用同样危险。正确姿势是用asyncio.to_thread包装:

import asyncio result = await asyncio.to_thread(compiled_graph.invoke, input_data, config)

5. 生产环境避坑:日志、并发、持久化

5.1 uvicorn fastapi 日志丢失问题到底怎么回事

我在团队里遇到过非常诡异的现象:服务正常运行,但 uvicorn 的访问日志偶尔缺失,甚至有些报错日志完全没打出来。后来发现这跟 uvicorn 的日志传播机制有关。

uvicorn 默认自带一套日志配置,包括uvicorn.access和uvicorn.error两个 logger。如果你在代码里设置了全局的logging.basicConfig,或者你依赖第三方库自己也创建了 handler,就很容易出现 logger 之间互相覆盖或者传播链断裂的问题。最典型的场景是:你在main.py里用logging.getLogger("uvicorn.error")加了一个 handler,但同时你的应用日志 logger 也在输出重复日志,两边不同步,看起来就像日志“丢了”。

实际操作中我建议明确统一日志格式,并且不要轻易给 uvicorn 的 logger 重复挂 handler。一个比较稳的做法是在项目配置里指定 log level 和 handler:

import logging from logging.config import dictConfig dictConfig({ "version": 1, "disable_existing_loggers": False, "formatters": { "default": { "format": "%(asctime)s [%(levelname)s] %(name)s: %(message)s", } }, "handlers": { "console": { "class": "logging.StreamHandler", "formatter": "default", } }, "root": {"handlers": ["console"], "level": "INFO"}, })

这段配置放在 FastAPI 应用实例化之前执行,可以保证你的路由日志、LangGraph 节点日志、uvicorn 自身日志全部遵循同一套规则。另外,如果你用 Docker 部署,记得让日志输出到 stdout,而不是写本地文件,不然容器一重启日志就没了,追踪问题会很痛苦。

5.2 并发问题和 LangGraph State 的隔离性

FastAPI 是一个天然支持高并发的框架,但 LangGraph 的 State 是全局对象,如果你把多个用户的上下文章在一个全局 State 里管理,立刻就会出大问题。每个用户进来都要通过config["configurable"]["thread_id"]区分会话。thread_id是 LangGraph 做状态隔离的键,同一 thread_id 的请求共享同一份历史状态,不同 thread_id 之间互相隔离。

我一开始就犯过把 thread_id 漏掉的错误,导致两个用户共用一份历史上下文,A 用户的话术会莫名其妙出现在 B 用户的对话里,排查了很久才定位到是配置对象复用的问题。所以在 FastAPI 依赖注入阶段,我会把 thread_id 强制校验:

def get_graph_config(request: AgentRequest) -> dict: if not request.thread_id: raise HTTPException(status_code=400, detail="thread_id is required") return {"configurable": {"thread_id": request.thread_id}}

另一个并发相关的坑是 SQLite checkpointer 的写入锁。SqliteSaver在本地开发时很好用,但一旦并发量上来,多个请求同时写同一个 SQLite 文件会出现database is locked错误。生产环境建议直接用 PostgresSaver 或者 RedisSaver。书里也专门提醒过,SQLite 只适合单机开发和测试,不适合多 worker 部署。

5.3 流式响应中的超时与连接管理

用StreamingResponse做 SSE 流式输出时,FastAPI 本身不帮你管理浏览器端的连接断开。如果用户中途关闭了页面,底层 asyncio 任务可能还在继续跑,Agent 依然在调 LLM、调工具,白白浪费额度。这个问题我在项目里碰到过无数次。

我的建议是在事件循环里监听请求断开事件。FastAPI 的Request对象有一个is_disconnected()方法,可以定期检查客户端连接状态。你可以在每轮事件循环里判断:

async def event_stream(): for event in event_generator(): if await request.is_disconnected(): break yield event

这样做能及时终止 Agent 的后续执行,避免资源浪费。更稳妥的方案是在 Agent 执行前设置一个总超时时间,用asyncio.wait_for包住整个 Agent 调用,超过阈值直接中断并返回友好提示。

5.4 状态持久化的正确姿势

LangGraph 的 checkpointer 能保存每一步的 State,但默认情况下它保存的是经过序列化的完整状态。如果你的 State 里有非 JSON 可序列化对象,比如自定义 class 实例、数据库连接、文件句柄,在做持久化时就会报错。所以设计 State 字段时,尽量只放基础数据类型、字典、列表和字符串。复杂对象在写入 State 之前先转成字符串或者只存引用 ID。

另外是状态膨胀的问题。随着会话变长,State 里累积的消息越来越多,每次调用 LLM 时要发送的 token 越来越多,成本和延迟双双上升。生产级系统一定要做上下文压缩,比如超过一定轮数后,用摘要节点把早期对话压缩成一段摘要,然后拼接到后续的 Prompt 中。LangGraph 里可以加一个 “summary” 节点,在消息数超阈值时触发。

6. 一些实战经验:从这本电子书到真正上线的心得

6.1 一定不要直接照搬这本书的代码

市面上很多技术书的问题在于代码是教学性质的,为了讲清楚原理会把一些工程细节简化掉。这本书虽然已经算很贴近生产了,但你在真实项目里仍然要做几个改造。第一是密钥管理,书里很可能直接在配置里写死了 LLM API key,你在生产环境一定要用环境变量或密钥管理服务,比如 Vault。第二是错误处理,教学代码通常只在主流程里捕获异常,你上线前必须把节点级异常、工具调用异常、LLM API 异常分别处理。第三是可观测性,建议接入 OpenTelemetry 之类的链路追踪,把 LLM 调用、工具事件、图节点流转都打点上报。

6.2 用测试保护你的图结构

LangGraph 的图结构是可测试的。我强烈建议你在写业务之前先写一个最小可复现的图测试,用 mock LLM 返回的固定结果来验证节点流转是否正确。比如你可以 mock LLM 始终返回“需要调用工具”,然后断言图确实进入了工具节点。这样后续无论你加多少业务逻辑,只要图流转测试不挂,重构就不会出大问题。

6.3 这本电子书适合出现在“fastapi面经”里的问题

如果你在准备面试,这本书里的很多内容可以直接转化为面试回答素材。比如问你 FastAPI 和 LangGraph 怎么结合,你可以从“FastAPI 负责 HTTP 生命周期和流式输出,LangGraph 负责 Agent 决策编排和状态持久化”这个角度回答,比单纯背诵框架特性有说服力得多。再比如问你多 Agent 系统怎么设计,你可以谈 Supervisor 模式、条件路由、状态隔离、检查点恢复这四个层面。这些都是书本里有完整场景描述的,理解之后用自己的话讲出来,面试官很容易听出你真的做过项目。

7. 最后再聊聊这本书的阅读方式

我个人读这类技术书的习惯是先挑最关心的章节跳着读,但这本书我建议从头往后按顺序读。因为它下半部分有一个很明显的推进逻辑:先讲单 Agent 的图结构,再到多 Agent 协作,再到状态管理和持久化,最后落到 FastAPI 的对外接口设计。每一步都在前一步的基础上叠加复杂度,如果你没看懂状态怎么传递,直接跳到多 Agent 章节会一头雾水。

读的时候可以边读边敲代码。LangGraph 的 API 从 0.1 到 0.2 变化不小,书里写的是哪个版本、实际安装环境是哪个版本,需要你自己对照文档确认。我实测下来,如果你装的是 0.2 以上版本,StateGraph和add_conditional_edges的用法跟旧版略有差异,照着书运行出现AttributeError时不要慌,多半是版本差异,查一下官方 changelog 就行。

还有一点我想特别提醒,就是这本书虽然标题里带“生产级”,但它的真正价值是给你一套思路骨架。生产级三个字不是写完就有的,而是靠不断完善重试机制、监控告警、人工兜底之后才获得的。你可以把这本电子书当作一份很好的起点,在它的基础上把自己项目的真实业务逻辑填充进去,你的 Agent 系统才能真正从“能跑”变成“能干活”。

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

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

立即咨询