AgentScope (Alibaba)
一句话定位
AgentScope 2.x 是阿里 Tongyi Lab(GitHub org agentscope-ai,仓库 28k★)维护的开源
Agent 框架,采用**“库 + 运行时服务”两层结构:库层 src/agentscope/ 提供一个统一的
Agent 类(异步事件流 ReAct 循环)、Toolkit、独立 PermissionEngine、中间件系统、
Workspace 沙箱与 ChatModelBase/Formatter 模型抽象;服务层 src/agentscope/app/
把库层 agent 包成 FastAPI 多用户运行时,带 session 持久化、credential 管理与多 agent 团队
编排。README(README.md:70)自陈的设计哲学是”给 agent 透明、可控的能力,而不是用严格
prompt + opinionated orchestration 去束缚它”。这一框架同时是同厂QwenPaw**(Agent OS
应用层)的底座——写本页时区分两者:AgentScope = 引擎,QwenPaw = 长在引擎之上的操作系统层。
核心架构总览(目录结构关键路径 + 引用的 commit)
- repo(已验证):https://github.com/agentscope-ai/agentscope
- commit:
1aeb03d004292799091d437aaaf9486b424ecfa6(2026-07-10 15:39:07 +0800, messagefeat(service): support to share resource (credential, agent, knowledge bases) across different users as a group or org (#1998)) - 版本:
2.0.4(src/agentscope/_version.py)。注意 QwenPaw 固定依赖agentscope==2.0.2, 本次克隆是其更新版;核心 API(Agent/ReActConfig/Msg+AgentState/Toolkit/PermissionMode/ChatModelBase/中间件钩子)与 QwenPaw 引用一一对上。 - 克隆:
git clone --depth 1 ...,2026-07-11 拉取分析。 - 仓库内无独立 ARCHITECTURE 设计文档(
docs/仅 NEWS/changelog/roadmap),架构信息全部 从源码读出。
两层的关键路径:
src/agentscope/ ← 库层(QwenPaw 的底座)
├── agent/_agent.py (2836 行) 统一 Agent 类:ReAct 循环 / 工具 dispatch / prompt 组装 / 权限落地 / 压缩
├── agent/_config.py ReActConfig / ContextConfig / SummarySchema / ModelConfig
├── tool/_toolkit.py Toolkit:工具/MCP/skill 注册与 dispatch 中枢
├── tool/_base.py ToolBase 契约 + 每工具权限 hook(check_permissions/match_rule)
├── tool/_builtin/* bash/read/write/edit/grep/glob/meta(ResetTools)/skill(SkillViewer)
├── tool/_task/* 单 agent 内 TODO 式任务工具
├── permission/_engine.py,_types.py PermissionEngine + 5 种 PermissionMode
├── state/_state.py AgentState(全量可序列化)+ ToolContext(读缓存) + TaskContext
├── middleware/_base.py MiddlewareBase 5 钩子
├── middleware/_longterm_memory/ AgenticMemory / mem0 / reme 三后端长期记忆
├── middleware/_tracing/* OpenTelemetry GenAI semconv
├── workspace/_base.py + 后端 Local/Docker/E2B/K8s/OpenSandbox 沙箱,同时充当 offloader
├── model/_base.py + formatter/* ChatModelBase(~10 家 provider)+ 每家一个 Formatter
└── app/ ← 服务层:FastAPI 运行时
├── _tool/_agent_create.py 团队工具 TeamCreate/AgentCreate/AgentInvite/TeamSay
├── _types.py (SubAgentTemplate) 子 agent 模板
├── message_bus/* InMemory / Redis 消息总线
├── _router/* session / credential REST 路由
└── storage/* Redis session 持久化
Agent Loop(主循环 / 何时继续何时停)
统一 Agent 类(agent/_agent.py:97,2836 行),非继承式(旧版拆 AgentBase/ReActAgent,
本版收敛为单一 Agent)。构造签名含 name/system_prompt/model/toolkit/middlewares/state/ offloader/model_config/context_config/react_config。全异步、事件流架构。
- 入口:
reply()(消费所有事件返回最终Msg)/reply_stream()(流式yield AgentEvent), 两者都进_reply→_reply_impl(_agent.py:664)。 - 循环体(
_reply_impl:745):while self.state.cur_iter < self.react_config.max_iters,max_iters默认 20(agent/_config.py:126)。每轮先_check_next_action()决定reasoning/acting/exit。 - 停机判定(
_check_next_action:2542,真值表):- 有可执行 tool call(state
PENDING/ALLOWED)→acting; - 无可执行但有 awaiting tool call(
ASKING等用户确认 /SUBMITTED等外部执行)→exit, 把控制权交回外部,等 HITL 事件再续; - 都没有 →
reasoning(再问模型); - reasoning 生成纯文本且无 tool call → yield 一个
Msg,ReplyEndReason.COMPLETED,退出。
- 有可执行 tool call(state
- 额外退出路径:超
max_iters→ExceedMaxItersEvent+ReplyEndReason.EXCEED_MAX_ITERS(约 :861-879);asyncio.CancelledError→ReplyEndReason.INTERRUPTED。 - 一等 HITL / 可恢复:
reply()的inputs可以是Msg,也可以是UserConfirmResultEvent/UserInterruptEvent/ExternalExecutionResultEvent——循环可被 park 后用外部事件续跑,把”人类确认 / 外部工具执行”做进 loop 状态机。 - 工具并发:
_batch_tool_calls(约 :1336)按tool.is_concurrency_safe分成 sequential / concurrent 两批,分别走_execute_sequential_tool_calls/_execute_concurrent_tool_calls(asyncio 并发)。
记忆与上下文管理(压缩、长期记忆、会话持久化)
三层结构:
- 短期上下文 =
AgentState.context: list[Msg](state/_state.py:159)+AgentState.summary(压缩摘要,:156)。_prepare_model_input(agent/_agent.py:2280)拼装顺序:SystemMsg→ (若有)summary包成UserMsg→context。 - 原生上下文压缩:
compress_context()(_agent.py:271)在每次 reasoning 前调用。- 触发阈值:估算 token(
model.count_tokens)超过trigger_ratio(默认 0.8,_config.py:57) * model.context_size才压。 - 方式:结构化 LLM 摘要——
SummarySchema(_config.py:9)5 字段(task_overview / current_state / important_discoveries / next_steps / context_to_preserve),用 continuation-summary prompt 引导模型输出,套 summary_template 拼进state.summary, 保留尾部reserve_ratio(默认 0.1,_config.py:62)的原始 context。等价 Claude-Code 的 /compact。 - 带
on_compress_context中间件钩子——QwenPaw 的 “Scroll strategy” 就是在此层定制。
- 触发阈值:估算 token(
- 工具结果压缩/卸载:单个 tool result 超
tool_result_limit(默认 50000 tokens,_config.py:112)就截断并插<<<TRUNCATED>>>reminder;若配了offloader,把截断部分落盘并在 reminder 给出文件路径供 agent 按需再读。 - 文件读缓存:
ToolContext.read_file_cache(state/_state.py,LRU、按 mtime 失效)。
长期记忆(可选中间件,见”自进化”章):AgenticMemory / mem0 / reme 三后端。
会话持久化:AgentState 是 pydantic 模型,可整体序列化(含 context/summary/tool_context/
tasks_context/permission_context/middle_context,state/_state.py:149);服务层
app/storage/_redis_storage.py + session router 做 per-session 落盘与恢复。
工具体系(定义/调用协议/注册/权限)
Toolkit(tool/_toolkit.py:66)是唯一的工具/MCP/skill 注册与 dispatch 中枢。
- 定义契约:
ToolBase(tool/_base.py:94),类属性name/description/input_schema(JSON Schema)/is_concurrency_safe/is_read_only/is_external_tool/is_state_injected/is_mcp, 实现call()返回ToolChunk或AsyncGenerator[ToolChunk](流式统一)。Python 函数可从 docstring + Pydantic 自动生成 schema。 - 调用协议:
Toolkit.call_tool(tool_call, state)——tool_call是ToolCallBlock(含id/name/input),累加成ToolResponse(state: OK/ERROR/DENIED/INTERRUPTED);工具间用ToolResultBlock(tool_call_id关联)回填 context。这套Msg+ block 契约就是 QwenPaw 继承的那套。 - 注册/分组:工具按
ToolGroup组织,永远有一个"basic"组(构造入参tools/mcps/skills默认进 basic)。 - 动态激活(agentic):内建 meta tool
ResetTools(tool/_builtin/_meta.py;tool/_toolkit.py:157注册)让 LLM 自己激活/停用工具组——只有注册了非 basic 组时才暴露该 meta tool;调用未激活组的 工具返回ToolGroupInactiveError提示先激活。这是”渐进披露工具”以省 context。 - 内建工具(
tool/_builtin/):bash/read/write/edit/grep/glob/meta(ResetTools)/skill(SkillViewer) ——Claude-Code 同款工具集;另有tool/_task/(create/get/list/update_task)。 - MCP:一等公民,
Toolkit直接注册MCPClient,_get_available_tools里await client.list_tools()动态拉取;支持须已连接的 stateful client。 - 工具中间件:
ToolMiddlewareBase(tool/_base.py:36)洋葱式包裹单个工具执行,与 agent 级 中间件独立。 - 权限:工具自带
check_permissions/match_rule,由引擎裁决(见”安全与权限”)。
Prompt 设计(系统提示结构、动态组装)
_get_system_prompt(agent/_agent.py:2255)动态拼装,顺序:
- 用户给的
self._system_prompt(基础); - skill 说明(
toolkit.get_skill_instructions(activated_groups))——只拼当前激活组的 skill; - workspace/offloader 说明(若 offloader 是
WorkspaceBase); - 逐个过
on_system_prompt中间件(transformer 模式,字符串进出)——长期记忆中间件在此注入 MEMORY.md。
工具 schema 不进 system prompt,走 _prepare_model_input(:2280)的 tools 参数(标准
function-calling)。skill 说明模板 DEFAULT_SKILL_INSTRUCTION(tool/_toolkit.py:51)明确告诉模型
“skill 不是 tool,要用 SkillViewer 工具去读全文再照做”;工具组说明用 Jinja2 渲染当前激活组 +
<tool-instructions>。
Router / 编排(任务分解、多 agent、子 agent)
核心库层没有内建多 agent 编排——单个 Agent 就是一个 ReAct worker。编排在服务层 app/:
- 团队模型(star 拓扑):
app/_tool/暴露给 leader agent 一组团队工具TeamCreate/AgentCreate(app/_tool/_agent_create.py:140)/AgentInvite/TeamSay/TeamDelete。AgentCreate从SubAgentTemplate(app/_types.py:83)spawn 一个 worker(source='team'),prompt作为 worker 第一条 user message,worker 立即开跑;subagent_type枚举由开发者注册的 模板集合决定(类似 Claude Code 的 subagent type)。- 拓扑硬约束(prompt 硬编码,约 :168-173):所有成员只向 leader 汇报,禁止成员间通信、 禁止建 “integrator” 成员——刻意保持星形而非图状,降低通信复杂度。
- 通信底座:
app/message_bus/——MessageBus抽象 +InMemoryMessageBus(asyncio.Queue pub/sub)/RedisMessageBus;key 空间含 session_events / inbox / wakeup_queue / cancel/interrupt channel 等。 - 任务分解(单 agent 内):库层
tool/_task/+TaskContext(state/_state.py)提供 TODO 式 任务清单(pending→in_progress→completed),是单 agent 自我编排,非多 agent。 - QwenPaw 的 Goal/Mission 多模式编排是它自己在应用层另做的,并未复用这套 app 团队工具——是条 值得点出的边界。
Skill / 插件体系
Skill = Claude-Code / Anthropic Skills 同款(一个目录 = 一个 skill,含 SKILL.md + 脚本 + 资源), 与 tool 严格区分:
- 注册:
Toolkit(skills_or_loaders=[...])接受目录路径 /Skill对象 /SkillLoaderBase;skill/模块有SkillLoaderBase+ 本地目录加载器。 - 使用协议:skill 不能直接调用;system prompt 里列出可用 skill(name/description/dir),模型必须先用
内建
SkillViewer工具(tool/_toolkit.py:166注册;tool/_builtin/_skill.py)读取 skill 全文, 再照做。 - 分组:skill 也归属 tool group,随组激活(
get_skill_instructions(activated_groups))。 - 插件层 = MCP(见工具体系章)——外部能力通过 MCP client 接入,无私有插件协议。
自进化能力(自我改进 / 学习型记忆 / eval 驱动纠错)
框架核心无 RL / eval 驱动纠错 / 参数自更新(在 src/agentscope 内 grep
trajectory|reward|reinforcement|rollout|fine.?tun 无实质命中,仅 scheduler/prompt 文案)。
最接近”学习”的是长期记忆中间件(middleware/_longterm_memory/),三后端:
AgenticMemoryMiddleware(_agentic_memory/_middleware.py:208)——filesystem MEMORY.md 式, 由 LLM 自己决定何时/存什么,几乎逐字复刻 Anthropic memory skill:memory 分 user/feedback/project/ reference,两步保存 = 写独立 md 文件 + 在 MEMORY.md 加一行索引(约 :126-142),还带”memory 会过期, 用前先核实当前状态”的告诫。检索:on_reply时起一个 asyncio 异步任务用 LLM 从文件名 + 描述里选 最相关 ≤5 个记忆文件,结果在on_reasoning消费——检索与推理重叠以省延迟。- 另两后端:
_mem0(Mem0 适配 + 记忆工具)、_reme(agentscope-ai/ReMe,即 QwenPaw 默认长期记忆)。
定性:这是”经验记忆”式自改进(跨会话积累事实/偏好),不是 eval/RL 闭环——有记忆型(非训练型) 自改进。
可观测性(日志 / trace 格式)
OpenTelemetry 原生(middleware/_tracing/):
TracingMiddleware挂在 agent 中间件链上,为 reply / reasoning(LLM) / tool 三级各开一个 span。- 语义遵循 OTel GenAI semconv——直接
from opentelemetry.semconv._incubating.attributes import gen_ai_attributes,span 属性含 model / token / tool 等标准gen_ai.*字段。 - 未调用
setup_tracing时用 no-op provider,零开销。 - 事件流本身即可观测面:
event/_event.py定义大量AgentEvent(ReplyStart/End、 ModelCallStart/End、ToolResultStart/End、RequireUserConfirm、ExceedMaxIters 等),reply_stream全量吐出,前端/日志可订阅。 - 服务层另有
middleware/_budget.py(预算)、_tts_middleware.py等。
安全与权限(审批门、密钥管理)
独立 PermissionEngine(permission/_engine.py:17),Claude-Code 式规则引擎:
- 5 种
PermissionMode(permission/_types.py:18,源码内附完整对照表):DEFAULT(每次问,除非 allow 规则或工具自判只读)/ACCEPT_EDITS(工作目录内读写/文件命令自动放行)/EXPLORE(只读, 改动一律 deny)/BYPASS(跳过安全检查,只认用户 deny/ask 规则——QwenPaw 就是设成 BYPASS 关掉 原生引擎换自己的 Gate 系统)/DONT_ASK(把所有 ASK 转 DENY,无人值守安全默认)。 - 规则:
PermissionRule(tool_name + rule_content + behavior),behavior ∈ ALLOW/DENY/ASK/PASSTHROUGH(permission/_decision.py,_types.py);引擎持 allow/deny/ask 三张表。 - 每工具自带匹配逻辑:
ToolBase.check_permissions()+match_rule()(tool/_base.py)。Bash 做 命令级——只读命令(ls/git status)自动放行,危险模式(rm -rf /、写~/.bashrc)触发 ASK; Write/Read/Edit 做 glob 路径匹配;有dangerous_files/dangerous_directories黑名单。 - 审批门落地:
_execute_tool_call(agent/_agent.py,约 :1563)调engine.check_permission; ASK/PASSTHROUGH → 置 tool call state=ASKING并 yieldRequireUserConfirmEvent,loop 退出等UserConfirmResultEvent;DENY → 回ToolResultState.DENIED;ALLOW → 执行;已确认过的(state=ALLOWED)跳过复检。 - 密钥管理:
credential/模块 +CredentialBase(model/_base.py:42的credential);服务层app/_router/_credential.py做 API key CRUD,#1998 支持跨用户/组织共享 credential。
沙箱与执行隔离
Workspace 抽象(workspace/_base.py),一个 workspace 同时提供 resources(skills) / tools(MCP +
内建) / offload(落盘) 三件事,多种后端:
LocalWorkspace(本地文件系统,无隔离)DockerWorkspace(容器;自带 Dockerfile 模板 + node 变体)E2BWorkspace(E2B 云沙箱)K8sWorkspace(Kubernetes)OpenSandboxWorkspace(远程 OpenSandbox)
统一 BackendBase(_sandboxed_base.py)抽象路径/命令执行;固定目录布局
{workdir}/{.mcp, data/, skills/, sessions/}。还有 _mcp_gateway/(MCP 网关)和
_offload_protocol.py(context/tool result 卸载协议)。workspace 同时充当 Offloader——agent 的
offloader 参数接 WorkspaceBase,把截断的工具结果/压缩上下文写进沙箱文件系统供 agent 再读。
与模型的协同设计
ChatModelBase(model/_base.py:35)统一接口:credential/model/stream/max_retries/retry_delay/context_size(默认 32768,model/_base.py:68,直接喂给上下文压缩阈值计算) +count_tokens。provider 可替换——已内建 openai(chat & responses)/anthropic/gemini/dashscope/ deepseek/moonshot/ollama/xai 等 ~10 家(model/_*/)。FormatterBase(formatter/)每家一个 formatter——把统一的Msg+ block 契约翻成各家 wire 格式(tool_call/tool_result 块、reasoning 块、多模态)。这是”一套 Msg 契约 × N 家 API”的解耦点,也 是 QwenPaw 能换 provider 的原因。- 重试/fallback:
ModelConfig(agent/_config.py)带max_retries+fallback_model;主模型 失败自动切 fallback,retry 仅对_get_retryable_exceptions()声明的异常生效。 - 流式:整条链路(model→agent event→tool)都是
AsyncGenerator,ChatResponsechunk 经_convert_chat_response_to_event转 agent event。
轨迹利用(session/trajectory 是否反哺训练/评测)
- 有 session 持久化:
AgentState(全量 pydantic 状态)+ 服务层app/storage/(_redis_storage.py+_model/)+app/_router/_session.py做 per-user/per-session 落盘、恢复、session_events。 - 无训练/RL/eval 反哺:框架内没有把 trajectory 导出去做 SFT/RL/reward 的任何管线(无 trainer / rollout / reward)。session 数据用途 = 运行时恢复 + 可观测(OTel)+ 前端回放,不是训练语料生成。
- 定性:有轨迹持久化/回放,无轨迹→训练闭环(限本仓库;阿里内部或 sibling repo 是否另有,未在此 仓库出现)。
与同类 harness 的关键差异(1-3 条)
- “库 + 运行时服务”两层同仓:多数 harness 要么是单体 CLI(Claude Code、Codex CLI),要么是纯编排
库(LangGraph、AutoGen)。AgentScope 把一个统一
Agent(库)+ FastAPI 多用户运行时(服务,含 session 持久化、credential、team)打进同一个包,可当 SDK 也可当托管后端——这是它成为 QwenPaw 之类 Agent OS 底座的直接原因。 - 权限做成独立引擎 + 5 模式,且可被下游整体旁路:
PermissionEngine是与工具解耦的规则引擎,PermissionMode.BYPASS允许下游(QwenPaw)关掉整套原生审批换自己的治理层——权限层被设计成”可替换的 插槽”而非硬编码,同类 harness 少见这种显式旁路点。 - 工具/skill/记忆三处都对齐 Anthropic 心智模型:内建工具集是 Claude-Code 同款、skill 是 Anthropic
Skills 同款(SkillViewer 先读后做)、
AgenticMemory几乎复刻 Anthropic memory skill——是一套刻意贴近 Claude 生态惯例的开源实现,迁移成本低。
原始源码定位
- repo: https://github.com/agentscope-ai/agentscope
- commit/version analyzed:
1aeb03d004292799091d437aaaf9486b424ecfa6(version 2.0.4, 2026-07-11 克隆分析) - 关键文件列表(相对
src/agentscope/):agent/_agent.py(2836 行,核心:loop / 工具 dispatch / prompt / 权限落地 / 压缩)agent/_config.py(ReActConfig / ContextConfig / SummarySchema / ModelConfig)tool/_toolkit.py、tool/_base.py、tool/_builtin/*、tool/_task/*permission/_engine.py、permission/_types.pystate/_state.pymiddleware/_base.py、middleware/_longterm_memory/_agentic_memory/_middleware.py、middleware/_tracing/*workspace/_base.py+_docker/_e2b/_k8s/_opensandbox后端model/_base.py+formatter/*app/_tool/_agent_create.py、app/_types.py(SubAgentTemplate)、app/message_bus/*、app/_router/*、app/storage/*
一手源存档(sources/)
保存于 /Users/zhao/projects/self-wiki/ai-research/sources/harness/agentscope/:
NOTES.md——第一阶段源码级调研笔记(含 12 维度、验证信息、QwenPaw 交叉引用)src/(12 个核心文件,332K,文件名以模块__文件.py展平):agent__agent.py、agent__config.pytool__toolkit.py、tool__base.pypermission__engine.py、permission__types.pystate__state.pymiddleware__base.py、agentic_memory__middleware.pyworkspace__base.pymodel__base.pyapp_tool__agent_create.py