QwenPaw Architecture and Design Analysis Report
A detailed source-level architecture analysis of QwenPaw (formerly CoPaw, renamed at v1.0.0 after integrating into the Qwen open-source ecosystem) — a personal AI assistant platform under Apache-2.0, requiring Python 3.10+. Core positioning: local-first, multi-channel reach, skill-driven, multi-agent collaboration.
Tech stack: AgentScope (multi-agent framework), FastAPI (HTTP), Vue 3 (Console), Tauri (desktop shell), Playwright (browser automation), MCP (Model Context Protocol).
Key points
Six-layer architecture (outside-in)
1. Channels Layer — 18 built-in channels registered in app/channels/registry.py: IM (iMessage, Discord, DingTalk, Feishu, QQ, Telegram, Mattermost, MQTT, Matrix, WeCom, WeChat, OneBot), terminals (console, voice, SIP), and ecosystem (xiaoyi, yuanbao). Each channel is an independent subdirectory; BaseChannel(ABC) defines the contract (native payload adaptation, batch merging, MessageRenderer/RenderStyle, per-channel access control). ChannelManager._process_batch splits native vs. generic payloads with a per-channel queue cap of 1000.
2. Console Layer — Web UI / Tauri desktop.
3. Agent Layer — class QwenPawAgent(CodingModeMixin, ToolGuardMixin, ReActAgent); every _acting override must call super()._acting(...) to preserve the MRO chain (plan gate + security interception stack).
4. Security Layer — ToolGuard (STRICT / SMART / AUTO / OFF execution levels) + SkillScanner.
5. Provider Layer — Provider(ProviderInfo, ABC) abstract base; 8 implementations (OpenAI file contains 3 classes: OpenAI, OpenCode, Kilo; plus Anthropic, Gemini, Ollama, LM Studio, OpenRouter). Deep-merges provider-level and model-level generate_kwargs.
6. Memory/Context Layer — 3 memory backends (AgentMdManager file-based, ReMeLightMemoryManager, ADBPGMemoryManager); LightContextManager handles tool-result pruning, context-size checking, and compaction with distinct EN/ZH prompts. Automation-triggered sources (cron, heartbeat) skip long-term memory writes.
Agent layer details
- Tool registration (three-plus mechanisms): 21 hardcoded built-in tools (shell, file ops, grep/glob, browser, screenshots, media viewing, multi-agent tools like
spawn_subagent/chat_with_agent,run_tool_batch); plugin tools auto-discovered via__all__but disabled by default unless enabled in config; auto-registered background-task tools (view_task/wait_task/cancel_task) when any enabled tool is async; Coding Mode tools (lsp,ast_search) gated on CLI/language-server availability. - Hook lifecycle: BootstrapHook (pre_reasoning) plus 4 ContextManager hooks; pre_reply performs tool-result pruning.
- Media fault tolerance (3 tiers): proactive stripping when the active model doesn't support multimodal; passive retry on 400/media-error keywords, degrading to memory-block stripping; learning via
get_capability_cache().learn(model_key, "rejects_media", True). Nested media blocks insideToolResultBlock.outputare also stripped. - Plan gating: 4 flags in
plan_notebook(_plan_tool_gate,_plan_awaiting_user_confirm,_plan_text_only_after_mutation,_plan_just_mutated);_filter_plan_tools()pre-locks before execution to preventasyncio.gatherconcurrency races. - Auto-continue: up to 2 extra reasoning rounds with a bilingual
<system-hint>when the model replies text-only; the previous assistant tail (600 chars) is wrapped in<previous-assistant-tail>for self-review. - MCP recovery: reconnect → rebuild (using
client._qwenpaw_rebuild_infometadata) → reconnect, else return None. - Multi-agent routing priority: explicit
agent_id→request.state.agent_id→X-Agent-Idheader →agents.active_agentconfig fallback (default"default"); lazy workspace loading releases locks during startup withasyncio.Eventcoordination. ToolExecutionLevel: STRICT (all tools need approval), SMART (INFO/LOW auto-pass, MEDIUM+ need approval — recommended), AUTO (only explicitly guarded tools), OFF.- Three guardians:
RuleBasedToolGuardian(env-var rule priority stack),FilePathToolGuardian(path allow/deny lists with default secret-dir deny list),ShellEvasionGuardian(shell obfuscation detection). - Guard UI i18n: en / zh / ru / ja. Default-on priority: env
QWENPAW_TOOL_GUARD_ENABLED>config.json> True. - Hardcoded-secret and exfiltration detection live in
security/skill_scanner/(pre-installation skill scanning), separated from ToolGuard. PluginTypeenum: TOOL, PROVIDER, HOOK, COMMAND, FRONTEND, GENERAL.- Skill system (7 modules): pool/workspace services, remote hub,
resolve_effective_skills(workspace_dir, channel_name), per-channel env overrides, builtin skill localization variants (<name>-en/<name>-zh). - Deployment: pip, script installer (auto-manages Python + Node), Docker, Alibaba Cloud ECS, ModelScope Create Space, and a beta Tauri desktop app.
Security layer
Plugins, skills, deployment
Startup and resilience
Two-phase lifespan: Phase 1 (target < 100 ms) — cleanup, env registration, migrations, core manager instantiation (MultiAgentManager/ProviderManager/LocalModelManager), then "Server ready" log; Phase 2 (background) — plugin loading, agent startup, local-model resume, provider registration, control commands, startup hooks.
Design philosophy
1. Local-first — secrets in ~/.qwenpaw.secret/, data in ~/.qwenpaw/, never auto-uploaded.
2. Skill-driven — effective skills resolved per workspace + channel.
3. Secure by default — guarding on by default; plugin tools unregistered without config; skills scanned before install.
4. Progressive complexity — three-command setup up to multi-agent collaboration.
5. Resilience — LLM retry with exponential backoff, three-stage MCP recovery, three-tier media tolerance, plan-gate pre-locking.
Assessment
Strengths: clear six-layer separation, rich extension mechanisms (Skills + Plugins + MCP + custom providers, no lock-in), layered security, and end-to-end resilience. Potential improvements: inter-agent communication relies on tool calls with no native message bus; the plan system is fairly coupled to the agent core; test coverage targets are modest (fail_under = 30).