不为某个新特性,而是没道理把底座停在带并行 tool-result 缺陷的补丁版;2.0.3 是同线相邻补丁版,升级面窄、收益确定。承 tech-decisions §11-13「护城河进洋葱、 框架件谨慎审计」线。 代码:两 worker requirements 钉 2.0.3+溯源注;4 个 cheap-worker patch 的版本 guard 更 2.0.3——主控逐一源码核实 2.0.3 锚点仍成立:compress_context@_agent.py:259 未漂移 / _parse_stream_response@_openai_chat/_model.py:297·index 分桶:417 未漂移 / list_tools@_local_workspace.py:660 / get_toolkit 装配点迁 _chat.py:354(patch 替 绑定名不依赖行号);patch 头 pin 声明同步 2.0.3+复核标记,根因 2.0.2 期实证保留。 文档:current-truth 面扫除(agentscope-2.0-facts 改掉一处「2.0.3 是笔误」错陈述+ 行号漂移开源码更新 594→622/136→162/33→42/857→884/875→902、tech-decisions §15 升级决策散文、运行时 SoT 当前选型句、活代码注释、tier2 README 死链修);留痕层 (plans/HANDOFF/patch 根因分析/ADR 历史核验句)按两层纪律不动。 兼容三证:源码逐处 diff(RedisMessageBus/OpenAI formatter 零变化、Anthropic formatter 仅并行 tool-result bug 修、ModelCallEndEvent 无变化、MiddlewareBase 加性 get_middleware_key)/ cheap 393+tier2 140+patch 20 测试全绿 / dev 两 venv 升级后 3 服务健康。收敛真跑:cheap 便宜档 ReAct 全链路 356 trace 零升级异常+ 真出游戏过九门 9/9;tier2 Anthropic 工具循环跑满 40 轮写 15 文件 gen.log/trace 零升级异常(decision=fix 属 tier2 生成质量、非升级回归)。 2.0.3 新增原生 ReplyBudgetControlMiddleware(历史反复核验 2.0.2 不存在的类)/ tool 级洋葱/RAG/mem0,列而不迁(自建 ¥ 两段式 fail-closed 硬闸是护城河,原生 token 软控替不了),follow-up 见 §15。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
13 KiB
name, description, node_type
| name | description | node_type |
|---|---|---|
| agentscope-2.0-facts | AgentScope 2.0 架构事实速查(源码实证 v2.0.3 + 官方文档)——编排/沙箱/服务化部署,给 tier2 富游戏线设计用 | knowledge |
AgentScope 2.0 架构事实(源码实证 + 官方文档)
本文记录 AgentScope 2.0 的真实形态。来源是直接读 /root/oss/agentscope(checkout 在正式版 v2.0.3,即项目当前锁定的稳定版)的源码,并与官方文档 docs.agentscope.io/v2 交叉验证,每条关键结论都给了源码出处。
版本口径:项目当前钉 AgentScope 2.0.3,2026-07-06 从 2.0.2 升级而来。2.0.3 已正式发布到 PyPI,此前文档里「PyPI 没有 2.0.3、那是笔误」的说法不再成立,据此更正。1.0.x 到 2.0.x 是同一条线的连续大版本演进,2.0.2 与 2.0.3 是这条线上相邻的两个补丁版;本文事实已按 2.0.3 源码逐条复核。引用时以项目锁定的 2.0.3 为准。
核心范式
2.0 是一次架构大重写。1.x 的静态编排原语(pipeline / MsgHub / sequential_pipeline)已经全部删除——在 src/ 下搜这些类名零命中。取而代之的是「单个自带 ReAct 循环的 Agent 类 + 一个 FastAPI 服务层(agentscope.app)」。多 agent 协作、对外发布、沙箱执行这些能力,都上移到了服务层,而不再是库里的拼接式管道。
编排:单 Agent 自治 + 服务层 Team 工具
agentscope.agent 模块只导出一个统一的 Agent 类,它自带 reasoning→acting 的 ReAct 循环(agent/_agent.py:622 的迭代主体,max_iters 兜底退出)。1.x 那种声明式的 agent 子类(ReActAgent / DialogAgent)和消息管道都不存在了。
需要多个 agent 协作时,走的不是静态拓扑图,而是把「建队、派 worker、对话」做成工具交给 leader agent 自己调用:AgentCreate / TeamCreate / TeamSay / TeamDelete 四个工具配 SubAgentTemplate(worker 蓝图)。leader 调 AgentCreate 就 spawn 一个 worker agent + session,worker 的 source="team"、只拿得到 TeamSay(向 leader 汇报),leader 拿全套工具(app/_service/_toolkit.py 按 source 选工具可见性)。这是 agent-as-tool 的动态组队,对应官方哲学——靠模型自身的推理和工具调用,而不用刚性 prompt 和带倾向的编排去约束它。
一个硬约束:这套多 agent 能力只在 app 服务层可用,纯库里 import 一个 Agent 跑脚本是没有的。
沙箱:编排后工具调用直接落沙箱执行
Workspace 提供三种执行后端(workspace/__init__.py):LocalWorkspace(host 进程内,零隔离,开发用)、DockerWorkspace(容器)、E2BWorkspace(E2B 云沙箱)。agent 的工具来自 workspace(get_toolkit(workspace=...) 时 tools = await workspace.list_tools()),所以「换一个 workspace」就把执行环境从本地搬到了容器或云沙箱。
执行如何落进沙箱:Local 后端的 Bash/Read/Write 是 host 进程内的 Python 工具;Docker/E2B 后端的 list_tools() 返回空,工具改由容器内的 FastAPI MCP gateway 提供——agent 调工具时,host 侧 GatewayClient 发 HTTP POST {gateway}/mcps/{mcp}/tools/{tool}(_gateway_client.py:162)到容器内 gateway 真正执行。这就是「编排好之后工具调用直接在沙箱里跑」的机制。
一个坑:Docker/E2B 沙箱镜像默认不注册任何 filesystem/bash MCP,要在沙箱里有 Bash/Read/Write,得自带 MCP server 注册为 default_mcps;只有 Local 后端内置这些工具。
安装与部署:pip 装包即可,官方只主推一条生产路径
跑 AgentScope 不需要 clone 仓库——pip install agentscope[full] 装包即可,app / workspace / tool 全在 wheel 内。框架没有 CLI(pyproject 无 [project.scripts],不存在 as serve 之类命令),启动靠在 main.py 里自己调 uvicorn。两个例外要记:Docker 沙箱早先在 2.0.x 尚未上 PyPI 的过渡期需要本地备有 agentscope 源码(构建镜像时 COPY 进去)——2.0.3 已发布到 PyPI,这条过渡期约束随之解除,镜像可直接 pip 安装;E2B 沙箱仍需 E2B 账号和 API key。/root/oss/agentscope 这份 clone 的主要价值是读源码核对,而非生产运行的必需品。
生产部署,官方主推且唯一给出端到端示例的形态是 Agent Service:用 create_app(storage, message_bus, workspace_manager) 造一个 FastAPI/ASGI app(app/_app.py:42),再用 uvicorn 起进程(examples/agent_service/)。它提供多租户、多会话、REST 触发 + SSE 事件流、HITL 审批、定时任务、凭据托管。两个要点决定了接入方式:一是 chat 端点是 fire-and-forget,POST /chat 立即返回 started,事件要另外从 GET /sessions/{id}/stream 的 SSE 流里收;二是强依赖 Redis——storage 和 message_bus 都只有 Redis 实现,没有 in-memory/SQLite 版本,生产必须配 Redis。要弹性扩展,就把这个 ASGI app 自己容器化后上 K8s 或 serverless,框架不提供 app 级的 Dockerfile/compose。
生态定位与一个架构信号
独立的 agentscope-runtime 项目已归档:官方声明其全部能力(工具沙箱、Agent-as-a-Service、可观测)已原生并入 AgentScope 2.0。所以 2.x 做沙箱和部署不要再装那个独立仓,agentscope[full] 一个包就齐。AgentScope Studio 是开发期的可视化追踪/调试台,不是生产承载层。
一个值得记的信号:官方称 Spring AI Alibaba 底层将采用 agentscope-java 作为引擎。这意味着项目里「SAA 廉价线」和「AgentScope 富游戏线」在引擎血统上正趋同。这条长期架构判断已裁定(2026-06-25 reframe):框架收敛 AgentScope、SAA 降最低优先级(留作远期适配验证可插拔的目标)——三档生成不再按引擎或产线分,而按 AI 参与深度切;详见运行时 SoT 生成引擎/agentic运行时架构图说 §一 / §四。相关决策见 saa-agentic-infra-decision。
关键纠偏对照
| 凭名臆想 | 源码实证(v2.0.3) |
|---|---|
| 2.x = pipeline / MsgHub | 已删,改单 Agent ReAct + 服务层 Team 工具 |
| 多 agent 是静态编排图 | agent-as-tool 动态组队,且只在 app 服务层 |
| 用框架要 clone 源码 | pip install agentscope[full] 即可(Docker 沙箱过渡期暂需源码) |
有 CLI / serve 命令 |
无,生产 = create_app() FastAPI + uvicorn + Redis |
| 沙箱要装独立 agentscope-runtime | 已归档,能力并入 2.0 主框架 |
便宜档 cheap-worker 实现 API 速查(2.0.3 源码实证 + WU-A spike 落地)
上文偏架构(编排/沙箱/服务化)。本节是「怎么用库写一个跑通的 agent」的实现层速查——WU-A spike 把便宜档生成核心重写进 AgentScope(cheap-worker/,import 复用 tier2 框架层)时落地并核验,下一个 WU-A 全量重写 / n=5 直接照用,不必重新挖。
import 路径(全部源码核验存在):from agentscope.agent import Agent, ReActConfig, ContextConfig · from agentscope.tool import Toolkit, FunctionTool · from agentscope.middleware import MiddlewareBase · from agentscope.model import OpenAIChatModel, AnthropicChatModel · from agentscope.message import UserMsg, TextBlock · from agentscope.state import AgentState · from agentscope.permission import PermissionContext, PermissionMode。
三个「凭名臆想会用错」的不存在 API(源码全树零命中,别用):
register_tool_function不存在 → 注册靠构造器Toolkit(tools=[FunctionTool(fn), ...])。ReplyBudgetControlMiddleware不存在 → 预算/软刹得自挂MiddlewareBase的on_system_prompt/on_model_call钩子(tier2 的CircuitBreakerMiddleware即如此自实现)。- 内置 ReAct 不会「跑满 max_iters 才停」 → 在「模型产出无 tool_call 的纯文本回合」即退出(
agent/_agent.py)。要多轮自修必须在 Agent 外自建有界 resume 循环:for attempt in range(max_resumes): await agent.reply(...); 判收敛/门绿;否则带失败反馈再 reply。这一圈正对应 Node 生成 harness 的 while 主循环。(2026-07-02 阶段一① 更新:tier2 已改用on_reasoningmiddleware 在洋葱内拦 finish 续修、取代这圈 Agent 外 resume——见下「护城河续修/软预算 middleware 的 2.0.3 机制」段与tech-decisions.md§11;外层 resume 仍留 fallback。)
工具写法(schema 自动抽):每个工具是 async def + 参数类型注解 + Google docstring(Args:),FunctionTool(fn) 据此抽 schema;闭包捕获一个可变 session 对象做跨工具状态;返回 str(纯文本或 json.dumps)。
Agent 构造(无人值守跑脚本):Agent(name, system_prompt, model, toolkit, middlewares=[trace, breaker], state=AgentState(permission_context=PermissionContext(mode=PermissionMode.BYPASS)), react_config=ReActConfig(max_iters=...), context_config=ContextConfig(...))。BYPASS 必给——否则 FunctionTool 默认 check_permissions 返回 ASK,无人值守跑会卡死。reply 是 async:await agent.reply(UserMsg(name="user", content=text))(UserMsg 必带 name)。model 直调(验连通用):await model([UserMsg(...)]) → ChatResponse(content=[TextBlock(text=...)], ...)。
便宜档复用 tier2 框架层(import 不重写、零改 tier2):config.build_model_openai("MiniMax-M3", max_tokens=16000, record=True)(OpenAI 协议、自动补 /v1、自动装代理旁路 + 取 key)· config.build_context_config()(历史压缩)· CircuitBreakerMiddleware + Tier2TraceMiddleware(四道熔断 + trace,与模型档无关,enable_rmb_gate=False 可关 ¥ 闸)· client.install_proxy_bypass(必须在 import openai 之前,否则本机 clash 把发往内网网关的请求转走得 502)· client.get_api_key()(只读 env NEWAPI_KEY;内网阶段 key 在 docs/内网凭据与端点.md,调用方先解析注入 env)。
跨包 import 含连字符目录:gen-worker 不能 import;把 tier2/gen-worker/ 加进 sys.path 再 from worker import ...(from observability import ... 同理)。
落地实证 = 便宜档 Python 线 cheap-worker/(WU-A spike,端到端九门对照 Node 9/9 持平、过门率 1.0=1.0、对 tier2 零改动)。便宜档生成线现状见 cheap-model-game-generation(注意其旧 W-G1 路已被 cheap-worker 取代)。
护城河续修/软预算 middleware 的 2.0.3 机制速查(阶段一① 落地,2026-07-02)
多轮自修除了在 Agent 外自建 resume 循环,还有护城河的正解——在 middleware 洋葱内拦 finish 续修、不每轮重开 POST(tier2 阶段一① 落地)。这里记住 2.0.3 的几个机制事实,免得下次碰 middleware 又去翻源码:
- finish 是什么:ReAct 在「模型产出无 tool_call 的纯文本回合」即退出,那个纯文本
Msg就是 finish。它在agent/_agent.py里先存进 context(约 :884,_save_to_context)再 yield(约 :902),穿过on_reasoning洋葱链才到 reply 收尾循环。 - 怎么拦、怎么续:
on_reasoningmiddleware 遍历next_handler吐的事件,遇到那个 finishMsg就不 yield(吞掉)——本轮没有 Msg,reply 循环cur_iter++继续下一轮推理,等于续跑。要让 agent 真去改,用agent.observe(UserMsg(...))注入一条 role=user 的反馈(system/tool/thinking 角色会让内部_handle_incoming_messages抛 ValueError)。注意吞掉 finish 前 agent 已把「做完了」文本存进 context,压制 yield 抹不掉,要context.pop()清掉才有干净血缘。 - 洋葱序:Service 框架在 extra middleware 外还前置了
InboxMiddleware(挂 on_reasoning、每轮 drain inbox 后透传全部事件、不吞 finish),所以工厂注入[tracer, repair, breaker]的实际 on_reasoning 链是[InboxMiddleware, tracer, repair]——repair 在最内层、能拦到_reasoning产的原始 finish(breaker 不挂 on_reasoning)。 - 软预算/门判为什么必须自挂:
ReplyBudgetControlMiddleware这类不存在(见上),预算软刹得自挂on_model_call(¥ 闸)/on_system_prompt(提醒);放行门判得 middleware 自己重跑run_gates独立判,绝不采信 agent 上报的门结果。
本项目落地的三个类(RepairMiddleware / CircuitBreakerMiddleware.soft_budget / gate_judge)与那个红线坑(run_gates 起跑前清 verdict 防陈旧假绿)见 tech-decisions.md §11。