跳到主要内容

QwenPaw — 架构与原理

30 秒导读: QwenPaw 是一个能装在自己电脑或自己服务器上的个人 AI 助理。你从微信、飞书、钉钉、Telegram、命令行等任意渠道给它发消息,它用一个 ReAct(边想边用工具)的 agent 处理,能读写文件、跑 shell、开浏览器、调外部服务。它的能力不是写死的:一个「带 SKILL.md 的文件夹」就是一项技能,丢进去就多一种本事。数据、记忆、模型密钥全在你自己手里。


1. 这是什么(零基础也能懂)

一句话定义: QwenPaw = 「你私有的、可自托管的、能力可插拔的 AI 助理运行时」。它把 AgentScope 的 ReActAgent 包成一个带多渠道接入、技能系统、请求编排、多层安全、长期记忆的完整应用。

解决什么问题 / 给谁用:

想象你想要一个「7×24 待命的私人助理」,但又不放心把聊天记录和文件传给某个云服务。QwenPaw 让你:

  • 把它部署在自己机器(数据不出本地)或自己的服务器上;
  • 你已经在用的聊天软件里直接使唤它,不必开新 App;
  • 给它加新技能只需放一个文件夹,不用改它的源码;
  • 让它跑真实操作(改文件、发文件、开网页、连数据库)且有安全闸门兜底。

它能做什么(功能):

能力说明
多渠道接入命令行 / 钉钉 / 飞书 / 微信 / 企业微信 / Discord / Telegram / Slack / QQ / Matrix / iMessage / 语音电话 等(app/channels/)
技能即能力每个技能是一个带 SKILL.md 的文件夹;内置 PDF/Office/建技能等,自定义技能自动加载
真实工具shell、文件读写、文件搜索、浏览器控制、桌面截图、LSP、AST、发送文件等(agents/tools/)
外部服务 / MCP通过统一的 Driver 层接入 MCP 服务器与凭证(drivers/)
多 agent 协作建多个独立 agent,各有角色,可互相委派任务
长期记忆 + 主动性从对话里抽记忆、反思、并能主动服务(agents/memory/)
多层安全工具守卫、策略治理、技能扫描、系统级沙箱、审计日志
定时任务Cron 触发的自动执行(app/crons/)

用起来什么样: 最小场景就是命令行里聊天。启动后台服务,然后在控制台渠道发一句「把桌面上的 PDF 都总结一下」——agent 会加载 PDF 技能、用文件搜索找到文件、跑脚本、把结果发回来。所有渠道最终都汇入同一个 agent 运行时。

一句话直觉/类比: 把 QwenPaw 想成一台私人电器的主板:主板(运行时)是固定的,但插槽(技能 / 渠道 / 外部服务 / 模型)全是可插拔的模块。你换插槽,它就变一台不同的机器,而主板本身不用动。

本节不涉及底层代码;下面开始进主板内部。


2. 顶层全景(它大概怎么转)

2.1 主线:一条消息从渠道到回复

怎么读这张图: 从左到右是一条用户消息的旅程;竖线右边是「每个 agent 独占一个 Workspace」。

你(任意渠道)
│ 消息

┌──────────────┐ 同 (渠道,会话,优先级) 严格串行,
│ Channel │ 不同键并发;消费者按需创建、闲置回收
│ (接入层) │────────────────┐
└──────────────┘ │
│ 归一化为 AgentRequest ▼
│ ┌──────────────────┐
│ │ UnifiedQueue │ per-(channel,session,priority)
│ │ Manager │ 队列 + 按需消费者
│ └──────────────────┘

┌───────────────────────────────────────────────┐
│ Workspace(每个 agent 一个,含插件/服务注册表) │
│ │
│ Runtime.run(request) ← 8 阶段编排 │
│ ┌─────────────────────────────────────────┐ │
│ │ 归一化 → [钩子]① 派发前 → 斜杠命令派发 │ │
│ │ → [钩子]② 派发后 → [钩子]③ 建 agent 前│ │
│ │ → 〔定步〕AgentBuilder.build │ │
│ │ → [钩子]④ 建 agent 后 → [钩子]⑤ 执行前 │ │
│ │ → 〔定步〕AgentExecutor.run(ReAct 循环)│ │
│ │ → [钩子]⑥ 响应后 → ⑦ 出错 → ⑧ 收尾 │ │
│ └─────────────────────────────────────────┘ │
│ │ build 时装配 │
│ ▼ │
│ QwenPawAgent(ReActAgent 之上) │
│ · Model+Formatter(provider 工厂) │
│ · Toolkit = 工具 + 技能→工具 + Driver/MCP 工具 │
│ · 每个工具裹 PolicyGuardedTool(治理+沙箱) │
│ · Memory manager / Context(scroll) │
└───────────────────────────────────────────────┘
│ SSE 事件流(Envelope)

回复(流式发回原渠道)

主线走一遍(高层,不进代码):

  1. 任意渠道收到消息,归一化成统一的 AgentRequest,投进统一队列;
  2. 队列按 (渠道, 会话, 优先级) 三元组把消息路由给按需创建的消费者;
  3. 消费者路由到该 agent 的 Workspace,调 Runtime.run();
  4. Runtime固定的 8 个阶段编排:阶段之间夹着两个「碰 agent 的定步」——建 agent执行 agent;
  5. 建 agent 时,AgentBuilder 现场装配模型、工具、技能、记忆、安全闸门,产出一个 QwenPawAgent;
  6. 执行就是跑 ReAct 循环(想→调工具→观察→再想),工具调用前后都过安全层;
  7. 输出以 SSE 事件流(Envelope)流式发回原渠道。

2.2 部件一句话职责

部件干什么在哪
Channels各聊天平台的收发适配,归一化消息app/channels/*/channel.py
UnifiedQueueManagerper-(渠道,会话,优先级)队列 + 按需消费者 + 闲置回收app/channels/unified_queue_manager.py
Workspace每个 agent 一个,持有插件/服务/驱动/记忆注册表app/workspace/workspace.py
Runtime8 阶段请求编排,只有 build/execute 两步碰 agentruntime/runtime.py:Runtime.run
LifecycleHook插在阶段之间的可插拔特性(会话、bootstrap、cron、技能环境、可观测)hooks/
AgentBuilder每请求现场组装一个 QwenPawAgentruntime/builder.py:AgentBuilder.build
QwenPawAgent建在 AgentScope Agent(ReAct)之上的主 agentagents/react_agent.py:QwenPawAgent
Skill system技能发现/校准/解析/env 注入agents/skill_system/registry.py
Driver/MCP外部能力(含 MCP)统一为 Driver capabilitydrivers/manager.py:DriverManager
安全层工具守卫 + 策略治理 + 技能扫描 + 沙箱security/governance/sandbox/
Memory记忆抽取/检索/主动响应/dreamagents/memory/

3. 阅读地图(建议顺序)

想真正读懂,按下面顺序看各章(从「怎么转」到「怎么实现」,由浅入深):

  1. 这是什么 · 全景图 · 阅读地图 — 就是本页,先建立大盘。
  2. 一次请求的一生:8 阶段运行时编排 — 主干骨架:Runtime.run 的 8 个阶段、两个定步、钩子如何短路/跳过 agent、SSE EnvelopeFINALLY 的收尾顺序。先读这章,它是理解其它一切的地基。
  3. Agent 与模型:ReActAgent 之上的组装、prompt、providerAgentBuilder 怎么装配一个 agent、系统 prompt 怎么拼、模型工厂与多 provider、上下文管理(scroll)、媒体能力学习与自动续答。
  4. 技能即能力:Skill 系统与 skill→tool — 技能=带 SKILL.md 的文件夹;内置/池/工作区三级、磁盘为准的校准、技能配置注入环境变量、/make-skill 自造技能。
  5. 接入层:多渠道 drivers、统一队列、MCP — 渠道适配、统一队列的并发/串行模型、Driver 生命周期与凭证、MCP 如何统一为 Driver capability。
  6. 多层安全:工具守卫、技能扫描、沙箱、审计 — 工具守卫引擎与守卫者、PolicyGuardedTool + ResourceGovernor、技能安全扫描、跨平台系统沙箱、审计。
  7. 记忆、主动性与多 agent 工作区 — 记忆后端与中间件、主动记忆/dream、每 agent 一个 Workspace 的多 agent 模型与委派。

只读一章的话,读第 2 章(请求生命周期):它是这个项目「巧妙工程」最集中的地方。


4. 巧妙之处(值得带走的设计)

4.1 「固定阶段 + 阶段间钩子」把编排和特性彻底解耦

Runtime.run 是一根写死的骨架:8 个 Phase 阶段点,阶段之间只夹着三个固定步——斜杠命令派发、AgentBuilder.buildAgentExecutor.run(runtime/phases.pyruntime/runtime.py:49-169)。

关键点:只有 build 和 execute 两步真正碰 agent;其它一切特性(会话加载、bootstrap 引导、cron 回写、技能环境注入、可观测)都做成 LifecycleHook 插在阶段点上,注册在每个 workspace 的 HookRegistry 里。钩子可以「短路」直接返回、或「跳过 agent」,由 HookAction 表达(runtime/runtime.py:63-127)。

这带来一个干净的扩展面:加新特性不改编排主干,只加一个钩子

4.2 收尾顺序被刻意设计,让审计不丢

FINALLY 阶段先关 agent、再跑收尾钩子:因为关 agent 时 ResourceGovernor 要 flush 审计日志、落盘策略,必须赶在下游 FINALLY 钩子观察上下文之前完成(runtime/runtime.py:155-169,注释明确点出这个依赖)。这是把「正确的关闭顺序」写进代码而非靠运气。

4.3 技能:磁盘是唯一事实源,丢个文件夹就多个能力

技能系统不把 manifest 当内容的事实源,而是扫磁盘重建 manifest:reconcile_pool_manifest / reconcile_workspace_manifest 扫描目录、发现带 SKILL.md 的文件夹就登记,目录没了就从 manifest 删除(agents/skill_system/registry.py:954:1022)。所以「手动拖一个 skill_pool/demo/SKILL.md 进去,下次校准就自动收录」。

技能配置进 env 也很讲究:apply_skill_config_env_overrides 只在一次 agent turn 内注入环境变量,用引用计数_acquire_skill_env_key/_release_skill_env_key 保证并发 turn 之间不互相踩、退出时干净还原(registry.py:308-391)。

4.4 双层工具安全:绕过框架自带权限,换成自己的策略闸门

QwenPawAgent 主动关掉 AgentScope 自带的权限引擎(PermissionMode.BYPASS),因为它要用自己的 PolicyGuardedTool.check_permissions 统一把关(agents/react_agent.py:126-129)。每个工具在装配时被 PolicyGuardedTool 包一层,内部接 ResourceGovernor(治理策略 + 沙箱 + 审计)。工具调用前还有独立的 ToolGuardEngine,跑三个守卫者:文件路径、规则、shell 规避(security/tool_guard/engine.py:85-110)。两层各司其职、纵深防御。

4.5 「驱逐与召回同生共死」的降级保护

上下文的 scroll 策略会把旧对话驱逐进索引,靠一个沙箱化的召回工具读回。AgentBuilder 发现召回工具跑不起来(治理层没上、又没显式允许非沙箱召回)时,主动降级回原生上下文管理——否则会把历史驱逐进一个「谁也读不回来」的索引里(runtime/builder.py:204-213_scroll_recall_runnable:601-625)。这是把一个隐蔽的数据丢失路径提前堵死。

4.6 模型媒体能力「学一次记住」,又小心不误伤

跑推理时,若模型不支持多模态,agent 会先剥离媒体块;若模型报错像是媒体相关,则学习并缓存 rejects_media、剥离后重试(agents/react_agent.py:401-467)。但它用 _is_bad_request_or_media_error 精细否决:请求过大、上下文超长、内容安全拒绝都不算媒体问题,避免污染能力缓存导致后续默默丢图(react_agent.py:549-592)。

4.7 MCP 只走 Driver 一条路,不给「重复暴露」留缝

MCP 服务器只通过 Driver capability 暴露,代码注释直说「一个 server 不能通过两条运行时路径被暴露两次」(runtime/builder.py:515-536)。Driver 的热重载是先建后换:新 handler 初始化失败就保留旧的,不会把服务弄挂(drivers/manager.py:reload_driver:153-174)。

4.8 队列:同会话串行、跨会话并发、消费者按需生灭

UnifiedQueueManager(channel_id, session_id, priority_level) 三元组做键:同键严格串行(一个会话不会自己打架),不同键并发;消费者首条消息到达才创建、闲置超时自动回收,没有固定 worker 池(app/channels/unified_queue_manager.py:60-117_cleanup_idle_queues:376)。

4.9 沙箱按平台真探测,而非拍脑袋

系统沙箱有 5 种模式(macOS Seatbelt / Linux Bubblewrap / Linux Landlock / WSL2 / 无),启动时真的探测:Landlock 会检查内核版本、LSM 列表、甚至发一次 landlock_create_ruleset 系统调用拿 ABI 版本(sandbox/config.py:probe_sandbox_support:410_probe_linux_landlock:158)。Linux 优先级 bubblewrap > Landlock > 无;沙箱是允许列表模型(未列出=拒绝)。


5. 代码地图(导航索引)

按符号名(比行号抗漂移)跳进源码。所有路径相对克隆根 aiRef/repos/qwenpaw/

主题文件关键符号
8 阶段枚举src/qwenpaw/runtime/phases.pyPhase(8 个成员)
请求编排主干src/qwenpaw/runtime/runtime.pyRuntime.runRuntime._build_context
钩子动作src/qwenpaw/runtime/hooks.pyHookActionHookContextHookRegistry
SSE 事件流src/qwenpaw/runtime/envelope.pyEnvelope
执行器(ReAct)src/qwenpaw/runtime/executor.pyAgentExecutor
每请求装配 agentsrc/qwenpaw/runtime/builder.pyAgentBuilder.buildbuild_toolkitbuild_model_scroll_recall_runnable
主 agentsrc/qwenpaw/agents/react_agent.pyQwenPawAgent_reasoning_is_bad_request_or_media_errorload_state_dict
模型工厂src/qwenpaw/agents/model_factory.pycreate_model_and_formatter
Provider 管理src/qwenpaw/providers/provider_manager.pyProviderManager
技能注册/校准/解析src/qwenpaw/agents/skill_system/registry.pyresolve_effective_skillsreconcile_workspace_manifestreconcile_pool_manifestimport_builtin_skillsapply_skill_config_env_overrides
技能环境钩子src/qwenpaw/hooks/skill_env/skill_env_hook.pySkillEnvHook(PRE_EXECUTE)、SkillEnvCleanupHook(FINALLY)
自造技能工具src/qwenpaw/agents/tools/make_skill_tools.pymaterialize_skill
统一队列src/qwenpaw/app/channels/unified_queue_manager.pyUnifiedQueueManagerQueueKey_cleanup_idle_queues
Workspace + 入口src/qwenpaw/app/workspace/workspace.pyWorkspace.stream_query(→ Runtime)
多 agent 管理src/qwenpaw/app/multi_agent_manager.pyMultiAgentManager.get_agentreload_agent
Driver / MCPsrc/qwenpaw/drivers/manager.pyDriverManagerinvoke_capabilityreload_driver
Driver→agent 工具src/qwenpaw/drivers/adapters/agentscope_tool.pybuild_driver_agent_tools
工具守卫引擎src/qwenpaw/security/tool_guard/engine.pyToolGuardEngine.guardget_guard_engine
守卫者src/qwenpaw/security/tool_guard/guardians/FilePathToolGuardianRuleBasedToolGuardianShellEvasionGuardian
策略治理工具包装src/qwenpaw/governance/tool_adapter.pyPolicyGuardedTool
资源治理器src/qwenpaw/governance/resource_governor.pyResourceGovernor
技能安全扫描src/qwenpaw/security/skill_scanner/scanner.pySkillScanner.scan_skill
系统沙箱src/qwenpaw/sandbox/config.pySandboxModeSandboxConfigcreate_sandboxprobe_sandbox_support
记忆基类/注册src/qwenpaw/agents/memory/base_memory_manager.pyBaseMemoryManagerget_memory_manager_backend
主动记忆src/qwenpaw/agents/memory/proactive/proactive_triggerproactive_responder

同步提示(给维护者): frontmatter 的 sourceCommit 锁定写作时的 commit。若上游未改动本页引用的这些文件,结论仍成立,只需重盖 sourceCommit;若只是行号漂移、符号还在,按符号重锚定即可;只有引用代码语义变了才需重生成本页及各章。