侧边栏壁纸
  • 累计撰写 56 篇文章
  • 累计创建 5 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

QwenPaw_面试100题

温馨提示:
部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

🔥 QwenPaw 源码面试 100 题(含答案)

基于 QwenPaw v1.1.9 源码深度解析
出题人:小微


目录

  1. 架构与整体设计(Q1-Q10)
  2. Agent 系统与 ReAct 循环(Q11-Q25)
  3. 记忆系统(Q26-Q35)
  4. 技能系统(Q36-Q45)
  5. 工具系统(Q46-Q50)
  6. 频道系统(Q51-Q58)
  7. Cron 与 Heartbeat(Q59-Q66)
  8. 多 Agent 与 ACP(Q67-Q74)
  9. 安全体系(Q75-Q81)
  10. App 与 Console(Q82-Q88)
  11. 配置系统(Q89-Q93)
  12. CLI 与命令(Q94-Q97)
  13. 开放题(Q98-Q100)

1. 架构与整体设计

Q1. QwenPaw 的入口文件是哪个?描述从 python -m qwenpaw 到启动服务的完整链路。

答案:

入口是 __main__.py,它会调用 cli/main.py 中的 cli()cli() 是一个 Click 命令组,支持 appinitchatcron 等子命令。启动服务的命令是 qwenpaw app,它通过 _app.py 创建 FastAPI 实例,在 lifespan 中初始化 MultiAgentManager 并启动监听端口。

__main__.py → cli/main.py cli() → app_cmd → _app.py (FastAPI lifespan)
    → MultiAgentManager → 各 Workspace 延时启动

Q2. constant.py 中的 _get_env 函数相比直接用 os.environ.get 多了什么能力?

答案:

提供 COPAW_ 前缀向后兼容。当查询的 key 以 QWENPAW_ 开头且找不到时,自动尝试同名的 COPAW_ 变体(如 QWENPAW_WORKING_DIRCOPAW_WORKING_DIR)。这是为了从旧版本 CoPaw 平滑迁移。

Q3. QwenPaw 的工作目录结构是怎样的?config.jsonagent.json 有何区别?

答案:

默认工作目录是 ~/.qwenpaw

  • config.json:全局配置(模型提供商、Agent 列表、全局设置)
  • workspaces/{id}/agent.json:各 Agent 独立配置(频道、工具、心跳、安全)
~/.qwenpaw/
├── config.json           ← 全局
├── workspaces/default/
│   ├── agent.json        ← Agent 独立配置
│   ├── AGENTS.md / SOUL.md / PROFILE.md / MEMORY.md
│   ├── skills/  &  skill.json
│   └── memory/
└── skill_pool/

配置优先级:agent.json > config.json

Q4. WORKING_DIR 的解析优先级顺序是什么?

答案:

  1. 环境变量 QWENPAW_WORKING_DIR(或遗留 COPAW_WORKING_DIR
  2. 目录 ~/.copaw 存在 → 兼容老版本
  3. 默认 → ~/.qwenpaw

Q5. QwenPaw 如何实现配置热加载?

答案:

通过 agent_config_watcher.py 启动后台异步任务,每 2 秒检测 agent.json 的修改时间。变化后自动重新加载并应用到运行时,无需重启服务。

Q6. 描述 QwenPawAgent 的 MRO 及其意义。

答案:

QwenPawAgent → CodingModeMixin → ToolGuardMixin → ReActAgent

每个 mixin 重写 _acting 并调用 super()。_acting(...) 保持链条完整。CodingModeMixin 负责内联 diff 编辑,ToolGuardMixin 负责工具鉴权拦截。

Q7. DynamicMultiAgentRunner 是做什么的?为什么需要它?

答案:

它是一个动态路由器,代理 AgentScope 的 AgentApp。AgentScope 原生只支持单工作区,而 QwenPaw 通过 DynamicMultiAgentRunner 检查 HTTP 头 X-Agent-Id,将请求动态路由到正确的 Workspace Runner,实现单服务多 Agent。

Q8. QwenPaw 如何确保跨平台 MIME 类型正确?

答案:

_app.pymimetypes.init() 后显式 add_type 注册 .js.mjs.css.wasm.svg 等类型,避免 Windows 因缺少映射导致前端资源加载失败。

Q9. RULE.md 文件在 QwenPaw 中的用途是什么?

答案:

RULE.md 是可选的人设文件,存储硬性不可违背规则。如果存在,它会被加载到系统提示词中,优先级高于 AGENTS.mdSOUL.md

Q10. PromptBuilder 类在处理人设文件时做了哪些处理?

答案:

  1. 读取文件内容(多编码回退)
  2. 去除 YAML frontmatter(---...---
  3. 去除心跳标记块(<!-- heartbeat:start-->...<!-- heartbeat:end-->
  4. 去除记忆标记块(<!-- memory:start-->...<!-- memory:end-->
  5. 拼接为系统提示词
  6. 可选追加记忆管理器的记忆提示

2. Agent 系统与 ReAct 循环

Q11. QwenPawAgent 的 reply 方法执行流程是怎样的?

答案:

  1. 检查是否为系统命令(/compact/new 等),是则直接处理
  2. 调用 reply_memory 从历史加载上下文
  3. 执行 ReAct 循环(_acting):模型推理 → 生成工具调用 → 执行工具 → 获得结果
  4. 达到 max_iters 或模型返回最终回答后结束
  5. 调用记忆管理器总结并存储
  6. 返回最终回复

Q12. max_iters 的作用和默认值是什么?

答案:

控制 ReAct 循环的最大轮数。每轮 Agent 可以调用工具或生成回复。默认 50running.max_iters)。超限时强制结束,返回已有内容。

Q13. CommandHandler 支持哪些系统命令?/plan 有什么特殊之处?

答案:

支持:compact, new, clear, history, compact_str, summarize_status, message, dump_history, load_history, proactive, plan

/plan 的特殊性: /plan(无参数)是系统命令;/plan 开发天气应用(带参数)会传给 Runner 启用 Plan Mode,不走系统命令流程。

Q14. 描述 Agent 对话结束时的记忆总结流程。

答案:

如果 summarize_when_compact 启用,Agent 完成 reply 后:

  1. 调用 memory_manager.summarize() 提取关键信息
  2. 生成摘要并写入 MEMORY.md
  3. 下次对话时摘要被加载到系统提示词

Q15. CodingModeMixin 实现了什么功能?

答案:

实现内联差异编辑(Inline Diff)。Agent 在编写代码时,对于短文件可以直接在回复中展示 diff,减少 write_file/edit_file 工具调用次数。

Q16. reply_memory 与普通 reply 的区别是什么?

答案:

reply_memory 负责组装对话历史和记忆:将用户消息加入上下文,调用上下文管理器和记忆管理器封装完整消息列表。普通 reply 完成整个处理流程(思考→工具→回复)。

Q17. ToolGuardMixin 在工具调用链中扮演什么角色?

答案:

在工具执行前拦截,检查安全性:

  1. 根据 approval_level(STRICT/SMART/AUTO/OFF)决定策略
  2. 对 shell 命令检测注入攻击模式
  3. 可阻止执行、请求审批或自动放行

Q18. Agent 如何处理多模态消息(图片、视频)?

答案:

  1. 通过 get_capability_cache 检查模型是否支持多模态
  2. 支持 → 将媒体内容传给 LLM
  3. 不支持 → 用占位符 [Media content removed - model does not support this media type] 替换

Q19. HEARTBEAT.md<!-- heartbeat:start--> 标记的作用是什么?

答案:

PromptBuilder 用正则匹配此标记块。心跳启用时保留;禁用时删除,避免 Agent 误认为自己有定时任务能力。

Q20. auto_continue_on_text_only 解决了什么问题?

答案:

当模型只返回文本而未调用工具时,Agent 自动重试最多两轮,迫使模型重新思考并正确调用需要的工具。

Q21. chat_with_agentsubmit_to_agent 的区别是什么?

答案:

  • chat_with_agent(前台):同步等待目标 Agent 完成并返回结果
  • submit_to_agent(后台):异步提交,立即返回 task_id,通过 check_agent_task 查询状态

Q22. Agent 中工具注册的机制和 NamesakeStrategy 是什么?

答案:

工具注册在 QwenPawAgent.__init__ 中完成:

  1. 导入内置工具函数
  2. 动态加载已启用的技能工具
  3. 调用 register_tool() 注册
  4. 同名冲突策略(NamesakeStrategy):override / skip / raise(默认)/ rename

Q23. ASMsgHandler 的作用是什么?

答案:

消息处理器,负责:

  1. AgentScope Runtime 消息格式 ↔ 内部消息格式的转换
  2. SSE 流式推送
  3. 工具调用中间结果展示
  4. 审批流程交互

Q24. /compact 命令内部做了什么?

答案:

  1. 读取当前对话历史
  2. 对历史进行摘要总结(保留关键信息)
  3. 压缩后的摘要替换原始长历史
  4. 释放上下文窗口空间
  5. 返回压缩前后的 token 数对比

Q25. _MemoryMark 的作用是什么?

答案:

AgentScope 的标记机制,在消息流中标记来自记忆而非本次对话的内容。带 _MemoryMark 的消息进入系统提示词,但不参与常规对话历史管理。


3. 记忆系统

Q26. QwenPaw 有几种记忆管理器?默认是哪个?

答案:

  1. ReMeLightMemoryManager(默认)— 轻量级,语义搜索 + 自动总结
  2. ADBPGMemoryManager — 基于阿里云 ADB PG 数据库
  3. AgentMdManager — 基于 MEMORY.md 文件
  4. BaseMemoryManager — 抽象基类

Q27. ReMeLightMemoryManager 的核心工作机制是什么?

答案:

  1. 写入:对话结束后调用 LLM 总结关键信息写入 MEMORY.md
  2. 检索:对话前用 Embedding 语义搜索 MEMORY.md
  3. 自动搜索:启用后每轮自动检索
  4. 压缩:超过阈值时压缩旧记忆(近期保留详细,远期摘要)

Q28. Embedding 缓存如何工作?

答案:

embedding_cache 目录缓存文本-向量对:

  1. 计算文本的 Embedding 向量
  2. 写入本地缓存文件
  3. 下次相同文本直接返回缓存
  4. max_cache_size 控制最大条目(默认 3000)

Q29. 什么是「梦境」记忆优化(Dream)?何时运行?

答案:

梦境(Dream)是记忆优化机制,默认每天 23:00(0 23 * * *)运行。从 MEMORY.md 和每日记忆中提取关键信息,交叉关联、去重、优化结构和表达后写回,类似人类睡眠记忆巩固。

Q30. auto_memory_interval 的作用是什么?

答案:

每隔 N 次用户查询触发一次自动记忆存储。例如 5 表示每 5 次用户消息后自动触发一次记忆总结。null 表示禁用(仅在上下文压缩时总结)。

Q31. memory_search 工具的 Query 参数有哪些?

答案:

memory_searchMEMORY.mdmemory/*.md 做语义搜索。参数:

  • query(必填):搜索文本
  • max_results(默认 5):最大结果数
  • min_score(默认 0.1):最低相似度阈值

Q32. memory/YYYY-MM-DD.mdMEMORY.md 的关系?

答案:

  • memory/YYYY-MM-DD.md原始日志,每天一个文件,记录当天对话事件
  • MEMORY.md精选长期记忆,是对每日记忆的提炼总结

关系:每日记忆 → 提炼 → MEMORY.md,再加梦境优化

Q33. Proactive(主动触发)功能的机制是什么?

答案:

Proactive 位于 agents/memory/proactive/

  1. 每个会话独立维护 ProactiveConfig(启用状态、空闲阈值、最后交互时间)
  2. 后台 _run_trigger_loop 异步循环监控空闲时间
  3. 超时后 generate_proactive_response 生成主动消息
  4. 每个会话对应一个 asyncio.Task

Q34. memory_manager_backendcontext_manager_backend 的区别?

答案:

  • memory_manager_backend(默认 remelight):管理跨会话的长期记忆
  • context_manager_backend(默认 light):管理当前会话的上下文(对话历史、组织、压缩、修剪)

长期记忆 vs 短期工作上下文。

Q35. compact_threshold_ratioreserve_threshold_ratio 是什么?

答案:

  • compact_threshold_ratio(默认 0.8):当上下文占用超过 max_input_length 的 80% 时触发压缩
  • reserve_threshold_ratio(默认 0.1):压缩时保留最后 10% 的原始内容

4. 技能系统

Q36. 一个 Skill 的本质是什么?必须包含什么文件?

答案:

每个 Skill 是一个目录,必须包含 SKILL.mdSKILL.md 用 Markdown 描述技能名称(name)、触发条件(description)和操作步骤。可附带 scripts/images/ 等资源。

Q37. resolve_effective_skills 做了什么?

答案:

  1. 读取 skill.json 确定已启用技能
  2. 从工作区 skills/skill_pool/ 中找到这些技能
  3. 读取 SKILL.md 注入系统提示词
  4. 注册技能定义的工具函数

Q38. 技能池(Skill Pool)和技能集(Skills)的区别?

答案:

  • 技能池skill_pool/):全局共享,所有 Agent 可引用
  • 技能集workspaces/{id}/skills/):Agent 专属

池 → 广播/加载 → 集。

Q39. materialize_skill 工具做了什么事?

答案:

将技能提案持久化到工作区:

  1. 格式验证和安全扫描
  2. 写入 SKILL.md
  3. 更新 skill.json 清单
  4. 启用该技能

常用于 /make-skill 命令流程。

Q40. ensure_skills_initialized 的职责是什么?

答案:

确保技能系统正确初始化:

  1. 检查 skills/ 目录(不存在则创建)
  2. 验证 skill.json 有效性
  3. 复制内置技能
  4. 返回初始化后的配置

Q41. 如何从 Skills Hub 导入技能?

答案:

Console 的 Workspace → Skills 页面点击 Import from Skills Hub,输入技能 URL,系统下载并自动启用。也支持上传 .zip 技能包。

Q42. 技能如何实现 Config 运行时注入?

答案:

通过 apply_skill_config_env_overrides

  1. 技能声明需要的环境变量
  2. 系统从 envs.json 读取对应值
  3. 注入到子进程环境(API Key、Base URL 等)

Q43. 两个已启用的技能定义同名工具怎么办?

答案:

NamesakeStrategy 决定处理方式:

  • override:后注册覆盖先注册
  • skip:跳过同名
  • rename:自动重命名
  • raise(默认):报错

Q44. skill.json 的结构?

答案:

{
  "skills": {
    "guidance": { "enabled": true, "builtin": true },
    "pdf": { "enabled": true, "builtin": true },
    "my_custom": { "enabled": true, "builtin": false }
  }
}

Q45. Skill 的 description 为什么重要?

答案:

description 是 Agent 决定使用技能的关键。Agent 在系统提示词中查看所有已启用技能的描述,当遇到匹配场景时按照 SKILL.md 的步骤操作。格式惯例:"Use this skill when [触发场景]"


5. 工具系统

Q46. 内置工具定义在哪里?列举 10 个。

答案:

定义在 agents/tools/ 目录下。例如:
read_file(file_io)、write_file / edit_file(file_io)、execute_shell_command(shell)、browser_use(browser_control)、desktop_screenshotgrep_search / glob_search(file_search)、get_current_timeget_token_usagechat_with_agent / submit_to_agent / check_agent_task(delegate_external_agent)、list_agentsmaterialize_skillsend_file_to_userview_image / view_videoset_user_timezone

Q47. browser_use 支持哪些浏览器启动模式?

答案:

三种:

  1. Headless(默认):无头运行
  2. Headed:打开真实窗口
  3. Managed CDP:通过 Chrome DevTools Protocol 管理,支持外部连接

headedprivate_modecdp_port 参数控制。

Q48. execute_shell_command 的超时机制?

答案:

  1. 默认超时来自 agent.jsonshell_command_timeout(默认 60 秒)
  2. 每次调用可通过 timeout 参数覆盖
  3. 超时后子进程被终止,返回超时错误

Q49. 文件守卫(File Guard)的工作原理?

答案:

文件守卫在 Agent 访问文件时:

  1. 检查路径是否在允许范围
  2. 检查是否访问敏感路径(~/.ssh//etc/passwd 等)
  3. 判定危险则阻止操作

security.file_guard.enabled 控制。

Q50. get_token_usage 的数据来源和存储位置?

答案:

数据来自 AgentScope Runtime 的 LLM token 使用统计。保存在 workspaces/{id}/token_usage.json(可通过 QWENPAW_TOKEN_USAGE_FILE 自定义),按模型和日期分类。


6. 频道系统

Q51. QwenPaw 支持哪些频道?核心抽象是什么?

答案:

支持:Console、DingTalk、Feishu、Discord、Telegram、QQ、iMessage、WeChat、WeCom、XiaoYi、Matrix、Mattermost、MQTT、Voice、SIP。

核心抽象:app/channels/base.pyBaseChannel 基类 + ChannelType 枚举。所有频道继承 BaseChannel 实现收发逻辑。

Q52. 描述消息通道的流水线。

答案:

  1. 用户发送消息 → 触发 BaseChannel 接收
  2. 封装为 AgentRequest → 进入 UnifiedQueueManager
  3. 队列分发到 Workspace Runner
  4. Runner 调用 Agent → 生成 AgentResponse
  5. 响应通过 SSE 流推回原频道
  6. MessageRenderer 格式化输出

Q53. UnifiedQueueManager 的作用?

答案:

统一消息队列管理器:

  1. 接收多频道的消息请求
  2. 有序/优先级分发到 Agent Runner
  3. 支持背压(back-pressure)和限流
  4. 保证消息处理顺序和可靠性

Q54. Console 频道和外部频道的实现区别?

答案:

Console 内置,通过 WebSocket/SSE 直连前端。外部频道需要:

  1. SDK/API 建立连接
  2. 注册 Webhook 或回调
  3. 实现消息格式转换
  4. 处理频道特有特性(卡片消息、交互组件等)

Q55. DEFAULT_CHANNEL 的值和用途?

答案:

值为 "console"。当没有特定频道上下文时(如心跳、Cron),系统使用默认频道发送消息。

Q56. access_control 模块做什么?

答案:

实现频道的访问控制:

  1. 用户 ID 白/黑名单
  2. 启用/禁用控制
  3. 消息频率限制
  4. 权限级别

Q57. MessageRenderer 的作用?

答案:

将内部消息格式渲染为各频道可展示的格式。支持多种 RenderStyle(Markdown、纯文本、富文本),处理工具调用结果、错误信息、流式输出等。

Q58. doctor_connectivity_notes 的用途?

答案:

BaseChannel 的类方法,用于频道连通性诊断。copaw doctor --deep 调用已启用频道的此方法,返回网络连接状态的自检信息。


7. Cron 与 Heartbeat

Q59. Cron 系统的后台调度器是什么?支持哪些触发器?

答案:

使用 APScheduler 的 AsyncIOScheduler。支持:

  • IntervalTrigger:固定间隔(如每 5 分钟)
  • CronTrigger:5 字段 Cron 表达式
  • DateTrigger:指定时间单次执行

Q60. Cron 任务的调度类型和任务类型有哪些?

答案:

调度类型:Interval(间隔)、Cron(表达式)、RunAt(指定时间)
任务类型:Text(固定文本)、Agent(Agent 生成回复)

Q61. Heartbeat 与 Cron 的关系和区别?

答案:

关系:Heartbeat 是特殊的 Cron 任务(job_id 固定为 _heartbeat),由 CronManager 管理。
区别

  • 查询内容来自 HEARTBEAT.md
  • 支持活跃时段设置
  • 结果可推送到 Inbox / Last / Main

Q62. Cron 执行失败的容错机制?

答案:

  1. max_concurrency:限制同一任务并发数
  2. timeout:单次超时
  3. misfire_grace_time:错过触发宽限期
  4. APScheduler 自动重试
  5. 执行记录保存于 CronExecutionRecord

Q63. is_cron_expression 如何区分 Cron 和间隔表达式?

答案:

  1. 分割为部分,不是 5 部分则返回 False
  2. 每部分匹配 ^[\d\*\-/,]+$ → True
  3. 否则 False。间隔表达式如 30m1hparse_heartbeat_every 解析。

Q64. _heartbeat 作为 job_id 的特殊性?

答案:

_heartbeat 是系统保留 job_id,用于 Heartbeat。普通任务不能使用此 ID。Heartbeat 配置来自 agent.jsonheartbeat 块,而非 jobs.json

Q65. Heartbeat target 参数的取值?

答案:

  • main:主会话执行并推送
  • last:推送到最近一次用户消息来源频道
  • inbox:推送到 Inbox 管理中心

Q66. CronExecutor 的工作流程?

答案:

  1. 获取待执行 job
  2. 检查并发/超时限制
  3. Text 类型:直接发消息;Agent 类型:构造 AgentRequest 提交 Runner
  4. Runner 调用 Agent 处理
  5. 记录执行历史
  6. 推送到目标频道

8. 多 Agent 与 ACP

Q67. MultiAgentManager 如何实现懒加载?

答案:

使用 asyncio.Lock()

  1. 首次 get_agent(id) 检查字典,不在内存则创建
  2. 加锁后再次确认(防竞态)
  3. 第一个调用者创建,其他等待者等 Event 通知
  4. 锁短暂保持(仅字典操作),不阻塞 WorkSpace 慢启动

Q68. Workspace 类封装了哪些运行时组件?

答案:

  1. Runner(AgentRunner):处理 Agent 请求
  2. ChannelManager:管理通信频道
  3. MemoryManager:管理对话记忆
  4. ContextManager:管理上下文
  5. MCPClientManager:管理 MCP 客户端
  6. CronManager:管理定时任务
  7. TaskTracker:跟踪任务状态

Q69. ACP(Agent Communication Protocol)的用途是什么?

答案:

ACP 是 Agent 间通信协议,位于 agents/acp/。允许不同 Agent 实例通过标准化协议互相发现和通信,支持:

  1. Client:发送请求到其他 Agent
  2. Server:接收并处理来自其他 Agent 的请求
  3. Service:注册和发现 Agent 服务
  4. Permissions:访问控制
  5. ToolAdapter:将远程 Agent 映射为本地工具

Q70. ACP Server 和 Client 的核心功能?

答案:

  • Server(902 行):监听请求,解析 ACP 协议消息,路由到目标 Agent,返回结果
  • Client(466 行):构造 ACP 请求,发送到目标 Agent,处理响应
  • 两者通过 core.py 定义的协议消息格式通信

Q71. ToolAdapter 在 ACP 中的作用?

答案:

ToolAdapter(241 行)将远程 Agent 的 ACP 服务映射为本地 Agent 的一个工具。这样当前 Agent 可以像调用本地工具一样调用远程 Agent 的能力,实现了跨 Agent 工具编排。

Q72. agent_id 在 HTTP 请求中如何传递?

答案:

通过 HTTP 头 X-Agent-IdAgentContextMiddleware 从中提取当前请求的目标 Agent,然后 DynamicMultiAgentRunner 根据此 ID 路由到正确的 Workspace。

Q73. 配置文件(agent.json)中的 description 字段在多 Agent 协作中的作用?

答案:

description 在多 Agent 协作时描述各 Agent 的角色和能力。其他 Agent 通过查看此描述来决定委派什么任务给该 Agent。它是一个「自我介绍」。

Q74. 内置 QA Agent 的作用和 skill 配置?

答案:

内置的 QwenPaw_QA_Agent_0.2(QA Agent)用于回答关于 QwenPaw 自身的问题。默认技能:guidance + QA_source_index。首次创建时自动配置。


9. 安全体系

Q75. QwenPaw 的三层安全防护是什么?

答案:

  1. ToolGuard(工具守卫):运行时检测危险命令和注入
  2. FileGuard(文件守卫):保护敏感文件访问
  3. SkillScanner(技能扫描器):启用前扫描恶意代码

Q76. approval_level 有哪些取值?分别代表什么?

答案:

  • STRICT:所有敏感操作都需要用户明确批准
  • SMART:智能判断,低风险自动放行,高风险请求审批
  • AUTO:完全自动,仅记录日志
  • OFF:不进行安全检查

Q77. ToolGuard 检测哪些 shell 注入模式?

答案:

  • command_substitution:命令替换($(...)`...`
  • obfuscated_flags:混淆参数
  • backslash_escaped_whitespace:反斜杠转义空格
  • backslash_escaped_operators:反斜杠转义操作符
  • newlines:换行注入
  • comment_quote_desync:注释/引号反同步
  • quoted_newline:引号内换行

Q78. 技能扫描器(SkillScanner)在什么时机运行?

答案:

在技能启用时运行(materialize_skill 或 Console 启用技能时)。扫描模式:

  • block:发现恶意代码阻止启用
  • warn:警告但允许(默认)
  • off:不扫描

Q79. 认证功能如何启用?默认是否启用?

答案:

通过环境变量 QWENPAW_AUTH_ENABLED=true 启用,默认 false(不启用)。用户名和密码可通过 QWENPAW_AUTH_USERNAME/QWENPAW_AUTH_PASSWORD 设置。启用后 Web Console 需要登录才能访问。

Q80. allow_no_auth_hosts 的用途?

答案:

IP 白名单,默认 ["127.0.0.1", "::1"],允许 localhost 绕过 Web 登录认证。可以配置更多受信任的 IP。

Q81. 审批超时和心跳间隔的默认值?

答案:

  • 审批超时:TOOL_GUARD_APPROVAL_TIMEOUT_SECONDS,默认 300 秒
  • 审批心跳间隔:TOOL_GUARD_APPROVAL_HEARTBEAT_INTERVAL,默认 15 秒(保持 SSE 连接存活)

10. App 与 Console

Q82. FastAPI 应用(_app.py)的 lifespan 中做了什么?

答案:

  1. 加载环境变量(load_envs_into_environ
  2. 加载配置
  3. 执行数据迁移(工作区、技能池、QA Agent)
  4. 恢复/清理备份工件
  5. 初始化 MultiAgentManager
  6. 注册频道路由
  7. 注册认证中间件
  8. 启动心跳和梦境任务
  9. 按配置启动频道

Q83. Console 的 Files 页面支持哪些文件操作?

答案:

  1. 在线编辑人设文件(AGENTS.mdSOUL.mdPROFILE.md 等)
  2. 查看/编辑每日记忆(MEMORY.md 展开按钮)
  3. 下载整个工作空间(.zip)
  4. 上传恢复工作空间(.zip,最大 100MB)

Q84. Inbox 的用途是什么?

答案:

Inbox 是统一审批和执行结果中心:

  1. 审批待处理:工具执行的审批请求
  2. 推送消息:Cron/Heartbeat 的执行结果
  3. 超时机制:审批请求有倒计时,超时默认拒绝

Q85. 如何 Console 查看 Token 用量?

答案:

侧边栏 Settings → Token Usage,选择日期范围(默认 30 天),页面展示总 token 数、总调用数和按模型/日期分类的明细。也可在聊天中问「我用了多少 token」。

Q86. 环境变量页面(Environments)可以做什么?

答案:

管理工具和技能所需的运行时环境变量(如 TAVILY_API_KEY)。支持增删改、批量删除。变量值由用户保证有效性,QwenPaw 只负责存储和注入。

Q87. Console 的 Skills 页面有哪些操作?

答案:

启用/禁用、查看详情、编辑、创建、删除技能。从技能池加载、同步到技能池、从 Skills Hub 导入、上传 zip 技能包。

Q88. 多 Agent 模式下 Console 顶部有什么特殊组件?

答案:

一个 Agent 切换器,显示当前活跃的 Agent。点击可切换到其他已配置的 Agent。切换后侧边栏和控制台内容(频道、工具、配置等)自动切换到该 Agent 的设置。


11. 配置系统

Q89. 全局 config.json 中的 agents.profiles 结构是怎样的?

答案:

{
  "agents": {
    "active_agent": "default",
    "profiles": {
      "default": {
        "id": "default",
        "name": "默认智能体",
        "description": "默认工作区智能体",
        "enabled": true,
        "workspace_dir": "~/.qwenpaw/workspaces/default"
      }
    }
  }
}

每个 Agent 配置引用包含 idnamedescriptionenabledworkspace_dir

Q90. agent.json 中部份关键配置项的作用?

答案:

配置 说明
language Agent 语言(zh/en/ru)
system_prompt_files 人设文件列表
active_model 使用的模型(provider_id + model)
running.max_iters ReAct 最大轮数
running.shell_command_timeout shell 命令默认超时
channels 频道配置
mcp.clients MCP 客户端
heartbeat 心跳配置
tools.builtin_tools 工具开关
security 安全策略

Q91. 模型提供商配置存在哪里?有哪些内置提供商?

答案:

存储在 ~/.qwenpaw.secret/providers.json(通过 QWENPAW_SECRET_DIR 自定义)。内置提供商包括:DashScope、OpenAI、Anthropic、DeepSeek、ModelScope、Ollama、LM Studio、SiliconFlow、Zhipu、Kimi、Gemini、OpenRouter 等,以及 Custom(自定义兼容)。

Q92. 环境变量的存储位置和加载时机?

答案:

存储在 ~/.qwenpaw.secret/envs.json。加载时机:

  1. 首次 import qwenpaw 时(__init__.pyload_envs_into_environ()
  2. FastAPI lifespan 开始时再次加载

Q93. last_dispatch 配置项的作用?

答案:

记录了最近一次用户消息分发到的频道、用户 ID 和会话 ID。用于 Heartbeat 的 target="last" 模式——心跳结果会被发送到上次用户说话的频道。自动更新,无需手动配置。


12. CLI 与命令

Q94. Click CLI 中的 LazyGroup 解决了什么问题?

答案:

LazyGroupclick.Group 的子类,实现了子命令的懒加载cli/main.py 中用 lazy_subcommands 字典将命令名映射到模块路径,只有用到时才 __import__ 加载。这大大缩短了 qwenpaw --help 的启动时间——不需要加载所有 30+ 个子命令的依赖。

Q95. CLI 中 app 命令的 _log_init_timings 是做什么的?

答案:

在设置好日志级别(debug)后重新输出 CLI 模块加载阶段的计时信息。因为模块加载发生在 setup_logger 之前,第一次导入时如果日志级别还不是 debug,那些 debug 消息会被丢弃。app_cmd 在完成日志初始化后调用 log_init_timings() 重新输出,确保调试信息不丢失。

Q96. CLI 如何确保 Windows 下能正确处理中文输出?

答案:

cli/main.py 开头:

  1. 调用 ensure_standard_streams() 确保标准流对象有效
  2. 尝试 sys.stdout.reconfigure(encoding="utf-8")(Python 3.7+)
  3. Linux 默认 UTF-8 无需处理

这样 cron 和其他命令在 Windows 终端也能输出中文。

Q97. qwenpaw init 命令的交互式向导提供哪些配置?

答案:

qwenpaw init 交互式配置:

  1. 模型提供商选择和 API Key 配置
  2. 工作目录选择
  3. 频道配置(可选)
  4. 环境变量配置(TAVILY_API_KEY 等)
  5. 创建默认工作区和人设文件

13. 记忆加固与梦境

Q98. QwenPaw 的备份系统是如何工作的?

答案:

位于 app/routers/backup.py,提供:

  1. 手动备份:通过 API 或 CLI 触发,将整个工作空间打包
  2. 自动备份:配置定时备份策略
  3. 恢复:从备份文件恢复工作空间
  4. 备份存储在 QWENPAW_BACKUP_DIR(默认 ~/.qwenpaw.backups/

14. 开放题

Q99. 如果你要扩展 QwenPaw 支持一个新的消息频道(如 Slack),你需要做哪些事?

答案:

  1. app/channels/ 下创建 slack/ 目录
  2. 继承 BaseChannel 实现 SlackChannel 类:
    • 设置 channel = ChannelType.SLACK(或新增枚举值)
    • 实现消息接收(Webhook/WebSocket)
    • 实现消息发送(SDK API 调用)
    • 实现消息格式转换
    • 可选重写 doctor_connectivity_notes 做连通性检查
  3. agent.jsonchannels 中增加 Slack 配置块
  4. registry.py 中注册新频道
  5. schema.py 添加 ChannelType 枚举值

Q100. 假设现在 QwenPaw 需要支持在多个 Agent 之间共享一个 MEMORY.md,你会如何设计?

答案:

设计思路:

方案一:中心化记忆共享

  1. skill_pool/ 级别或全局配置新增 shared_memory.md
  2. 所有 Agent 的 ReMeLightMemoryManager 在搜索时同时检索各自的 MEMORY.md + shared_memory.md
  3. 写入时,Agent 判断信息是否跨 Agent 相关,写入共享文件

方案二:ACP 式记忆查询

  1. 新增一个「记忆管家」Agent,专门管理共享记忆
  2. 其他 Agent 通过 chat_with_agent 或 ACP 协议向它查询/写入共享信息
  3. 记忆管家负责冲突解决和去重

方案三:记忆路由层

  1. BaseMemoryManager 下层新增 SharedMemoryRouter
  2. 每个 Agent 的写入先经过 Router,判断是否广播到其他 Agent
  3. 读取时自动合并个人记忆 + 共享记忆的搜索结果

三种方案从简单到复杂,取决于一致性要求和性能需求。


🎯 全部 100 题到此结束!

小微出品,祝你面试顺利~ 🚀

0

评论区