Agent 形态一天一个样但 Infra 不能跟着形态跑。今天这篇不是讲某个具体框架的安装教程而是聊一个更现实的问题当 ReAct、Workflow、Multi-Agent、MCP、Skill、Harness 这些概念快速迭代时底层基础设施到底该为谁而建。先说结论Infra 应该为“稳定边界”而建而不是为“某一种 Agent 形态”而建。形态会变但 Agent 运行时的执行链路、上下文管理、工具连接、任务调度、可观测性和安全边界是不会轻易变的。把这六层抽象出来比天天追最新 Agent 框架更值得投入。这篇文章会从 Agent 形态变化带来的基础设施压力讲起给出一套分层建设的思路然后落到一套最小可运行的参考架构覆盖环境准备、核心实现、功能测试、API 与批量任务、资源占用观察、常见问题排查和安全合规边界。适合负责 Agent 平台建设、做 AI Infra 选型、或者正准备把 Agent 从 Demo 推向工程化的技术同学。1. Infra 建设与 Agent 形态的错位先看一个普遍现象团队里 Agent 的形态基本三个月一变。上个月还在写 ReAct 循环这个月在编排多 Agent 协作下个月可能又要接 MCP 工具生态。如果 Infra 跟着某一个 Agent 框架走每次换形态都要重写调度、重做日志、重新对接工具成本非常高。更稳的做法是把 Agent 形态和基础设施解耦。Agent 形态属于“业务编排层”Infra 属于“运行时能力层”。形态可以频繁换但运行时能力层需要保持相对稳定。1.1 什么是 Agent 形态Agent 形态通常指 Agent 的组织和交互方式。现在常见的有几类单 Agent 循环模型在 ReAct 框架下反复执行 Thought、Action、Observation直到完成目标。工作流编排把任务拆成固定 DAG节点之间通过显式步骤流转。多 Agent 协作多个 Agent 分角色协作如规划者、执行者、评审者。工具编排与技能封装通过 MCP、Function Calling、Skill 等方式挂接外部工具。Harness 驱动的执行框架用一套 Harness 管理上下文、工具调用和 Agent 生命周期。这些形态的核心差异在编排逻辑但它们最终都会落到模型推理、工具执行、状态保存、结果返回这些固定动作上。1.2 Infra 到底该为谁而建从使用者视角拆分Infra 的服务对象有三类Agent 开发者需要易用的 SDK、调试工具、测试环境、版本管理。Agent 运行时需要稳定的模型调用通道、并发控制、任务队列、容错重试。最终业务方需要可观测的调用链路、清晰的审计日志、可控的权限边界。如果把“Infra 为谁而建”这个问题简化成一句话为“可以被复用的通用能力”而建而不是为“某一个 Agent 项目的私有逻辑”而建。1.3 Infra 分层决策速览Infra 层级解决什么问题典型组件建设优先级开发与调试层Agent 编排、本地调试、版本管理Workflow 引擎、Debugger、Prompt 管理高运行与调度层模型调用、并发控制、任务队列Runtime、Executor、Queue、Retry高连接与集成层工具注册、MCP 网关、外部系统接入Tool Registry、MCP Router高记忆与状态层上下文管理、会话持久化、向量检索Memory Store、Vector DB中高可观测与评估层日志、Trace、效果评估Trace SDK、Eval Pipeline中高安全合规层权限、审计、数据脱敏、工具授权Policy Engine、Audit Log高这个表可以作为 Agent Infra 建设时的优先级检查清单。预算有限时先保证运行调度、连接集成、安全合规三层再逐步补齐可观测和记忆层。2. Agent 形态变化带来的三大基础压力Agent 形态虽然变化快但给 Infra 带来的压力基本指向三个方向执行链路变长、上下文状态变复杂、外部连接变多。2.1 执行链路从“单次调用”变成“执行图”早期 LLM 应用基本是单轮指令模型返回结果就结束了。现在典型 Agent 任务是一个多步执行图规划、调用工具、观察结果、再次推理、循环直到结束。执行链路的每一步都可能失败都需要重试都需要被追踪。这带来几个直接的 Infra 需求执行轨迹的记录每一步的输入输出要能回放。超时控制Agent 循环可能出现死循环或长时间无响应。失败重试策略工具调用失败后是重试、换路径还是终止。并发限制多个 Agent 实例不能乱跑不受控。2.2 上下文与记忆状态管理Agent 形态无论怎么变都绕不开上下文。不同形态对上下文的需求不同单轮对话上下文短状态简单。多 Agent 协作需要共享上下文或者通过消息传递上下文。长任务执行需要把超长历史压缩、摘要或者外置到记忆系统。工具交互每一步的工具返回结果都要写入上下文上下文很容易膨胀。状态管理如果做不好Agent 的表现就是“丢上下文”“答非所问”“重复执行”。Infra 层需要提供标准的状态存取接口让 Agent 可以读写会话状态而不是每次把全部历史堆给模型。2.3 工具、技能与外部系统连接现在热词里的 Skill、MCP、Tool Calling本质上都指向同一个问题Agent 怎么稳定地调用外部能力。工具连接层需要解决工具发现Agent 如何知道当前有哪些工具可用。工具协议Function Calling、MCP、HTTP API 如何统一接入。鉴权与授权工具不是随便能给所有 Agent 用的需要按身份控制。工具限流外部服务有配额工具网关要统一控流。失败语义工具返回错误时Agent 能否理解并自我恢复。从工程角度看工具连接层最值得先做。因为模型可以换、框架可以换但企业内部的工具和系统接口是长期存在的。3. 环境准备与前置条件在开始搭建 Agent Infra 之前先确认基础环境。下面是一份通用检查清单不绑定具体框架按实际项目调整即可。3.1 硬件与系统操作系统Linux 服务器为主开发机可选用 macOS 或 Windows WSL。GPU如果需要本地部署 LLM按模型参数量评估如果走云端 APIGPU 不是硬性要求。CPU 与内存Agent 编排层本身不重但多实例并行和向量检索会吃内存。磁盘模型文件、日志、向量库、缓存都需要空间建议预留足够余量。网络需要能访问模型服务、外网工具 API 或者内网服务网关。注意不要一上来就规划大规模 GPU 集群。Agent Infra 的瓶颈往往不在推理而在编排稳定性、上下文管理和工具调度。初期尽量复用已有的模型 API把编排层跑通再考虑私有化部署模型。3.2 软件环境推荐用容器化方式部署便于隔离和迁移。# 通用目录参考结构 agent-infra/ ├── runtime/ # Agent 运行时与执行器 ├── tools/ # 工具注册与 MCP 集成 ├── memory/ # 记忆与状态存储 ├── api/ # 对外 API 服务 ├── worker/ # 批量任务消费端 ├── configs/ # 配置文件 ├── logs/ # 运行日志 └── tests/ # 测试用例与评估脚本依赖管理建议用 Python、Node.js 或 Go 都行关键是团队熟悉。Python 生态在 Agent 框架里最成熟Node.js 适合做前后端联动Go 适合做高性能网关。3.3 模型服务准备Agent 运行时需要一个可访问的模型服务。三种选择云端模型 API接入简单适合快速验证。私有化 vLLM、TensorRT-LLM 等服务适合数据敏感场景。本地 Ollama 等轻量推理工具适合开发调试。无论哪种都需要在配置中区分模型名、接口地址、超时时间和 API Key。# configs/llm.yaml 示例按实际项目替换 llm: provider: openai_compatible base_url: http://127.0.0.1:8000/v1 api_key: local-test-key model: qwen2.5-72b-instruct temperature: 0.2 max_tokens: 4096 timeout: 604. 一套最小可运行的 Agent Infra 参考架构下面给出一套不依赖具体 Agent 框架的参考架构核心思路是“把执行链路标准化把工具接入标准化把状态管理标准化”。4.1 架构组件说明组件职责可选实现API 服务对外接收任务请求返回任务 IDFastAPI、Flask调度器把任务分发到执行器支持并发控制Redis Queue、Celery、自研执行器执行 Agent 循环调用模型和工具自研 Agent Loop / LangGraph / CrewAI工具网关统一鉴权、限流、路由到具体工具自研 Router、MCP Proxy状态存储保存会话、任务、执行轨迹Redis、PostgreSQL、SQLite观测组件记录日志、Trace、Token 消耗OpenTelemetry、Loki、Prometheus4.2 目录结构与启动配置# docker-compose.yml 参考模板按实际项目调整 version: 3.8 services: redis: image: redis:7-alpine ports: - 6379:6379 api: build: ./api environment: - REDIS_URLredis://redis:6379/0 - LLM_CONFIG/app/configs/llm.yaml ports: - 8000:8000 volumes: - ./configs:/app/configs - ./logs:/app/logs depends_on: - redis worker: build: ./worker environment: - REDIS_URLredis://redis:6379/0 - LLM_CONFIG/app/configs/llm.yaml volumes: - ./configs:/app/configs - ./logs:/app/logs depends_on: - redis这个模板的价值在于API 和 Worker 分离任务通过 Redis 队列传递启动多个 Worker 就能横向扩展。Agent 形态怎么变这套底座都能复用。4.3 核心执行器的伪代码# runtime/agent_loop.py 参考实现核心执行循环 class AgentLoop: def __init__(self, llm_client, tool_registry, memory_store, max_steps10): self.llm llm_client self.tools tool_registry self.memory memory_store self.max_steps max_steps def run(self, task_id: str, user_input: str): messages self.memory.get_session(task_id) for step in range(self.max_steps): # 1. 调用模型 response self.llm.chat(messages) # 2. 判断是否需要调用工具 tool_calls response.get(tool_calls, []) # 3. 无工具调用则返回最终结果 if not tool_calls: self.memory.save_session(task_id, messages) return response[content] # 4. 执行工具调用 for call in tool_calls: tool_name call[function][name] tool_args call[function][arguments] tool_result self.tools.invoke(tool_name, tool_args) messages.append(self.tools.to_message(tool_name, tool_result)) # 5. 限制循环步数防止死循环 if step self.max_steps - 1: raise TimeoutError(fagent loop exceeded max steps: {task_id}) # 6. 保存完整轨迹便于回放和排查 self.memory.save_trace(task_id, messages) return response[content]这个循环看起来基础但它定义了一个稳定的执行语义模型输出、工具调用、结果回填、循环终止。无论上层用 ReAct、LangGraph 还是自研 Harness这个循环都是底层的通用结构。5. 关键实现细节与接口设计Infra 搭建顺利不顺利往往取决于几个关键细节工具怎么注册、状态怎么存、任务怎么并发、API 怎么对外暴露。5.1 工具与 MCP 接入设计工具是 Agent 能力和外部世界的连接点。建议设计一套统一的工具注册表屏蔽底层协议差异。# tools/registry.py 工具注册参考 from dataclasses import dataclass, field from typing import Callable, Any dataclass class Tool: name: str description: str parameters: dict handler: Callable[..., Any] auth_required: bool True rate_limit: int 10 class ToolRegistry: def __init__(self): self._tools: dict[str, Tool] {} def register(self, tool: Tool): self._tools[tool.name] tool def list_tools(self): return [ {name: t.name, description: t.description, parameters: t.parameters} for t in self._tools.values() ] def invoke(self, name: str, arguments: dict): tool self._tools.get(name) if not tool: raise KeyError(ftool not found: {name}) return tool.handler(**arguments)如果接入了 MCP 工具生态可以在ToolRegistry之上加一层 MCP Client Adapter把 MCP Server 暴露的工具注册到同一张表里。这样上层 Agent 不用关心工具是本地函数还是远程 MCP 服务。5.2 任务队列与批量任务批量任务是 Agent Infra 的高频需求。单条任务直接同步调用没问题但批量任务必须走队列。# 提交批量任务的 Python 示例使用 Redis 队列 import redis import json r redis.Redis(host127.0.0.1, port6379, db0) tasks [ {task_id: task_001, input: 第一条任务内容}, {task_id: task_002, input: 第二条任务内容}, ] for task in tasks: r.lpush(agent:tasks, json.dumps(task))Worker 端只需要循环从队列取任务、执行AgentLoop、写结果到结果存储。批量任务的关键是幂等任务重试时不能产生重复副作用。给每个任务一个唯一 ID并在状态表里记录执行状态。5.3 对外 API 服务建议任务提交采用异步模式提交任务返回task_id执行完成后通过回调或轮询获取结果。# api/server.py 参考接口 from fastapi import FastAPI from pydantic import BaseModel app FastAPI() class TaskRequest(BaseModel): user_input: str session_id: str tools: list[str] [] app.post(/v1/agent/tasks) def create_task(req: TaskRequest): # 实际实现写入任务队列返回 task_id task_id ftask_{req.session_id} return {task_id: task_id, status: queued} app.get(/v1/agent/tasks/{task_id}) def get_task(task_id: str): # 实际实现从状态存储读取任务状态和结果 return {task_id: task_id, status: completed, result: ...}这样的接口设计对上层应用友好前端只需要先提交任务再轮询状态不关心 Agent 内部怎么执行。6. 功能测试与效果验证Infra 搭完不能直接用需要一套验证流程来确认执行链路、工具调用、批量任务和状态恢复都正常工作。6.1 测试用例设计测试项输入示例预期结果判定标准单轮对话普通文本问题模型直接返回答案响应正常无工具调用工具调用查询天气类问题先调用工具再回答Trace 中能看到工具调用记录多步规划需要多步拆解的任务多次模型调用并逐步推进执行轨迹完整不超步数批量任务100 条任务入队全部执行完成且有结果状态表均为 completed并发请求同时发起 20 个任务系统无明显错误队列消费正常无任务丢失状态恢复中断后重新拉起任务能继续或安全终止状态一致不重复执行6.2 关键验证命令启动 API 服务# 本地启动 API 服务实际命令按项目调整 uvicorn api.server:app --host 127.0.0.1 --port 8000启动 Worker# 启动一个或多个 Worker 消费任务 python worker/consume.py --concurrency 4测试工具调用链路curl -X POST http://127.0.0.1:8000/v1/agent/tasks \ -H Content-Type: application/json \ -d {user_input: 查询北京今天的天气, session_id: demo_001}观察返回的task_id再轮询任务详情。如果任务进入失败状态去日志目录查对应task_id的 Trace 文件定位是模型调用失败还是工具执行失败。6.3 成功与失败判断成功任务状态为completed返回结果里包含最终答案Trace 记录完整。失败任务状态为failed日志里有异常堆栈或超时记录。卡住任务长时间为running优先检查队列消费情况和模型调用超时时间。如果看到类似agent execution terminated due to error或the agent execution provider did not respond in time的报错通常指向两类问题模型服务响应超时或者 Agent 循环进入了异常分支。排查时先确认模型服务连通性再看执行器是否有未捕获异常。7. 资源占用与性能观察Agent Infra 的资源占用和传统 API 服务不完全一样。以下是需要重点观察的指标。7.1 关键性能指标指标说明观察方式Token 消耗每次任务消耗的输入输出 Token在 LLM 客户端中间层统计模型推理延迟单次模型调用的耗时Trace 中记录工具调用耗时外部工具从请求到返回的时间Trace 中记录队列积压待处理任务数Redis LLEN 命令Worker 并发数同时在执行的 Agent 实例数监控脚本统计内存占用上下文长时内存上涨情况容器监控7.2 如何观察# 查看任务队列积压数量 redis-cli LLEN agent:tasks# 查看 Worker 日志中的执行耗时 tail -f logs/worker.log | grep elapsed7.3 降低资源开销的思路上下文压缩长历史经摘要后只保留关键信息降低 Token 消耗。限制最大步数防止 Agent 无意义循环减少推理次数。工具结果截断超长工具返回先截断只保留核心字段。复用模型连接客户端使用连接池避免每次请求重新握手。批处理的并发数控制不是并发越高越好过高的并发反而会打满上游服务。需要明确一点具体数字依赖模型规格、上下文长度、工具数量必须用本机或测试环境实测不能照搬别人的显存和耗时数据。8. 常见问题与排查方法问题现象可能原因排查方式解决方案Agent 任务一直 running 不结束模型服务超时或 Agent 循环死循环查看任务 Trace 和模型日志设置模型超时时间限制最大步数工具调用返回异常工具参数格式错误或鉴权失败检查工具网关日志校验参数 schema检查授权配置批量任务部分失败上游工具限流或偶发网络错误统计失败任务错误码增加重试机制和退避策略上下文超出模型窗口多轮工具结果塞满上下文查看每轮 Token 统计增加上下文压缩或摘要策略任务重复执行消费者未做幂等处理检查状态表的 task_id消费前检查任务状态队列积压上升Worker 消费能力不足查看并发数和单任务耗时增加 Worker 或调整并发数报错 agent execution provider did not respond in time模型接口超时或网络抖动检查模型服务状态和超时配置延长超时增加重试确认模型负载报错 agent terminated due to error执行器未捕获异常查看异常堆栈增加全局异常捕获和失败终止语义注意排查 Agent Infra 问题最核心的手段是“有完整的执行轨迹”。如果连每一步的输入输出都没记录问题基本只能靠猜。所以可观测层不是可选项而是必须项。9. 安全、隐私与合规边界Agent 比普通 API 服务有更强的工具调用能力安全边界更严格。9.1 权限与鉴权工具不能对全部 Agent 开放。按 Agent 身份配置工具白名单。外部用户调用 Agent 接口时要鉴权且要限制可访问的会话范围。工具执行前要做参数校验防止注入非法操作。9.2 数据与隐私输入数据、工具返回数据、最终输出都可能有敏感信息需要脱敏处理。会话数据和执行轨迹要按数据等级设置保留期限到期自动清理。如果涉及人脸、声音、版权素材必须确认授权和合规边界不能默认允许使用。长期保存用户数据前要明确告知并获得同意。9.3 审计每次工具调用都记录操作者、调用时间、输入参数摘要和返回状态。批量任务同样需要审计不能因为是机器行为就忽略。审计日志要防篡改至少保证只能追加不能随意删除。10. 最佳实践与建设建议10.1 从最小可运行闭环开始不要一开始就铺开十几个组件。先把模型调用、工具注册、Agent Loop、日志 Trace 这四件套跑通再逐步加记忆、向量库、多 Agent 协作。最小可运行闭环是一切后续功能的基础。10.2 把形态和 Infra 解耦在选择 Agent 框架时注意框架是否依赖特定的 Infra 组件。如果一个框架要求你必须用它自己的队列、自己的状态存储、自己的工具协议迁移成本会很高。尽量选“可以嵌入现有运行环境”的框架而不是“要求你重建运行环境”的框架。10.3 执行轨迹必须完整每轮模型调用、每个工具调用、每个中间结果都要写入 Trace。这个投入在后期的排障、效果评估、成本分析里会成倍回报。10.4 批量任务要内置幂等和重试任务队列消费端一定要判断任务状态处理成功的不再处理。重试加指数退避避免雪崩。10.5 发布前做效果复核Agent 的随机性比传统程序高很多。同样的输入不同时间可能产出不同结果。发布或商用前要有评估流程至少跑一组测试用例确认输出质量稳定。10.6 控制外部工具调用风险工具调用是 Agent Infra 的高价值功能也是高风险功能。对每类工具要单独定义失败策略失败是重试、跳过、还是终止整个任务。特别是写操作类工具默认应该禁止自动重试避免重复下单、重复扣款这类问题。11. 总结与下一步Agent 形态确实一天一个样但 Infra 建设的核心问题始终没变执行链路要稳定工具连接要统一状态管理要可靠日志轨迹要完整安全边界要清晰。把这五件事做好无论上层形态怎么切换底层都不会成为瓶颈。如果现在团队刚开始做 Agent Infra最先应该验证的是“一个带工具调用的执行闭环能否稳定跑通”比如让 Agent 完成一个需要调用两次工具的任务并完整记录执行轨迹。最容易踩的坑是“过早追求复杂形态”在单 Agent 循环都没稳定时就去铺多 Agent 协作和大量 MCP 集成。下一步可以按这个顺序扩展先补可观测性和评估体系再补记忆与上下文管理然后考虑多 Agent 协作和更复杂的工具编排。接外部系统时优先通过工具网关统一接入不要每个 Agent 各接各的。Infra 建设的最终目标不是追新框架而是让自己拥有快速落地任何一种 Agent 形态的能力。形态会变但稳定边界和通用能力不会变这才是 Infra 真正该服务的东西。