QwenPaw
一句话定位
QwenPaw(原名 CoPaw,~/.copaw 仍作为遗留工作目录 fallback 保留于代码中)是阿里
AgentScope 团队维护的开源 “Agent OS” 应用层:它不是从零实现的 agent 循环,而是
构建在独立仓库 AgentScope 2.0(agentscope==2.0.2,pyproject.toml 第 8 行固定
版本)之上——AgentScope 提供 ReAct 循环基类、Msg/AgentState 序列化契约、工具调用层与
流式事件模型;QwenPaw 自己贡献的是操作系统层:workspace 边界、多模式(普通/Goal/
Mission/Coding)请求生命周期、Gate 停机系统、Scroll 上下文压缩策略、五层治理/沙箱信任
栈,以及技能/插件生态。长期记忆默认走内嵌的 ReMe(“ReMeLight”,同样是独立仓库
agentscope-ai/ReMe,本轮未克隆),其设计文档明确致谢 OpenClaw 的记忆机制启发
(memory.en.md 第 7 行)。
核心架构总览(目录结构关键路径 + 引用的 commit)
克隆方式:git clone --depth 1 https://github.com/agentscope-ai/QwenPaw(浅克隆,
main HEAD)。commit 085d6b2eaa3030e0e53d68514c23c9ea77480ecb(commit message
feat(ci): add QwenPaw review bot (#5736),2026-07-06 18:18:47 +0800),2026-07-07
拉取分析。
QwenPaw/ (Apache-2.0, PyPI 包名 qwenpaw)
├── src/qwenpaw/
│ ├── agents/
│ │ ├── react_agent.py — QwenPawAgent(CodingModeMixin, Agent),762 行,
│ │ │ 覆盖 _reasoning(),Gate 挂接,工具超时注册
│ │ ├── prompt.py / prompt_builder.py / templates.py — 系统提示组装
│ │ ├── md_files/{en,zh,ru,id}/{AGENTS,SOUL,BOOTSTRAP,HEARTBEAT,MEMORY,PROFILE}.md
│ │ ├── context/scroll/ — manager.py(431行) + eviction_index.py 等,
│ │ │ "Scroll strategy" 上下文压缩
│ │ ├── memory/ — ReMeLight/ADBPG 长期记忆管理器
│ │ ├── tools/ — 内建工具(shell/browser_control/agent_management/
│ │ │ delegate_external_agent/file_search 等)
│ │ ├── skill_system/, skills/ — 技能系统
│ │ ├── model_factory.py, routing_chat_model.py — 模型路由
│ │ └── acp/ — QwenPaw 作为 ACP server
│ ├── loop/gates/ — Gate 停机系统(iteration/budget/doom_loop/rubric)
│ ├── modes/{goal,mission,coding}/ — Goal Mode / Mission Mode / Coding Mode
│ ├── governance/ — policy.py(1317行)/audit.py(380行)/detectors.py 等
│ ├── security/tool_guard/, security/skill_scanner/, security/secret_store.py
│ ├── sandbox/ — linux/macos/windows/bubblewrap/local 后端
│ ├── plugins/ — PluginApi 六类扩展点
│ ├── local_models/ — llama.cpp 本地运行时(QwenPaw Local)
│ ├── observability/langfuse.py — 可选 Langfuse 集成
│ └── cli/main.py — click LazyGroup CLI 入口
└── website/public/docs/*.en.md — 官方设计文档,随仓库一并发布(本页主要证据来源之一)
Agent Loop(主循环 / 何时继续何时停)
- 基础 ReAct 循环本身在 AgentScope 2.0(
agentscope.agent.Agent、ReActConfig)里, 不在本仓库;QwenPaw 通过QwenPawAgent(CodingModeMixin, Agent)(react_agent.py第 46 行)子类化/包装它。 - QwenPaw 自身的核心贡献是 Gate 系统,在覆写的
_reasoning()方法内每轮 ReAct 迭代后运行(react_agent.py第 365-505 行):- 模型响应后调用
_run_stop_handlers()(第 683 行),按优先级顺序遍历所有注册的StopHandlerRegistration(loop/gates/runner.pyrun_stop_handlers,第 62-131 行)。 - 每个 Gate(
StopGate抽象基类,loop/gates/base.py)实现check(ctx) -> StopHandlerResult|None,返回STOP、CONTINUE(可携带continuation_message)或None(“无意见,交给下一个 gate”)——首个非None结果生效(文档称为”流水线”模型)。 - 内建默认 gate:
IterationGate(优先级 10,文档默认 max 50 / 代码常量默认max_iterations=20——文档层与代码常量层默认值不一致,本轮未进一步核实哪个是实际 生效值)、BudgetGate(优先级 20,默认 30 万 token)、DoomLoopGate(优先级 5, 滑动窗口工具调用重复检测,见下)、StandaloneRubricGate(优先级 90,纯文本输出 时重新提示,最多max_interventions次,默认关闭)。 - 延迟执行语义:若模型正处于工具调用中途,STOP 信号不会立即生效——暂存在
agent._gate_pending_stop,下一轮迭代才消费(apply_stop_result、check_pending_gates,runner.py第 134-195 行),确保正在执行的工具调用永不被 打断。 - 作用域隔离:gate 携带
scope字段(StopHandlerRegistration.scope);当非 默认作用域的 handler(如 Goal Mode 的)处于激活态时,默认作用域 handler 被过滤掉 (_filter_by_scope,runner.py第 16-59 行)——即 Goal/Mission 模式期间完全替换 默认 gate 集合,模式会话结束后默认 gate 自动恢复。 - 会话隔离:
LoopGate基类通过activate()/_state()/deactivate()维护 per-session 状态,确保同一 agent 的并发用户不共享 doom-loop/budget/iteration 计数器。
- 模型响应后调用
- Doom-loop 检测(
loop/gates/doom_loop.py,272 行全读):滑动窗口(默认window_size=3,文档默认配置 6)记录(tool_name, md5(args)[:8])签名;相似度公式1 - (unique-1)/(total-1);相似度达到阈值(代码默认 1.0 / 文档默认 0.8)且持续多个 窗口后,按配置的stages(每个{after: N, action: "modify_prompt"|"stop", message})升级——例如 2 次命中注入警告(CONTINUE),4 次命中强制STOP。每轮自动 从agent.state.context记录最新工具调用,常见路径无需手动调用record()。 - Goal Mode(
modes/goal/):单 agent、跨多个 HTTP 请求级 turn 的持久循环,靠GoalTurnGate(跨请求,区别于IterationGate的单请求内 ReAct 迭代)、GoalBudgetGate、包装可插拔RubricStrategy的RubricGate(GoalStatusRubric检查session.active,由update_goal工具置 false)。自我审计是文档记载的 提示工程纪律(“从需求推导具体检查项,逐条对照证据,未验证视为未完成”),叠加在 机械 gate 之上,而非代码里另一个独立的验证模型调用。 - Mission Mode(
modes/mission/):master→worker→verifier 流水线;Phase 1 产出 含 user stories 的 PRD(human-in-the-loop 确认),Phase 2 自主执行——master 被工具 限制(不能直接编辑文件/浏览器,必须委派),verifier agent 独立核对每条验收标准, 失败的 story 自动重试直至通过或迭代预算耗尽。文档明确记载的安全代价:worker/ verifier agent “自动绕过安全守卫,因为后台会话无法响应/approve”——文档明确警告 仅在完全可信的代码库中使用 Mission Mode。 - 循环系统可通过插件扩展:第三方插件可通过
PluginApi/StopHandler.register()注册自定义StopGate子类(loop-engineering.en.md给出TimeoutGate示例)。
记忆与上下文管理(压缩、长期记忆、会话持久化)
- 官方文档(
architecture.en.md“Memory and context” 节)明确区分两个概念: memory(跨会话、可插拔后端、基于 ReMe)vs context(当前模型窗口能装下什么、 可插拔策略:默认”摘要压缩”或选装的”Scroll strategy”)。 - 长期记忆(默认后端 = 内嵌 ReMe/“ReMeLight”,
agents/memory/ reme_light_memory_manager.py524 行,仅目录列出未逐行读,架构来自官方文档):- 管线:
Auto Memory(对话 → 每日 Markdown 笔记memory/YYYY-MM-DD/*.md,每 N 个 用户轮触发一次,默认auto_memory_interval=5)→Auto Dream(每日笔记 →digest/*.md长期节点 +interests.yaml主动话题,cron 触发,默认dream_cron="0 23 * * *")→Proactive(兴趣话题推送到 Inbox 供 agent/用户处理)。 - 混合检索(
memory_search工具)= BM25 关键词(权重 0.3)+ 可选向量检索(权重 0.7),按加权 Reciprocal Rank Fusion 融合:vector_contrib = 0.7/(60+rank),keyword_contrib = 0.3/(60+rank),逐 chunk 求和后降序排序。 - 备选后端:ADBPG(阿里云 AnalyticDB for PostgreSQL,仅 REST API,无直接 SQL 模式)——用于跨设备/多实例共享;热切换需要重启(不支持热重载)。
- 全部以纯 Markdown/YAML 落盘——设计上刻意要求应用不运行时也能人工阅读/编辑。
- 管线:
- 上下文(“Scroll strategy”)——这是 QwenPaw 在 AgentScope 原生上下文压缩之上的
自研贡献,也是本轮读到代码级别的部分(
agents/context/scroll/manager.py,431 行 全读):ScrollContextManager.on_save()——写穿(write-through):每个进入上下文窗口的 活跃 turn 立即持久化到 durablehistory.db(SQLite),在任何驱逐发生之前—— 即便进程中途崩溃也不会丢失未持久化的 turn。ScrollContextManager.compress()——当 token 数超过trigger_ratio * model.context_size时触发(复用 AgentScope 自身的count_tokens/配对安全切分):将上下文切分为固定头部 + 可驱逐中段 + 最近尾部; 被驱逐的中段折叠进上下文内的EvictionIndex,作为新的”Tier 0”块(不是摘要——该块 记录精确的seq区间,原始 turn 可逐字节恢复);重建agent.state.context = head + [index_placeholder] + tail。若折叠一次后上下文仍 过大,EvictionIndex.compact()会在一个”始终收敛”的循环里进一步压缩索引本身 (非无限循环)。- 恢复通过工具暴露给 agent:
recall_history_python(在持久历史之上的沙箱化 Python REPL——manager.py 模块 docstring 提及,REPL 实现在agents/context/scroll/repl.py,仅目录列出未全读)。 - 检查点:
to_dict()/load_state()往返所有去重记账信息(persisted_ids、persisted_tcids、seq_by_id、leaf_by_id、EvictionIndex本身),确保恢复的 会话不会重复追加已恢复的窗口。 - 留存:
purge_old(retention_days)在 agentclose()时删除history.db中早于 截止日期的行。 - 这正是 README “Never forgets” 声明的具体实现:“旧 turn 被驱逐但仍可按需召回; 没有东西被摘要掉或丢失”——在代码级别验证为真(仅针对 Scroll 策略;默认压缩模式 则会做摘要,不保留可召回性——Scroll 是可选项,非默认)。
- 会话持久化:
QwenPawAgent.state_dict()/load_state_dict()(react_agent.py第 173-240 行)同时处理原生 AgentScope 2.0AgentStatepydantic 模型往返和遗留 1.x 格式{"memory": {"content": [...], "_compressed_summary": ...}}的迁移路径—— 证明这是真实生产环境中的格式迁移,而非仅设计文档声明。
工具体系(定义/调用协议/注册/权限)
- 定义/注册:
@tool_descriptor装饰器在 import 时自动将函数收集进全局注册表 (agents/tools/__init__.pydocstring +discover_builtin_tool_funcs()委托给runtime.tool_registry.get_builtin_tool_funcs())。新增内建工具 = 装饰 + 在__init__.py中 import,无需手动维护列表。 - 调用协议:标准 AgentScope
Toolkit/工具调用块格式(tool_call/tool_use块含name+input,tool_result块以tool_call_id关联)——继承自 AgentScope,非 自研。 - 权限包装是全局且 agent 不可绕过的:每个工具在交给 agent 之前都被包装进
PolicyGuardedTool(react_agent.py第 105-114 行,内存工具注册处可见具体调用:PolicyGuardedTool(tool_fn, governor=..., request_context=...))。QwenPawAgent.__init__显式将self.state.permission_context.mode = PermissionMode.BYPASS(第 137 行)以关闭 AgentScope 自带的权限引擎,因为 QwenPaw 自己的 tool-guard/governance 栈(PolicyGuardedTool.check_permissions) 完全取代了它——即 QwenPaw 不是叠加两套权限系统,而是把 AgentScope 的换成了自己的。 - 单工具调用超时集中配置(
_register_tool_call_hooks,react_agent.py第 607-659 行)经由ToolCoordinator(request_context["tool_coordinator"])——例如execute_shell_command60 秒,chat_with_agent300 秒,check_agent_task30 秒,grep_search30 秒,glob_search15 秒,ast_search35 秒,desktop_screenshot30 秒,LSP 工具 20 秒,browser_use最长 3600 秒。 agent 配置级builtin_tools[...].timeout_seconds可覆盖单 agent 设置。 - 每次工具调用的治理决策流程(
governance/policy.py):ToolRegistry类型检查 →builtin_rules(不可变,系统所有)→user_rules(审批流程生成,“批准时智能泛化”: 首 token+glob 泛化,高风险命令保持精确匹配)→ 全局兜底。规则格式:GovernanceRule(match="Bash(git *)", action=ALLOW)风格的 glob-on-target 匹配, 区分”显式资源工具”(allow=直接执行)与”Bash 类工具”(allow=即便预授权也在沙箱内 执行,因为任意 shell 永远无法被完全预先审查)。四种可能动作:ALLOW/DENY/ASK/SANDBOX_FALLBACK。 - 每次受治理的调用都写入 SQLite
audit.db(governance/audit.py,含 tool_name/target/decision/reason)——详见可观测性章节。 - Access Policy(独立的文档记载层,目前仅针对 MCP):按
subject(身份)×principal(来源渠道/用户)×target(工具名/类型)匹配的 per-MCP-clientdefault_effect+ 优先级规则,最具体规则优先解析(security.en.md“Policy evaluation” 节)——这是声明式 YAML,独立于命令式的 Tool Guard 正则规则。
Prompt 设计(系统提示结构、动态组装)
- 系统提示在请求时由 agent 工作目录下最多 3 个 markdown 文件按固定顺序拼装:
AGENTS.md→SOUL.md→PROFILE.md(agents/prompt.pyPromptConfig.DEFAULT_FILES)。均为可选——缺失文件被静默跳过。AGENTS.md——行为规则(安全、内部/外部动作之间的”先问”边界、表情回应等社交行为、 heartbeat 块、工具/技能指引)。SOUL.md——未全读;按命名惯例与文档交叉引用,承载 agent 的人格/身份设定。PROFILE.md——由系统自动生成,来自 agent 名称+描述+技能+persona 文件(据multi-agent.en.md);供其他 agent 判断是否要委派任务给该 agent 使用。
- 通过 HTML 注释区段标记做动态拼接:
<!-- heartbeat:start -->...<!-- heartbeat:end -->与<!-- memory:start -->...<!-- memory:end -->正则 (PromptBuilder.HEARTBEAT_PATTERN、MEMORY_PATTERN)让构建器按条件剥离/注入这些 块(例如仅当heartbeat_enabled=True时才包含 heartbeat 块)。 - 无论 persona 文件如何都会注入的硬编码系统级指令:
DRIVER_POLICY_RECHECK_HINT(prompt.py第 29-40 行)——明确告诉模型此前driver_policy_denied的工具结果是 某个时间点的快照,若用户再次请求必须重新尝试,因为策略可能在对话中途变化。这是 harness 通过 prompt 工程(而非代码)修补一个具体观察到的 LLM 失败模式(过度泛化一次 过时拒绝)的具体例子。 - 本地化:默认 md 模板文件以 4 种语言发布(
en、zh、ru、id),外加角色专属变体 (qa/、local/),均位于agents/md_files/下。 - 内置示例插件
plugins/bundle/cloudpaw/展示了多 persona 捆绑模式:按角色 (orchestration、verifier、executor)× 语言各自独立的SOUL.md/PROFILE.md对——即提示组装机制被复用来构建一个固定的多 agent 团队,而非单一 persona。
Router / 编排(任务分解、多 agent、子 agent)
- 三种不同的多 agent 机制(据
multi-agent.en.md,源码仅目录列出未逐行读):- Multi-Agent Workspace——一个 QwenPaw 安装内 N 个独立 agent,各自隔离的
workspace(独立 memory/skills/history/channels)。配置拆分:全局
(
config.json:provider 密钥、环境变量)vs 单 agent (workspaces/{agent_id}/agent.json:channels、skills、history、cron、 persona)。 - Inter-Agent Collaboration(
multi_agent_collaboration技能,选装)—— agent A 调用qwenpaw agents list发现其他 agent 的Description+ 自动生成 的PROFILE.md,然后通过chat_with_agent/submit_to_agent委派;支持前台 (阻塞)与--background(返回task_id,通过check_agent_task轮询,状态流submitted→pending→running→finished)。 - In-Workspace Subagents(
spawn_subagent,v1.1.10 引入)——同 agent 配置下 的临时性子会话,用于项目内任务。fork=False(默认):空白会话,同一项目目录, 无对话历史。fork=True:继承父会话完整对话上下文;若开启 Coding Mode(或 workspace 是 git 仓库),会在<project>/.qwenpaw/worktrees/下创建隔离的 git worktree,使文件改动在手动合并前不触及主工作树(有改动才保留,无改动 自动清理);非 git 仓库时退化为原地 fork(继承上下文,无文件隔离)。.worktreeinclude文件可让.gitignore掉的配置(如.env)自动复制进 worktree。子 agent 永不可恢复——始终一次性。
- Multi-Agent Workspace——一个 QwenPaw 安装内 N 个独立 agent,各自隔离的
workspace(独立 memory/skills/history/channels)。配置拆分:全局
(
- Mission Mode(见 Agent Loop 章节)是最接近真正任务分解的机制:master agent 写出含 user stories 的 PRD(Phase 1,人工确认),随后固定的 master→worker→verifier 流水线逐 story 执行、逐 story 重试(Phase 2)。
- **ACP(Agent Client Protocol)**用于跨运行时编排(
acp-integration.en.md,agents/acp/目录 +delegate_external_agent工具,1022 行仅目录列出):- QwenPaw 作为 ACP client:
delegate_external_agent(action= start|message|respond|close, runner=...)驱动外部 ACP 兼容 agent 运行时(内建 示例:opencode、qwen_code、claude_code、codex——即 QwenPaw 可以字面意义上 shell out 到并编排 Claude Code 作为子运行时)。委派方提出的权限请求会转交人类 决定,从不自动决策。 - QwenPaw 作为 ACP server:
qwenpaw acp命令通过 stdio JSON-RPC 将 QwenPaw 自身 暴露出去(方法:initialize/new_session/load_session/resume_session/ list_sessions/close_session/prompt/set_session_model/set_config_option/ cancel),供 Zed/OpenCode 等编辑器驱动。
- QwenPaw 作为 ACP client:
- 本轮未发现独立的”规划器模型”或经典层级任务分解算法的证据——除 Mission Mode 的 “先 PRD 后执行”模式与基于 gate 的循环外,编排更接近”agent 通过工具调用 agent”, 而非专门的路由组件。
Skill / 插件体系
- Skills = 文件夹(
SKILL.md+ 可选脚本),两层结构:共享 Skill Pool ($WORKING_DIR/skill_pool/)vs 各 Workspace 的运行时副本 (workspaces/{agent_id}/skills/)。Pool 中的条目不会直接执行——必须先”广播”到某个 workspace。skill_paths配置允许外部目录(git 仓库、团队共享)不经复制直接读入同一 pool 视图(优先级:pool 优先,其次按配置顺序;名称冲突 = 先到者优先,后到者被遮蔽 并记录日志)。- Frontmatter:
name+description必填;metadata.requires.{bins, env}声明 外部二进制/环境依赖,暴露为require_bins/require_envs——仅声明不自动强制 校验(依赖缺失不会自动禁用该技能)。 - 引入来源:
skills.sh、clawhub.ai、skillsmp.com、lobehub.com/market.lobehub.com、github.com、modelscope.cn/skills。 /make-skill(Beta)——把一次完整的对话会话转成新技能,agent 根据对话记录写出 计划 + SKILL.md。- Skill Market:4 个内建 provider(QwenPaw、ClawHub、ModelScope 始终开启;Aliyun 需要阿里云 AK/SK),并行搜索,部分失败可容忍。
- 单技能运行时配置以环境变量形式注入,匹配声明的
requires.env键,加上始终可用的QWENPAW_SKILL_CONFIG_<NAME>JSON blob;宿主环境变量永不被覆盖;配置解析顺序: 宿主 env > workspace 配置 > pool 配置。 - 通过目录列出确认 20+ 内建技能(en/zh 本地化配对),多个明确移植自
github.com/anthropics/skills(docx、pdf、pptx、xlsx)与github.com/openclaw/openclaw(himalaya 邮件技能)。
- Frontmatter:
- Plugins(
src/qwenpaw/plugins/,PluginApi——仅目录列出,行为通过plugins.en.md的可运行示例核实):六种扩展类型——Provider、Middleware (register_middleware,包装 AgentScopeon_acting/on_reasoning钩子,priority= 洋葱式分层顺序)、Hook(startup/shutdown/uninstall/ workspace-created,应用生命周期级)、Command(/slash命令,经BaseControlCommandHandler)、HTTP API(在/api/<prefix>下挂载fastapi.APIRouter,一个插件一个前缀,卸载时自动卸挂)、Frontend(浏览器端 JS, 共享宿主 React/antd 运行时,经window.QwenPaw.*,可通过dispose()撤销注册)。- 通过 CLI 安装(
qwenpaw plugin install <path-or-url-or-zip>),仅限离线时; 热安装/卸载据文档也支持”应用运行期间”经 API(安全文档标记这是一个需要留意状态 一致性的风险点)。 - Manifest(
plugin.json)携带qwenpaw_version: {min, max}兼容范围(遗留min_version/max_version仍被接受)。 - 仓库内具体的示例插件:
plugins/bundle/cloudpaw(云运维多 agent 团队 + terraform/alicloud-cli 技能)、plugins/middleware-demo(tracing + 思考日志 middleware 示例,与文档 Example 8/9 逐字对应)、plugins/tool/gpt-image2(OpenAI 图片生成工具插件)。
- 通过 CLI 安装(
自进化能力(自我改进 / 学习型记忆 / eval 驱动纠错)
- 本仓库未发现权重级自我微调或训练循环式自我改进的证据(若存在,会在独立的 ReMe/AgentScope 仓库中,本轮未核实)。
- 最接近的类比,均为记忆驱动或 gate 驱动,而非模型训练驱动:
- Auto Dream(
memory-evolving-and-proactive.en.md):一个 cron 任务(默认 每晚0 23 * * *)读取近期每日记忆笔记,针对每个变化的记忆单元,在digest/{personal,procedure,wiki}/下”创建、佐证、修正或纠正”一个摘要节点—— 即记忆内容会随新证据被修订,明确包含一个”纠正”操作(与先前信念矛盾/更新)。这是 文档中唯一使用”自愈”/“自我纠正”记忆这类措辞的地方。 - Goal Mode 的自我审计 gate(
RubricGate+GoalStatusRubric/可插拔RubricStrategy)——循环不会终止,直到出现明确的验证信号(update_goal工具 调用或自定义 rubric 的SATISFIED判定);文档称之为”agent 必须证明任务完成, 而非仅仅感觉完成”。SubAgentRubric目前是个 stub(rubric.py第 121-151 行, 明确标注TODO: implement file-based state verification,当前始终返回GRADER_ERROR),引用了一种”oh-my-claudecode/ralph 模式”——生成验证子 agent 并 读取状态文件判定结果——已规划,未实现。 - Mission Mode 的 verifier agent——独立对照验收标准校验每条 user story,触发 失败 story 的自动重试——是一个 eval 驱动的纠正循环,但仅限于单次 mission 运行内, 不会作为通用学习信号被持久化。
model_capability_cache(providers/model_capability_cache.py,react_agent.py中引用,未独立全读)——在真实的 bad-request 错误发生后,为 每个模型键学习一个布尔rejects_media标记,并在后续调用中主动避免向该模型发送 媒体内容。这是 harness 基于观察到的模型失败调整自身行为的一个小而真实的例子 (基础设施层面的”eval 驱动纠错”,而非推理层面)。
- Auto Dream(
- 未在源码中发现针对 harness 自身代码的 CI/benchmark 驱动自我改进循环,除了克隆时
HEAD 恰好指向的新增提交本身:QwenPaw review bot
(
scripts/review-bot/{setup_review_workspace.py, review_runner.py, prompts.py})——即 commit085d6b2e(“feat(ci): add QwenPaw review bot (#5736)”) 给仓库自身 CI 添加了一个基于 LLM 的 PR 审查 bot。这是对代码库的 eval 驱动纠正, 而非对agent 自身运行时行为的纠正——与经典意义上的”轨迹强化”相邻但不同,仅作为 留意点标注,未详细读。
可观测性(日志 / trace 格式)
- 结构化的单次工具调用审计轨迹:SQLite
~/.qwenpaw/audit.db,单一全局单例,schemaaudit_events(ts INTEGER ms-epoch-UTC, workspace_dir, agent_id, session_id, tool_name, target, decision, reason, extra JSON)(governance/audit.py第 32-48 行,schema 部分全读)。record()同步写入(无内存缓冲);query()支持 过滤+分页;总行数达到 10 万时自动清理最旧的 1 万行。这是治理决策 (allow/deny/ask/sandbox_fallback 结果)专属的”轨迹”追踪,不是完整的 agent 推理轨迹。 - 可选 Langfuse 集成(
observability/langfuse.py,90 行全读):除非安装了langfuse包且设置了LANGFUSE_SECRET_KEY环境变量,否则是纯 no-op;激活时通过ContextVar传递LangfuseTraceContext(trace_id, parent_observation_id, name, metadata),使嵌套 span 可关联;README v1.1.12 更新日志明确声称”Langfuse agent loop grouping”是已发布功能(即一个 turn 内多轮 ReAct 迭代被归并到同一 trace 下)—— 除更新日志这一行 + 这个薄封装模块外未独立验证。 - 通过插件 middleware 的自定义 tracing 是被认可的扩展点(非核心硬编码):
plugins.en.mdExample 8 展示一个on_acting的MiddlewareBase子类写入<workspace>/.qwenpaw/trace.log,格式[HH:MM:SS] tool_name(input_prefix) — elapsed_ms,受QWENPAW_TRACE环境变量控制;与仓库内真实示例plugins/middleware-demo/tracing-middleware/tracing_plugin.py目录结构对应, 未与文档代码块逐行 diff。 - 纯文本日志文件
~/.qwenpaw/logs/qwenpaw.log在多篇文档(故障排查节)中被引用为标准 Python-logging 落点,例如security.en.md建议用户 grep 该文件寻找governance decision: tool=Bash target="..." action=sandbox_fallback sandbox=bubblewrap ...这类行以验证沙箱是否被激活——即治理层也会为每个决策发出一条 结构化的单行日志,独立于 SQLite 审计表。
安全与权限(审批门、密钥管理)
- 五层安全栈(据
security.en.md;每层代码目录已列出、关键文件行数已确认,核心策略 引擎governance/policy.py读了开头部分):- Governance Policy(
governance/policy.py)——实时工具调用拦截,builtin_rules(系统所有)+user_rules(审批流程生成,“智能泛化”:首 token+glob,高风险命令保持精确匹配)+ 正则/shell 规避检测,解析为 ALLOW/DENY/ASK/SANDBOX_FALLBACK。 - File Guard——独立于 Tool Guard(即便 Tool Guard 被禁用也照常运行,只要
file_guard.enabled);敏感路径拒绝列表(~/.qwenpaw.secret/默认受保护——存放 API 密钥/凭证),支持递归目录保护(尾部加/),路径归一化(~展开、 相对→绝对)。 - Sandbox——操作系统内核级隔离,按平台自动探测后端:macOS Seatbelt
(
sandbox-exec)、Linux Bubblewrap(优先,mount+user+PID 命名空间)或 Landlock(回退,内核 5.13+)、Windows AppContainer(+icaclsACL,安装需管理员 权限,需 build 10240+)。默认拒绝的白名单模型:仅显式writable=True的挂载点 可写;deny_paths即便原本可读也被阻断(在 Bubblewrap 上表现为不挂载因而不可见, 在 Seatbelt/Landlock/AppContainer 上表现为Permission denied)。明确记载的 当前局限:网络隔离尚未实现(沙箱化进程无论network_allow如何都拥有完整 网络),max_processes/max_memory_mb字段存在但任何后端都不强制执行, Windows AppContainer 无法 ACL 某些 TrustedInstaller 所有的系统目录(实际影响有限, 因为这些目录默认全局可读)。 - Skill Scanner——激活前静态扫描(YAML 正则签名,类别涵盖 command_injection/data_exfiltration/hardcoded_secrets/prompt_injection/ social_engineering/supply_chain_attack/obfuscation/resource_abuse/ unauthorized_tool_use);模式 Block/Warn(默认)/Off;基于 mtime 的扫描缓存; SHA-256 内容哈希白名单(技能文件内容变化即失效——“版本锁定”)。
- Access Policy(目前仅限 MCP)——声明式的按 (subject × principal/来源 × target) 三元组 allow/deny/ask,最具体规则优先解析顺序(target 名称 > target 类型 > principal 具体度 > subject 具体度 > 严格度 deny>ask>allow)。
- 另有可选的 Web Authentication(面向 Console,默认禁用;单管理员账号模型;
HMAC-SHA256 签名的 7 天 token;加盐 SHA-256 密码哈希;localhost 自动绕过;
auth.json以0o600权限写入)。
- Governance Policy(
- 单 agent 字段
approval_level:STRICT(始终询问)/ SMART(低风险自动允许)/ AUTO(默认——仅 guard 标记的调用才询问)/ OFF(该 agent 完全禁用 Tool Guard)。 - 明确记载的安全代价:Mission Mode 的 worker/verifier 子 agent”自动绕过安全
守卫”,因为后台会话无法响应交互式
/approve——文档明确表示仅在完全可信的代码库中 使用 Mission Mode。这是自动化与审批门之间一个真实的、有名字的权衡,而非隐藏缺陷。 - 密钥:
security/secret_store.py(466 行,仅目录列出未读)——provider API 密钥 + 连接器(MCP)凭证的加密存储;{WORKING_DIR}.secret/是磁盘位置,默认受 File Guard 保护。
沙箱与执行隔离
(详见上面”安全与权限”第 3 层——源码中这是统一的一个子系统,此处不重复展开)
概要:4 个真实后端(Seatbelt/Bubblewrap/Landlock/AppContainer)+ 一个 none
直通兜底,启动时按平台固定优先级顺序自动探测(Linux:bubblewrap > Landlock >
none),每次工具调用都创建全新沙箱实例、调用结束后销毁,配合 MountSpec
(path/writable/executable)声明与各后端基于 stderr 模式的违规检测。治理层决定是否
需要 sandbox_fallback;沙箱本身只在该决策做出后强制内核级边界——按设计是两个独立的层
(security.en.md:“Governance Policy = 执行前的模式检测 + 策略评估……Sandbox =
运行时内核隔离”)。
与模型的协同设计
- 模型被抽象在稳定的
ChatModelBase接口(AgentScope)之后,使 provider 可替换而 无需改动 agent 代码(architecture.en.md“Models” 节)。 - 据文档支持的云端 provider:OpenAI、Anthropic、Google Gemini、DashScope
(Qwen)、OpenRouter(+ 必要时的登录流程)。本地:Ollama、LM Studio,以及完全
端上运行的 llama.cpp(
local_models/llamacpp.py,935 行,仅目录列出)。 - 能力探测/对模型的自适应行为(代码级,读自
react_agent.py):model_capability_cache在真实 API 错误发生后为每个模型键学习rejects_media标记(_is_bad_request_or_media_error刻意将内容安全拒绝、以及尺寸/上下文长度 错误排除在”不支持媒体”的误判之外——据行内注释第 524-566 行,是为避免假阳性污染 缓存的刻意窄化启发式),随后在对该模型的后续调用中主动从 memory/formatter 剥离 媒体块。- 重试一次再剥离模式:遇到真实的媒体拒绝错误时,agent 会在剥离媒体后重试同一调用
一次(
_reasoning()中对super()._reasoning()的 try/except 包裹),而非直接 让该轮失败。
RoutingChatModel(129 行全读)——按AgentsLLMRoutingConfig.mode在预先构建 好的local_endpoint与cloud_endpoint之间路由每次模型调用。当前实现是静态 全局开关,非按请求自适应路由:RoutingPolicy.decide()接受text/channel/tools_available参数但立即丢弃它们(del text, channel, tools_available),仅当mode == "cloud_first"时返回cloud,否则始终返回local。参数接口暗示内容感知路由是计划中/意图中的功能,但在这个 commit 尚未实现。- README 声称 QwenPaw-Flash(2B/4B/9B)是”为 agent 任务训练的模型”,由内建的 “QwenPaw Local runtime” 提供服务——这个产品声明本轮未能独立核实(需要在 HF/ModelScope 上找到 QwenPaw-Flash 的 model card/训练报告/论文,超出仅克隆本仓库的 调研范围)。标注为未验证而非已确认。
- 本仓库未发现针对该 harness 的 RLHF/微调管线(若存在,会在模型自身的训练仓库中, 不在此处)。
轨迹利用(session/trajectory 是否反哺训练/评测)
- 本仓库未发现会话轨迹被导出用于模型训练或微调的证据。现存的持久化存储
(Scroll 上下文的
history.db,ReMe 记忆的mem_session/dialog/*.jsonl)在架构上 被定位为同一 agent 的运行时记忆基底,而非训练数据管线产物——未找到把轨迹指向 外部训练或评测系统的导出/上传代码。mem_session/dialog/<session_id>.jsonl被文档明确描述为在作为 ReMe 抽取源之前 先经过”净化”(剥离工具结果块与 base64 数据块)——即它是专门为记忆抽取清洗的, 而非作为原始 RL/SFT 轨迹数据保留。- Scroll 的
history.db被定位为纯粹的recall_history_python工具召回基底—— 未发现或记载任何导出路径。
- 最接近”轨迹被复用于评测”的机制是 Mission Mode 的 verifier agent 对每个 worker 产出按验收标准打分(见自进化章节)——但这是运行内评测,mission 完成后即丢弃(未发现 将 verifier 判定持久化用于后续分析/训练的证据)。
- 审计日志(
audit.db)无限期持久化治理决策(allow/deny/ask,直到 10 万行滚动清理 触发)——更接近合规/调试轨迹,而非 ML 轨迹数据集;它记录的是决策元数据,不是完整的 推理轨迹或 reward。 - 结论:在这个 commit,轨迹反哺训练/评测不是 QwenPaw 的内建能力。 若这类能力存在 于更广泛的 AgentScope/ReMe 生态中,会在那些独立仓库里,本轮未克隆核实。
与同类 harness 的关键差异(1-3 条,可以先留一句概述,后续 synthesis 阶段会做跨 harness 对比)
- QwenPaw 是本系列中少见的”应用层而非内核层”harness:ReAct 循环本身、权限引擎、 上下文压缩的基础实现都来自独立的 AgentScope 2.0 依赖,QwenPaw 自己只贡献 Gate 停机 系统、Scroll 记忆策略、治理/沙箱信任栈与多模式(Goal/Mission)编排——这种”host framework + OS layer”分层在同类 harness 中较为独特,值得跨 harness 对比时重点标注。
- Scroll 策略的”写穿持久化 + 驱逐折叠为可召回索引”设计,与常见的”摘要后丢弃原文”压缩 策略形成明确对比——具体差异留待 synthesis 阶段与其他 harness 的压缩机制并列分析。
- Mission Mode 显式记载的”后台子 agent 绕过审批门”是一个罕见的、被文档而非代码审查 发现的、公开承认的安全权衡,可作为跨 harness 安全设计对比的一个案例。
原始源码定位
- repo: https://github.com/agentscope-ai/QwenPaw
- commit/version analyzed:
085d6b2eaa3030e0e53d68514c23c9ea77480ecb(“feat(ci): add QwenPaw review bot (#5736)“,2026-07-06 18:18:47 +0800) - 关键文件列表(相对路径):
src/qwenpaw/agents/react_agent.pysrc/qwenpaw/loop/gates/{__init__,base,runner,doom_loop,rubric,budget,iteration,handler_registry,handler,loop_gate,file_loop_gate}.pysrc/qwenpaw/modes/goal/{gates,goal_mode,tools,helpers,prompts,contributor}.pysrc/qwenpaw/modes/mission/{gates,handler,state,prompts,contributor,hooks}.pysrc/qwenpaw/modes/coding/{mixin,hooks}.pysrc/qwenpaw/agents/context/scroll/{manager,eviction_index,history,serialize,memoryspace,sync,_as_internals,repl,cap_middleware,prompt}.pysrc/qwenpaw/agents/memory/{reme_light_memory_manager,reme_config,adbpg_memory_manager}.pysrc/qwenpaw/agents/tools/__init__.py(+shell.py、browser_control.py、agent_management.py、delegate_external_agent.py等)src/qwenpaw/agents/{prompt,prompt_builder,templates}.pysrc/qwenpaw/agents/md_files/{en,zh,ru,id}/{AGENTS,SOUL,BOOTSTRAP,HEARTBEAT,MEMORY,PROFILE}.mdsrc/qwenpaw/governance/{policy,audit,tool_registry,resource_governor,generalize,tool_adapter,detectors}.pysrc/qwenpaw/security/tool_guard/{engine,models,approval,execution_level,i18n,utils}.pyguardians/{rule_guardian,shell_evasion_guardian,file_guardian}.py
src/qwenpaw/security/skill_scanner/{scanner,scan_policy,models}.py+analyzers/pattern_analyzer.pysrc/qwenpaw/security/secret_store.pysrc/qwenpaw/sandbox/{config,linux_sandbox,windows_sandbox,macos_sandbox,bubblewrap_sandbox,local_sandbox}.pysrc/qwenpaw/agents/tools/agent_management.py、src/qwenpaw/agents/tools/delegate_external_agent.py、src/qwenpaw/agents/acp/src/qwenpaw/plugins/{architecture,registry,api}.pysrc/qwenpaw/agents/skill_system/、src/qwenpaw/agents/skills/plugins/bundle/cloudpaw/、plugins/middleware-demo/、plugins/tool/gpt-image2/src/qwenpaw/cli/main.pysrc/qwenpaw/agents/model_factory.py、src/qwenpaw/agents/routing_chat_model.pysrc/qwenpaw/local_models/{llamacpp,model_manager,download_manager,tag_parser,manager}.pysrc/qwenpaw/observability/langfuse.pyscripts/review-bot/{setup_review_workspace,review_runner,prompts}.py
一手源存档(sources/)
/Users/zhao/projects/self-wiki/ai-research/sources/harness/qwenpaw/ 下保存:
NOTES.md(830 行)——完整调研笔记,本页所有论断的原始出处(含精确文件路径/行号)docs/——从仓库website/public/docs/*.en.md拷出的 10 份官方一手设计文档:acp-integration.en.md、architecture.en.md、context.en.md、loop-engineering.en.md、memory-evolving-and-proactive.en.md、memory.en.md、multi-agent.en.md、plugins.en.md、security.en.md、skills.en.mdcode_excerpts/——从仓库摘录的关键源码片段:agent_tools_registry_init.py、react_agent.py、routing_chat_model.py, 以及context_scroll/、governance/、loop_gates/、modes_goal/、prompt/子目录(分别对应 Scroll 管理器、治理策略、Gate 系统、Goal Mode、Prompt Builder 的 代码摘录)
(注:仓库本体已按调研流程克隆读取后删除,未保留完整 clone;上述存档是本轮调研的 可复核证据。)