Marvis(腾讯马维斯)技术方案
来源说明:产品定位引自官方站点与技术介绍;实现机制全部来自对本机
~/.marvis/的实测(目录、SQLite schema、表行数、统计分布)。 实测数据采集于 2026-10-27,反映的是"这台机器上真实跑出来"的形态,可能与官方白皮书表述有出入 —— 出入处我以实测为准并标注。
1. 定位:操作系统级的"手",不是"笔"
WorkBuddy 的落点是交付物(文档、表格、代码)。Marvis 的落点是操作本身(改系统设置、开软件、点网页、控制手机)。
这个差别决定了架构取向:
| | WorkBuddy | Marvis |
|---|---|---|
| 隐喻 | 一个能干的同事,最后给你文件 | 一双手,直接替你点、改、装 |
| 执行半径 | 工作目录为主 | 文件系统 + 注册表 + 进程 + 应用 UI + 手机 App |
| 风险模型 | 怕改错文件 | 怕改坏系统 |
| 状态载体 | 项目文件夹(jsonl / md / zip) | 三个 SQLite 库(业务 / 记忆 / 主数据) |
官方两个模式:效率模式(端云协同)、本地模式(端侧模型,文件 0 上传)。本机实测 llm_token_usage.is_local 全为 0 —— 说明当前跑在效率模式。
2. 多 Agent:不是"临时派生",是"常设编制"
官方说法是 1 主 + 5 副。实测 agent_activities 表按 agent_name 分组的真实调用次数:
file-agent 330
computer-agent 16
app-agent 9
browser 8
(search 没有独立活动记录,可能并入主控或被合并;主控在工具归属里标为 main。)
关键区别在这里:WorkBuddy 的子 Agent 是一次任务里临时派生的,任务结束就没了;Marvis 的领域 Agent 是常设编制,各自拥有固定工具集。证据是 mcp_tool_index.owner_agents 字段:
yyb-toolkit / click_observe owner_agents = ["app-agent"] always_on = 1
game_info / list_game_capabilities owner_agents = ["main"] always_on = 0
androws_mcp / adb_debug owner_agents = ["app-agent"] always_on = 1
即:Agent 的边界是由"挂哪些工具"定义的,不是由 prompt 里的一段角色描述定义的。工具归属一变,Agent 能力就变,不用改代码。
3. 工具层:167 个可调用项,靠向量检索挑
实测工具规模:
mcp_tool_index78 个工具,分布在 9 个 MCP server:
androws_mcp 19 · commerce 18 · yyb-toolkit 16 · marvis_capabilities 14
knowledge_base 4 · coupon_activity 2 · game_info 2 · wintools 2 · MarvisMCP 1
skill_index89 个技能,category全部为builtin(内置;skills/custom与skills/market目录为空,用户没装第三方的)
合计 167 项,不可能全塞进 prompt。解法在表结构里:
mcp_tool_index: server, tool_name, source, name, description, parameter_desc,
owner_agents, added_at, last_used_at, enabled, always_on,
embed_text, version, indexed_version
三个字段说明了一切:
embed_text—— 工具存在向量化文本,选工具走语义检索("我想把手机上的截图拉过来"能命中adb_pull),不是关键词匹配。length(embed_text)=0的(如click_observe)是常驻工具,不需要被检索。always_on—— 白名单式常驻。高频且必须随手可用的工具不参与检索,直接进上下文。indexed_version/version—— 索引和工具定义各自带版本。工具描述改了要重新嵌入,这两个字段负责判断索引是否过期。
对比 WorkBuddy:那边用的是"关键词/精确名检索 → 取 schema → 调用"的两级懒加载,纯文本匹配;Marvis 这层是向量检索。前者确定性高、成本低;后者泛化好,但要维护嵌入索引和版本一致性。
能力几乎全部 MCP 化是 Marvis 最值得注意的架构选择。连"点应用宝界面"(yyb-toolkit/click_observe)、"adb 调试"(androws_mcp/adb_debug)、"改 Windows 设置"(wintools)都是 MCP 工具。好处是能力可插拔、可灰度、可单独开关(enabled 字段);代价是每条能力都多一层协议开销。
4. 事件流:2579 万行事件,UI 是"回放"出来的
data.db 有 12.4GB,主要来自一张表:
agui_events 行数 ≈ 25,790,649
字段:event_id, conversation_id, response_id, seq, event_type, data, metadata, timestamp
event_type 的实测分布(采样最近 3000 条):
REASONING_CONTENT 1396 TEXT_MESSAGE_CONTENT 1065
TOOL_CALL_ARGS 481 CUSTOM 12
TEXT_MESSAGE_START 7 REASONING_END 7
REASONING_START 6 TEXT_MESSAGE_END 6
RUN_STARTED 4 HUMAN_MESSAGE 4
RUN_FINISHED 4 TOOL_CALL_RESULT 4
TOOL_CALL_END 2 TOOL_CALL_START 2
这是一套标准的 AG-UI 事件协议(Agent–User Interaction):RUN_STARTED → REASONING_ / TEXT_MESSAGE_ / TOOL_CALL_* → RUN_FINISHED,带 seq 序号。
架构含义有三层:
- UI 不是"等最终答案",而是订阅事件流逐帧渲染。 思考过程(REASONING_CONTENT)、正文流、工具调用参数生成(TOOL_CALL_ARGS)都能实时显示 —— 这就是"执行日志里能看到六个人分工"的实现基础。
seq+ 全量落库 = 可回放、可断线续传。 关掉客户端再打开,会话能恢复到逐条事件级,不是恢复到"最后一句话"。- 代价是写放大约两个数量级:9.5 万条消息对应 2579 万条事件(约 272 倍)。这是用存储换体验的典型交易,必须配套归档/分区策略,否则单库无限膨胀(本机已经 12.4GB,WAL 还有 1.6GB)。
5. 人在环与可恢复:两张表撑起"敢让它动手"
approvals(审批) —— 1024 条,状态分布:
approved 790 · cancelled 6 · pending 2 · rejected 2
字段:approval_id, conversation_id, tool_call_id, tool_name, arguments, status, reason, metadata, created_at, decided_at
设计要点:审批是持久化实体,不是弹窗即弃。arguments 存了当时要执行的具体参数 —— 事后能回答"它当时想干什么、我批的是什么"。reason 让拒绝有据可查。约 1% 的消息会触发审批,说明分级做得比较克制:常规操作不问,只有越界才拦。
agent_checkpoints(61 万条…准确说是 60,644 条) —— 字段 conversation_id, response_id, checkpoint_data。
一个 response_id 一个检查点,意味着长任务中断后可从中途续跑,而不是从头再来。对"我要它连续装三个软件再配环境"这类任务,这是必备项。
对比 WorkBuddy:那边是 orderedRules 三类规则的事前拦截 + 哈希链审计 + 文件回滚;Marvis 是 approvals 事前确认 + checkpoints 事后续跑。前者偏"系统级策略",后者偏"交互级确认"。两者其实是互补的两套思路,谁也没覆盖对方。
6. 模型层:每个 Agent 一个模型别名 + 94% 缓存命中
llm_token_usage 字段(注意 is_local 这一列):
usage_date, conversation_id, response_id, model_id, is_local,
input_tokens, output_tokens, thinking_tokens, cached_tokens, total_tokens
实测分布(这是最能说明工程水位的表):
| model_id | 调用次数 | 输入 token | 输出 token | 缓存 token |
|---|---|---|---|---|
| file-auto | 24,303 | 1439.1M | 17.5M | 1351.3M |
| main-auto | 19,821 | 1074.0M | 11.8M | 996.4M |
| deepseek-v4-pro-external | 2,382 | 46.8M | 1.7M | 21.6M |
| venus-vision-llm | 1,245 | 1.1M | 0.3M | 0 |
| hy3-preview-agent-real | 1,238 | 11.1M | 0.1M | 1.1M |
| browser-auto | 1,136 | 61.9M | 0.4M | 59.4M |
| computer-auto | 691 | 29.4M | 0.5M | 27.7M |
| app-auto | 288 | 10.8M | 0.1M | 10.3M |
三个观察:
-auto后缀 = 路由别名,不是具体模型。file-auto/main-auto/browser-auto/computer-auto/app-auto一一对应领域 Agent —— 每个 Agent 有自己的选型策略(简单判据用便宜模型,复杂规划切强模型)。这是"按角色分模型",比"全局一个模型"省得多。- 缓存命中率 93–94%(1351/1439、996/1074)。这是硬指标:说明 prompt 前缀极其稳定 —— 系统提示、工具定义、历史前缀固定在前,只让末尾变化。前缀设计一旦抖动,这个数字会立刻掉下来。这是衡量 Agent 工程成熟度最直接的一个数。
venus-vision-llm缓存为 0 —— 视觉模型输入是截图,天然无法前缀复用。也反过来说明其他模型的缓存是"设计出来的",不是白捡的。
model_configs(business.db)显示支持 BYOK + 第三方模型:
deepseek-v4-flash DeepSeek https://api.deepseek.com/chat/...
GLM-5.3-Flash 智谱 https://open.bigmodel.cn/api/...
密钥处理是规范的:api_key_ciphertext(密文)+ salt + api_key_fingerprint + key_tail(只回显尾号)。没用明文列存 key。
7. 三个库的分工(这是与 WorkBuddy 最大的形态差异)
| 库 | 大小 | 表 | 职责 |
|---|---|---|---|
| business.db | 2.9 MB | 10 | 模型配置、会话-模型绑定、任务日统计、Office 行为埋点、schema 迁移 |
| memory.db | 570 MB | 6 | conversations / conversation_detail / memory_entries / user_profile / kv_store |
| data.db | 12.4 GB | 16 | 消息、事件流、活动、检查点、审批、工具索引、产物、token 计量、画像 |
为什么拆三个:写入频率与生命周期不同。事件流是高频写(2579 万行),业务统计是低频读(3MB),记忆是读多写少的长期资产。混在一个库里,一次 WAL checkpoint 就要拖动 12GB —— 拆开后各自独立 VACUUM / 归档。
memory_entries 的字段值得单独看:
memory_id, conversation_id, agent_name, uid, source, type,
title, summary, full, display_title, display_summary, display_full,
origin, status, metadata, created_at, updated_at,
last_accessed_at, accessed_times, migrated_from
- 双层存储
summary/full:检索走摘要,命中才拉全文。 - **
display_三件套*:另存一份展示用版本 —— 说明"给模型看的"和"给人看的"是两套文本(可能是脱敏或格式化后的)。 accessed_times/last_accessed_at:记忆有热度,可做 LRU 淘汰。记忆库只增不减是常见坑,这两个字段是解药。migrated_from:记忆格式迁移的溯源,说明这套记忆体系已经改过版。
user_personas 则是画像层:style / persona_keyword / scenario / hobby / raw_prompt / cloud_last_modified。cloud_last_modified 说明画像会跟云端同步 —— 这跟"文件 0 上传"的本地模式并不矛盾:画像同步的是偏好,不是文件内容。
8. 入口层:三个,且都不是屏幕模拟
浏览器扩展 + Native Messaging Host(这才是"Browser Agent"的真相)
AppData/Local/Marvis/nmh/ 下有:
com.marvis.extension.chrome.json
com.marvis.extension.edge.json
com.marvis.extension.qq_browser.json
com.marvis.extension.360_se.json
com.marvis.extension.360_speed.json
com.marvis.extension.json
Native Messaging Host 是浏览器官方支持的"扩展 ↔ 本地程序"通道。配合 marvis-browser-edge.json:
{ "port": 50315, "token": "...", "pid": 17564, "browser": "edge",
"host_version": "0.1.0", "started_at_ms": ... }
即:本地起一个带 token 校验的端口,扩展连过来。取 DOM、执行点击都不需要看像素 —— 这就是官方说"不靠视觉看屏幕"的实现路径:能走协议就不走视觉。
手机远程:mobile_address.json 存 mobile_open_id / mobile_guid / session_id / access_token / login_type。手机通过 token 连本机,看执行画面并接管。
安全提醒(重要):
mobile_address.json和marvis-browser-edge.json里的 token 是明文落盘的。这两个文件等于"你电脑的遥控器"。异常场景(共享机器、备份上传网盘、恶意软件扫盘)下这是明确的风险面,比 WorkBuddy 那种纯本地会话文件敏感得多。建议自己确认下这两个文件的权限。
产物面:products 表 1223 条,按扩展名分布:
.exe 141 · .py 116 · .md 86 · .png 73 · .apk 53 · .pdf 40
.html 27 · .txt 26 · .kt 21 · .js 21
不只输出文档,还能产出可执行程序(.exe / .py / .js)、写 Kotlin(.kt)、下载安装 APK(.apk)。这解释了 12GB 库的体积,也说明它的执行面确实比"办公助手"大一圈。
9. 与 WorkBuddy 的架构对比(同一类产品,两种哲学)
| 维度 | WorkBuddy | Marvis |
|---|---|---|
| 核心抽象 | 项目 = 文件夹 | 会话 = 数据库行 |
| Agent 编制 | 单主循环 + 临时派生子 Agent | 常设主控 + 5 个固定领域 Agent |
| Agent 边界由什么定义 | prompt + 可用工具集 | owner_agents 字段(数据驱动) |
| 工具发现 | 关键词/精确名检索(确定性) | 向量检索 embed_text + always_on(语义) |
| 扩展方式 | 内置 + Skill + MCP + 专家包(四种) | 几乎全 MCP 化(一种) |
| UI 驱动 | 消息 + 产物双区 | AG-UI 事件流(2579 万条,可回放) |
| 事前控制 | orderedRules file/command/network 三类有序规则 | approvals 审批表(1% 消息触发) |
| 事后追溯 | 哈希链审计(prevHash→hash,防篡改) | 事件全量 + 检查点(可回放) |
| 撤销能力 | 会话级文件回滚 | 检查点续跑(不是回滚) |
| 模型策略 | 云端路由 + 本地 llama.cpp | 每 Agent 别名 + BYOK + is_local 双轨 |
| 状态规模 | 与项目大小同阶 | 单机 13GB 起 |
最本质的差异:WorkBuddy 把状态放在文件系统里(人类可读、可 git、可打包带走);Marvis 把状态放在数据库里(查询快、可统计、可回放,但不可读、不可移植)。
对应两种产品观:
- 文件系统 → 产物导向,一切为了让用户拿到能用的文件
- 数据库 → 过程导向,一切为了让执行可观测、可干预、可恢复
10. 这套方案的风险点(实测看到的问题)
- 单库 12.4GB + 1.6GB WAL:事件全量持久化的代价。没有分区归档的话,长期使用会撞上 SQLite 的实际管理上限(备份、VACUUM、迁移都会变成大工程)。
- token 明文落盘:
mobile_address.json/marvis-browser-edge.json。这是设计上省了事、安全上留了口子。 - 能力半径过大:注册表编辑、进程管理、adb、装 APK。审批表能拦,但审批疲劳(790 次 approved)会让人逐渐无脑点"允许" —— 这是所有 HITL(人在环)系统的通病。
is_local=0全量:本地模式在本机没跑起来(官方门槛 ≥8GB 内存 / Apple Silicon M1)。端侧模型的实际体验仍是未知数。- 事件模型对磁盘的持续压力:2579 万条 / 97 个会话 ≈ 每个会话 26 万条事件。会话数一多,写放大很可观。
11. 一句话总结
WorkBuddy 是"把活干完,文件给你";Marvis 是"把机器接管,过程给你看"。
前者靠文件系统 + 有序规则 + 哈希链审计,追求确定性交付;
后者靠多 Agent 编制 + 向量工具检索 + 事件溯源,追求可观测执行。
要抄的话:Marvis 的 owner_agents(工具归属定义 Agent 边界)和 embed_text(工具向量检索)值得直接借鉴 —— 前者让 Agent 编排变成数据配置,后者在工具过百时几乎必需。至于事件全量落库,先想清楚 12GB 之后怎么办再动手。
最新评论
还没有评论