fix(engine): 显式发送 User-Agent,修复网关按 UA 拦截导致的 403 症状:同一 key、同一端点、同一模型,/models 返回 200, 一发对话就 403(返回体 error code: 1010),doctor 报「凭据连通性 失败」, 而 codex CLI 用同一套凭据正常 —— 看起来像密钥失效,实际不是。 根因:引擎只发 Authorization 与 Content-Type,未设 User-Agent, urllib 于是回落到默认的 Python-urllib/3.x,被网关前置的 Cloudflare 托管规则按 UA 拦掉。实测 curl / 浏览器 / codex 的 UA 均放行。 修复: LLMConfig 新增 user_agent 字段,默认发送自报身份的 UA(不冒充浏览器) _headers() 一并补上 Accept,作为唯一出站选择点,chat/stream/probe 全覆盖 支持 MACC_LLM_USER_AGENT 覆盖,换网关无需改代码 doctor 把 403 从 401 分支拆出:UA 拦截与密钥失效的修复动作完全不同, 合并处理会把排查引向错误方向 回归:新增 3 个用例钉住「必须带 UA」「可被环境变量覆盖」 「403+1010 不得诊断为密钥无效」。全套 1600 passed,四道静态闸门全绿。
fix(engine): 显式发送 User-Agent,修复网关按 UA 拦截导致的 403
症状:同一 key、同一端点、同一模型,/models 返回 200, 一发对话就 403(返回体 error code: 1010),doctor 报「凭据连通性 失败」, 而 codex CLI 用同一套凭据正常 —— 看起来像密钥失效,实际不是。
根因:引擎只发 Authorization 与 Content-Type,未设 User-Agent, urllib 于是回落到默认的 Python-urllib/3.x,被网关前置的 Cloudflare 托管规则按 UA 拦掉。实测 curl / 浏览器 / codex 的 UA 均放行。
修复:
回归:新增 3 个用例钉住「必须带 UA」「可被环境变量覆盖」 「403+1010 不得诊断为密钥无效」。全套 1600 passed,四道静态闸门全绿。
第三届中国研究生操作系统开源创新大赛暨开放原子大赛操作系统专项赛 赛道:应用创新 · 赛题 9(社区赛题)
MACC(Multi-Agent Collaboration Core)为多智能体协作提供系统层基础设施: 用结构化协议替代自然语言通信、用共享内存直接传递中间状态、用可检索记忆实现跨任务复用。
它不是又一个 Agent 编排框架。现有框架解决的是”如何组织 Agent”, MACC 往下一层,约束消息如何编码、状态如何传递、结果如何复用 —— 这三件事恰好都是操作系统层面的老问题:序列化开销、进程间数据搬运、缓存与复用。 我们把它们放回系统层解决,而不是继续堆在 prompt 里。
macc/
tests/
目录:演示视频 · 30 秒跑起来 · 给评审的复核路径 · 三端形态 · 仓库结构导览 · 解决什么问题 · 相关工作与差异定位 · 系统架构 · 三套机制怎么工作 · Agent 桌面执行环境 · 命令清单 · 实验设计 · 完整实测数据 · 工程质量 · 赛题符合性对照 · 关键设计取舍 · 依赖 · 文档 · 常见问题 · 已知限制 · 原创性说明
演示视频为一次完整演示的连续录制,分三段存放, 请按 1 → 2 → 3 的顺序连续观看(三段合计 14:41)。 文件已随仓库提交在根目录,可直接下载:
备用下载(网盘):https://pan.baidu.com/s/16guTLfWgAfPnB2YIOHeqJw 提取码 t223
t223
分段只是为了控制单文件体积,内容前后衔接、不可跳看 —— 后一段的操作建立在前一段已完成的状态之上(例如已安装的扩展、 已积累的会话与记忆、已产出的工作区文件)。
三段以桌面客户端实机运行为准,整体覆盖:多轮对话与会话管理、 长短期记忆与上下文压缩、多模态解析(PDF / 视频 / 图片 / 音频)、 工具调用、工作区文件读写与执行、Skills 与 Plugins 的安装管理及对话内调用、 三个子 Agent 分工协作,以及赛题三套机制(ACP / STX / SMEM)的验证视图。
三个文件均在赛事 100 MB/文件 的上限内,未使用 Git LFS。 其中视频 1 与视频 3 的原始录屏分别为 263 MB 与 77 MB,超过上限, 已用 tools/compress_video.py 压缩: 保持原 2560×1600 分辨率不缩放(屏幕录制需保证界面文字可读), 仅提高 CRF 与降低音频码率,抽样 SSIM 0.996,肉眼无差异。 视频 2 本身未超限,未做压缩。
演示脚本与逐步操作见 docs/09-demo-script.md。
openEuler 24.03-LTS-SP3 自带 Python 3.11,无需安装任何第三方包:
python3 -m macc.cli desktop # ① 桌面客户端 MACC Studio(推荐,图形界面) python3 -m macc.cli agent-smoke # Agent 全栈冒烟(18 项,不需要网络) python3 -m macc.cli doctor # 环境自检 python3 -m macc.cli smoke # 冒烟测试 → SMOKE OK python3 -m macc.cli demo # 六步演示(纯命令行) python3 -m macc.cli bench # 12 轮 A/B 实验 + 生成报告
桌面端需要 Tk 支持;openEuler 上一条命令即可:sudo dnf install -y python3-tkinter。 命令行部分不需要 Tk。
sudo dnf install -y python3-tkinter
完成后打开 reports/latest/report.html 查看全部对比数据与图表。 一键复现全流程:sh scripts/run_all.sh
reports/latest/report.html
sh scripts/run_all.sh
/dev/shm
--shm-size=256m
dnf install python3-tkinter
doctor 会把上面每一项逐条检查并打印结论,末行输出 DOCTOR OK。 它同时会真的调一次模型接口验证凭据连通性(离线环境可加 --no-llm-probe 跳过, 录屏或正式演示前建议加 --require-llm 强校验)。
doctor
DOCTOR OK
--no-llm-probe
--require-llm
复制 .env.example 为 .env,填入 OPENAI_BASE_URL / OPENAI_API_KEY / MACC_LLM_MODEL。任何 OpenAI 兼容端点均可。
.env.example
.env
OPENAI_BASE_URL
OPENAI_API_KEY
MACC_LLM_MODEL
优先级提醒:真实环境变量会覆盖 .env 中的同名项 —— 这是刻意设计, 但如果 shell 里残留一个失效的旧 key,就会出现”.env 明明填对了却一直 401”。 见常见问题第 1 条。
本项目所有对外声明的数字都可以在本地当场复核,报告中没有任何手工填写的数值。 下表给出”主张 → 命令 → 预期输出”的一对一映射,全程离线、约 5 分钟:
python -m macc.cli doctor
python -m macc.cli smoke
[PASS]
SMOKE OK (14/14 项通过)
python -m macc.cli agent-smoke
[OK]
AGENT SMOKE OK (18/18 项通过)
python -m macc.cli demo
python -m macc.cli bench --rounds 12 --seed 20260729
reports/latest/
diff
report.json
python -m macc.cli memory search --query "账单科目错配"
matched_by
python -m pytest tests -q
passed
live
python tools/check_docs.py
DOCS OK
python tools/originality_check.py
python tools/anonymity_check.py
ANONYMITY OK
一条命令跑完全部:sh scripts/run_all.sh,或 make verify。
make verify
我们也把不利数据留在了报告里。 例如协作层新增的记忆检索开销(约 0.8 ms/轮)、 端到端时延方向随平台变化、LoCoMo 上与 BM25 的差异未达统计显著 —— 这些都写在正文而不是脚注,理由见已知限制。
python -m macc.desktop
python -m macc.cli
import macc
桌面端是一个完整的 Agent 桌面执行环境(对标 ChatGPT Desktop / Claude Desktop / Trae / 通义灵码 一类产品),同时保留赛题机制的验证视图。左侧导航共 12 个页面, 分成”Agent 能力”与”机制验证”两组:
Agent 侧七层架构齐备:多轮会话与 Session 管理、长短期记忆(含上下文压缩与跨会话引用)、 ReAct 推理行动循环、17 个工具(+记忆读写共 19)、工作区四档权限(默认 YOLO 完全放开,等价 Codex YOLO / Claude Code --dangerously-skip-permissions)、 多模态解析(PDF/Word/Excel/PPT/音视频/图片,带页码与时间点定位)、 Skills 与 Plugins、五类子 Agent 编排。 详见 docs/14-agent-desktop-guide.md。
--dangerously-skip-permissions
关键设计:Agent 的长期记忆直接建在本项目 SMEM 之上;主/子 Agent 通信走 ACP 结构化协议(二进制、0 prompt token);代码执行走 CodeAct 沙箱 —— 赛题三套机制 在这里从”被展示”变成”被真实使用”。这一点值得强调:如果三套机制只是跑在评测脚本里, 它们的价值就只能靠数字说明;而当整个桌面端的记忆、通信、执行都压在它们身上时, “能用”本身就是一条证据。
运行截图见 docs/screenshots/(25 张:机制验证 16 张 + Agent 9 张, 均由脚本驱动真实窗口抓取并做内容去重校验 —— 有测试断言任意两张截图内容不得相同, 防止把过期画面当证据)。
project/ ├── macc/ ← 全部运行时代码(18,743 行,零第三方依赖) │ ├── protocol/ ACP 结构化协议:schema 强校验 · 四种 codec · │ │ 能力描述 · 文本⇄结构映射 · 增量上下文 │ ├── state/ STX 状态传递:POSIX 共享内存总线 · TensorRef · │ │ 零拷贝视图 · CRC32 校验 · embedder │ ├── memory/ SMEM 共享记忆:六类记忆单元 · BM25 倒排 · │ │ 标签索引 · 向量索引 · 混合检索 · 复用门控 │ ├── sandbox/ CodeAct 沙箱:AST 白名单 guard · 子进程 runner │ ├── transport/ 帧协议(长度+CRC)· 进程内队列 · UNIX socket · TCP │ ├── runtime/ Registry 能力发现 · Broker 握手与计量 · │ │ Scheduler DAG 调度 · Session 生命周期 │ ├── agents/ 四类协作角色:planner / retriever / executor / summarizer │ ├── engine/ 推理引擎:deterministic(默认)· llm(OpenAI 兼容) │ ├── eval/ 指标采集 · 任务族 · A/B 实验台 · 报告与 SVG 图表 │ ├── agent/ Agent 桌面端后端:会话 · 记忆 · ReAct 循环 · 工具 · │ │ 多模态 · Skills/Plugins · 扩展安装器 · 子 Agent 编排 │ ├── desktop/ tkinter 桌面客户端(12 个页面 + 主题 + 截图脚本) │ ├── app/ 服务层(桌面端与 CLI 共用) │ └── cli.py 9 个子命令的命令行入口 ├── tests/ 1,593 个用例(14,547 行)unit / integration / e2e ├── docs/ 16 份设计与交付文档 + 25 张运行截图 ├── tools/ lint · 文档一致性 · 匿名性 · 原创性 · 交付物生成 ├── scripts/ setup.sh · run_all.sh(一键复现) ├── reports/latest/ 实验产物:report.json/md/html + 5 张 SVG 图表 ├── skills/ plugins/ 内置 3 个技能与 1 个示例插件 ├── 项目说明书.pdf 提交材料(.docx 为源文件) ├── 原创承诺书.pdf 提交材料(.docx 为源文件) ├── 演示PPT.pptx 提交材料 └── 演示视频1~3.mp4 演示视频(串联,按序观看)
interface/ 为参考用的外部项目,不属于 MACC 运行时,未被本项目任何代码引用, 已在 tools/originality_check.py 的 ALLOWED 中登记并注明理由。
interface/
tools/originality_check.py
ALLOWED
赛题指出当前多 Agent 系统的三个痛点。MACC 针对每一个给出一套系统层机制:
(12 轮连续任务,种子 20260729,tiktoken 精确计量。24 轮时命中率升至 85.00%、执行步数 ↓27.78%)
为什么”少发 token”不等于”少办事”。 降开销最容易的做法是少传信息, 代价是答案变差 —— 那样的对比毫无意义。所以我们把”质量守恒”做成了断言: 端到端测试要求两种模式对同一任务产出的结论签名完全一致。 省下的 80% 字节和 100% token,没有以答案质量为代价换来。 这条断言在 tests/e2e/ 里,每次提交都会跑。
MACC 与现有工作并非只在单一算法指标上竞争,而是把控制面协议、数据/状态面载体、 知识面记忆复用统一进一个可在 openEuler 上执行和测量的运行时。相关工作的能力边界 与直接比较范围如下;完整论述、引用和实验口径见 technical supplement.pdf。
TensorRef
公平比较边界: nl/json/cjson/acp1 使用相同任务、Agent、DAG 和运行环境,属于 协议层同条件基线;Apache Arrow 属于状态载体同条件基线;SILO-BENCH 使用 Level-I exact-oracle replay 检查通信正确性和开销,不表述为完整端到端 SOTA 复现。 LoCoMo 的 1,977 个可评测问题上,MACC hybrid Recall@5 为 0.4977、BM25 为 0.4883,但 conversation-cluster 配对置信区间跨越 0,因此结论是“在显著降低 full-history 载荷的同时保持有竞争力的检索质量”,而不是“统计显著全面优于 BM25”。
nl/json/cjson/acp1
┌─────────────────────────────────────────────────────────────────────────┐ │ CLI / 评测 doctor · smoke · run · bench · memory · demo │ ├─────────────────────────────────────────────────────────────────────────┤ │ EVAL 评测层 指标采集 · 3 组关联任务族 · A/B 实验台 · 报告与 SVG 图表 │ ├─────────────────────────────────────────────────────────────────────────┤ │ AGENT 角色层 Planner · Retriever · Executor · Summarizer(四类角色) │ ├─────────────────────────────────────────────────────────────────────────┤ │ RUNTIME 运行时 Registry(能力发现) · Broker(握手/路由/计量) · │ │ Scheduler(DAG 调度/复用门控) · Session(生命周期) │ ├──────────────┬───────────────┬───────────────┬─────────────────────────┤ │ PROTOCOL ACP │ STATE STX │ MEMORY SMEM │ SANDBOX CodeAct │ │ 四要素强校验 │ 共享内存段 │ 六类记忆单元 │ AST 白名单 │ │ 四种 codec │ TensorRef 句柄│ BM25 倒排索引 │ 受限命名空间 │ │ 能力描述表 │ 零拷贝视图 │ 标签索引 │ 子进程隔离 │ │ 文本⇄结构映射│ 引用计数 GC │ 向量索引 │ 时间/输出/内存限额 │ │ 增量上下文 │ CRC32 校验 │ 混合检索+归因 │ 结构化结果回传 │ ├──────────────┴───────────────┴───────────────┴─────────────────────────┤ │ TRANSPORT 帧协议(长度+CRC) · 进程内队列 · UNIX socket · TCP │ ├─────────────────────────────────────────────────────────────────────────┤ │ 基础设施 config · logging(JSONL) · errors · ids/clock · tokens │ └─────────────────────────────────────────────────────────────────────────┘
对应赛题「具体要求 9」的五大模块:多 Agent 运行时(runtime/+agents/)、 协议解析与调度(protocol/+runtime/scheduler.py)、状态交换(state/)、 共享记忆存储与检索(memory/)、评测(eval/)。
runtime/
agents/
protocol/
runtime/scheduler.py
state/
memory/
eval/
以任务族 billing 的第 2 轮「生成根因报告」为例,一次完整往返如下 —— 每一步都能在「协作时间线」页看到对应的消息条目:
billing
① Session 开启,Broker 完成 HELLO/WELCOME 握手,版本协商通过 ↓ ② Scheduler 从任务族取出 DAG(6 步),逐步派发 ↓ ③ Planner 产出计划 → ACP Envelope{action="plan.task", params, result} 经 acp1 二进制编码写入 transport(278 字节,0 prompt token) ↓ ④ Retriever 收到后先查 SMEM: score = 0.5·BM25 + 0.2·Jaccard(tags) + 0.3·cosine 命中第 1 轮沉淀的"证据链"记忆 → 复用门控判定 REUSE → 整步跳过,不再重算(`recompute_skipped` +1) ↓ ⑤ 需要传向量时不进文本:Embedder 产出 float32 缓冲 → bus.publish() 写入 POSIX 共享内存 → 消息里只带 TensorRef 句柄 下游 bus.attach() 映射同一物理页,CRC32 校验后零拷贝参与运算 ↓ ⑥ Executor 需要跑代码 → CodeAct 沙箱子进程执行,AST 白名单先过一遍, 带时间/内存/输出三重限额,结构化结果回传 ↓ ⑦ Summarizer 汇总结论 → 写回 SMEM(六类记忆单元之一,五项必填元数据) ↓ ⑧ Session 关闭:引用计数归零,共享内存段自动 unlink(12 轮后零泄漏) 全过程指标进 metrics,落 JSONL 日志,供 eval 层生成报告
纯文本基线模式(--mode text)走的是同一条路径、同一套 Agent、同一个 DAG, 只把③的编码换成自然语言长文本、⑤的向量序列化进文本、④的记忆检索关掉。 差异只来自这三套机制 —— 这是整套 A/B 对比可信的前提。
--mode text
一条消息把协作信息收敛为四个语义单元,大块数据只传引用:
Envelope ├── action 动作类型 "retrieve.docs" ├── params 输入参数 {"query": "...", "top_k": 4} ├── result 返回结果 {"docs": [...], "count": 4} ├── caps 能力描述 [Capability(...)] ← 握手/发现时携带 ├── refs 张量句柄 [TensorRef] ← 大块数据走共享内存 └── memrefs 记忆引用 ["m-billing-0a1b2c3d"] ← 不内联记忆全文
同一条逻辑消息的四种线上形态(macc.cli demo 可现场复现):
macc.cli demo
nl
json
cjson
acp1
acp1 的 prompt token 为 0 不是取巧:结构化模式下 Agent 间不再经过语言模型 的上下文窗口,消息直接在运行时之间流动,因此没有任何 token 被消耗。 这也正是赛题要求”不得仅用自然语言长文本透传”的直接体现。
协议层强制执行这条要求:内联数值数组超 16 个元素、 单字段文本超 512 字符一律被 validate() 拒绝 —— 这是代码级约束,不是口头承诺。 想绕过它就得改 macc/protocol/schema.py 并让相应测试变红。
validate()
macc/protocol/schema.py
为什么保留 nl 与文本映射器? 因为可观测性不能牺牲。mapper 提供结构化 ⇄ 自然语言的双向映射并有往返语义等价测试:调试时人能读,运行时机器传二进制。 二者不是二选一。
mapper
生成 Embedder.encode() → float32 连续缓冲 传递 bus.publish(tensor) → 写入 POSIX 共享内存,返回 TensorRef 句柄 (消息内只有元数据,无任何数值) 接收 bus.attach(ref) → 映射同一物理内存,零拷贝 memoryview + CRC32 校验 使用 view.cosine() / .topk() → 直接参与运算,无文本解析
已验证:张量 8 → 8000 元素(放大 1000 倍),消息大小差 < 16 字节; 子进程仅凭句柄即可读出父进程张量(含切片视图);引用计数归零自动 unlink; 12 轮后零泄漏。
这里省掉的不只是字节,是两次格式转换。 传统做法把 embedding 序列化成文本 再由下游解析回浮点数,一来一回既耗 CPU 又损精度;共享内存路径下, 下游拿到的就是同一块物理内存上的 memoryview,没有拷贝、没有解析、没有精度损失。 本次实验中基线为此内联了 2,668 个字符的向量文本,结构化模式为 0。
memoryview
安全性同样被钉住:段名注入、越界句柄、CRC 篡改、超大帧声明都有专门的拦截测试 —— 共享内存是把双刃剑,暴露物理内存就必须假定句柄可能是恶意的。
score = 0.5 × BM25(关键词) + 0.2 × Jaccard(标签) + 0.3 × cosine(语义向量)
每条命中带 matched_by 归因,可解释”为什么被召回”。复用要过三道门: 分数达阈值、任务主题相关、content 含必备键。三档结论 REUSE(跳过计算)/ AUGMENT(作提示但仍计算)/ RECOMPUTE。
content
REUSE
AUGMENT
RECOMPUTE
三道门是必要的,不是保守。 只看相似度分数会把”看起来像”的记忆当成”能用”, 一旦复用了不该复用的中间结果,错误会沿任务链传播且难以定位。 所以门控除了分数,还要求主题相关且 content 里确实有下游需要的键 —— 宁可退回 AUGMENT(拿来当提示但照样算一遍),也不赌一次。 AUGMENT 这一档的存在本身就是承认:检索到了不等于可以跳过。
质量守恒的证据:端到端测试断言两种模式对同一任务产出的结论签名完全一致 —— 省下的开销没有以答案质量为代价。
记忆单元支持赛题要求的六类内容(中间结果 / 摘要 / 经验 / 证据链 / 结论 / 策略), 每条强制五项元数据(记忆 ID、来源 Agent、创建时间、任务主题、摘要描述), 缺一即被 schema 拒绝写入。
赛题考核的是机制,但机制要有真实负载才能证明自己站得住。因此我们把 MACC 做成了一个能实际干活的 Agent 桌面端 —— 它的记忆层、通信层、执行层 就是上面三套机制本身。
fs_read
fs_write
fs_edit
fs_delete
fs_list
fs_grep
workspace_tree
python_exec
shell_run
web_search
web_fetch
doc_parse
git_status
git_diff
git_log
git_add
git_commit
memory_search
memory_write
插件可再注册工具(内置示例插件提供 notes_append)。
notes_append
readonly
strict
approve
trusted
auto
yolo
admin
即便在 yolo 档,仍有三条无条件拦截:路径含空字节、删除工作区根、 删除文件系统根。”完全放开”不等于”允许自毁”。 两处切换入口(「对话」页右下角与「工作区」页)双向同步。
PDF(带页码)· Word · Excel · PowerPoint · 图片 · 音频 · 音频元数据标签 · 视频 · 视频关键帧 · 文本/代码 · CSV · JSON。
能力边界如实声明:音频的曲目识别依据是 ffprobe 读出的 ID3 等元数据标签, 不是波形识别 —— 本项目所用网关的 18 个模型中没有任何音频模型。 文件不带标签时,正文会明确写”当前模型不具备音频波形识别能力, 无法据音频内容判定曲目”,不猜。这条有专门测试钉住。
「Skills / 插件」页贴入 git 链接后自动去抖检索(450 ms),有效才点亮 Install, 无效在下方黄字说明原因 —— “能不能装”在点击之前就已知。
Install
检索不做整仓克隆:先 git ls-remote 确认可达,再做 blobless 无检出克隆取文件清单 判定类型(整仓克隆动辄数十 MB,而检索是交互动作必须快)。 归类按仓库实际内容而不是按用户填进哪个框:plugin.json 声明了非空 tools 才算工具插件,只有 SKILL.md 则按技能包安装,两者皆无判为无效。 把技能包填进 Plugin 框也能装成,但界面会如实标注「技能包,无可调用工具」—— 不虚构不存在的工具,也不粗暴拒绝用户的输入。
git ls-remote
plugin.json
tools
SKILL.md
安装物落在 var/extensions/(已 gitignore),不混进参赛作品仓库; registry.json 记录 url / commit / 许可 / 条目清单,评审 clone 后可据此复现安装。 社区技能包正文实测可达 42,362 字(≈8.5 万 token),因此注入时按 6,000 字截断 并给出文件路径供模型按需 fs_read 读全文(实测 10,127 → 1,656 token)。
var/extensions/
registry.json
对话内调用:Skill list ▾ / Plugin list ▾ 选一项 → Invoke → 输入框插入高亮的 @skill:名称。显式引用优先于关键词自动匹配 —— 用户点选了哪个就用哪个,不让匹配算法再猜一次;引用了不存在的名字会被如实指出, 而不是静默忽略让用户误以为技能已生效。
Skill list ▾
Plugin list ▾
Invoke
@skill:名称
五类角色(研究 / 编码 / 测试 / 文档 / 审查),支持流水线与并行两种拓扑, 每个角色可填独立任务描述(留空回落到共同目标)。主/子 Agent 之间走 ACP 协议通信 —— 实测三个子 Agent 协作产出三份报告,ACP 侧仅 6 条消息 / 4,192 字节 / 0 prompt token。这是三套机制在真实负载下的直接体现。
python -m macc.cli doctor # 环境自检(Python/共享内存/可选依赖/凭据连通性) python -m macc.cli smoke # 14 项冒烟检查 python -m macc.cli agent-smoke # Agent 侧 18 项全栈冒烟(离线) python -m macc.cli demo # 六步演示(录屏用) python -m macc.cli run --topic billing --goal "定位异常账单科目" python -m macc.cli run --mode text --json # 纯文本基线模式 python -m macc.cli bench --rounds 12 --seed 20260729 --out reports/latest python -m macc.cli memory list|search|stats --query "账单科目错配" python -m macc.cli agent "把工作区里的 CSV 汇总成日报" # 命令行版 Agent python -m macc.cli desktop # 启动桌面客户端 MACC Studio python -m macc.desktop # 同上(桌面端直接入口)
常用开关:
--mode structured
run
bench
--seed N
--json
--workspace PATH
agent
desktop
--permission MODE
--max-steps N
--attach PATH
桌面端的工作区可以在界面里随时切换(顶栏胶囊 / 📁 打开文件夹… / 最近 ▾), 不需要重启;切换会一起换掉工作区闸门、沙箱 cwd、工具注册表与编排器,并自动新建会话。
也可用 Makefile:make doctor|test|smoke|bench|demo|lint|verify|clean
make doctor|test|smoke|bench|demo|lint|verify|clean
3 组关联任务族 × 4 轮 = 12 轮连续任务(满足”≥10 轮”要求):
logaudit
codereview
任务族内有关联是关键:只有后续任务确实需要前序产物,记忆复用才有意义。 如果任务两两独立,命中率再高也说明不了什么。
关于基线公平性:纯文本基线不是稻草人,它就是主流做法 —— 自然语言消息体、 每轮重发全量上下文、向量序列化进文本、无记忆检索。两侧共用同一套 Agent、 同一个引擎、同一份语料、同一随机种子、同一 DAG。差异只来自这三套机制。
wire_bytes
text_tokens
cl100k_base
messages
tensor_transfers
tensor_bytes
memory_hit_rate
memory_hits / memory_lookups
recompute_skipped
steps_executed
wall_ms
可复现性:同种子两次运行,messages/text_tokens/wire_bytes/ tensor_transfers/memory_hits 等十项指标完全相等,由回归测试断言。
memory_hits
这条断言曾经真的抓到过缺陷:Executor 一度把沙箱的墙钟耗时(67~79 ms 抖动) 写进了消息载荷,导致文本模式下 wire_bytes 随机差 2 字节 —— 表面上像测试抖动,实际是可复现性被破坏。修复后 12 轮验证从 3 次不一致降为 0 次。 判断依据是失败是否与机器负载相关:可复现性断言在空载下也失败,就一定是代码问题。
12 轮 / 3 任务族 / 种子 20260729 / tiktoken 精确计量。 原始数据 reports/latest/report.json, 图表报告 reports/latest/report.html:
reports/latest/report.json
关于耗时,必须如实说明。 本次 12 轮里结构化模式端到端慢了 3.96%(54 ms)。 拆开看就清楚了:两种模式跑了同样 6 次沙箱执行,而沙箱耗时差恰好也是 54 ms —— 也就是说这点差异全部落在沙箱子进程的墙钟抖动上,与三套机制无关。 剔除沙箱后的协作层反而快了 11.11%(复用整步跳过省下的时间超过了检索开销)。 即便如此,我们也不把它写成”时延下降 11%”: 记忆检索本身确实是新增开销(约 0.8 ms/轮),不应隐藏; 而端到端时延的方向依赖平台与负载(Windows 与 openEuler 容器上符号相反)。 因此本项目不宣称通用时延下降,只宣称跨平台一致成立的三项: **字节 ↓80%、token ↓100%、重复计算步数 ↓22%**。
轮次越多,复用效应越明显:24 轮时命中率 85.00%、跳过重算 40 次、 执行步数 ↓27.78%、线上字节 ↓81.98%。详见 docs/08-experiment-report.md。
其中 Agent 桌面端相关 379 个(含 GUI 层 114 个,无显示环境下亦可跑)。 另有 12 个 live 标记用例需真实模型,默认不执行(pytest -m live 单独跑)。 用例数不是手写在文档里的 —— 由 tools/count_tests.py 采集到 reports/latest/testcount.json,并有测试断言《项目说明书》里的数字与采集值一致。 说明书定稿时的采集快照为 1,593 个,其后又补入 4 个交付物校验用例, 当前工作树 pytest --collect-only 为 1,597 —— 两个数字都是真的, 差异就是这 4 个用例,此处一并说明以免被当作笔误。
pytest -m live
tools/count_tests.py
reports/latest/testcount.json
pytest --collect-only
import os
eval
().__class__.__bases__[0].__subclasses__()
.docx
tools/lint.py
赛题条款已逐条拆成 R-01 ~ R-35 可测需求,每条都绑定实现模块与测试文件, 由 tests/test_traceability.py 机器校验 “需求 ↔ 模块 ↔ 测试”三者不脱节;tools/check_docs.py 另行校验文档里的编号无遗漏。 按赛题「具体要求」归并如下:
tools/check_docs.py
runtime/broker.py
config.py
eval/harness.py
--mode text/structured
memory/unit.py
eval/tasks.py
eval/metrics.py
eval/reporter.py
runtime/session.py
transport/
sandbox/
setrlimit
「关于」页内置同一张自查表,可在桌面端现场逐条点开核对。
工程里没有免费的选择。这里列出几个可能被质疑的决定和我们的理由 —— 包括被否掉的方案,因为否掉的原因往往比选中的理由更能说明问题。
LLMEngine
dnf
data['tried']
核心运行时零第三方依赖 —— 只用 Python 标准库 (multiprocessing.shared_memory、socket、sqlite3、array、struct、 zlib、ast)。可选增强(Python 包与系统工具)缺失时自动降级:
multiprocessing.shared_memory
socket
sqlite3
array
struct
zlib
ast
numpy
tiktoken
pytest
python-docx
python-pptx
certifi
ffmpeg
ffprobe
“自动降级”是有测试保障的:关键路径都有在无可选依赖环境下运行的用例, 确保降级后结果一致而不是悄悄出错。requirements-optional.txt 列出可 pip 安装的包, 但评审复现完全不需要装它们。
requirements-optional.txt
默认不接大模型:赛题考核系统层机制,而 LLM 采样噪声会淹没 A/B 信号。 默认使用确定性引擎保证离线可复现;LLMEngine(OpenAI 兼容)已实现, 配置 base_url + api_key 即可切换,缺凭证直接报错不静默降级。
base_url
api_key
另有 项目说明书.pdf、原创承诺书.pdf、 演示PPT.pptx 三份提交材料在根目录(.docx/.pptx 为可编辑源文件)。
.pptx
1. .env 填对了但一直 401 / “调用模型失败”。 shell 里可能残留一个失效的旧 OPENAI_API_KEY —— 真实环境变量会覆盖 .env (刻意设计的优先级)。排查:
echo $env:OPENAI_API_KEY # 有值就是它在遮挡 $env:OPENAI_API_KEY='' # 清掉,让 .env 生效 python -m macc.cli doctor --require-llm
doctor 会真的打一次接口并在 401 时直接提示这条遮挡关系。
2. doctor 报 HTTP 502 / 503,说”凭据连通性 失败”。 先看 /models 通不通 —— 通了就不是凭据问题。实测同一 key、同一端点, 换个模型即可用(gpt-5.6-sol 返 502,而 gpt-5.6-terra、claude-opus-5 正常), 故障在网关侧。在 .env 里改 MACC_LLM_MODEL=<可用模型名> 即可。 只有 404 才需要核对端点与模型名。这不影响机制验证部分 —— 那部分默认离线运行。
/models
gpt-5.6-sol
gpt-5.6-terra
claude-opus-5
MACC_LLM_MODEL=<可用模型名>
3. 桌面端起不来,报找不到 Tk。 sudo dnf install -y python3-tkinter(openEuler / RHEL 系)。 命令行部分不需要 Tk,机制验证与全部实验照常可跑。
4. doctor 说共享内存不可用。 容器没挂 /dev/shm 或给得太小,加 --shm-size=256m。 宿主机上一般不会出现。
5. 联网检索返回”没有检索到结果”。 免费检索入口按 IP 限流。已用三源冗余覆盖(DuckDuckGo 镜像 → DDG Instant Answer API → Wikipedia API),单源被挡不影响使用,界面也不会冒红字。 三源同时不可用时会如实说明并给出替代方案(换关键词,或已知网址直接用 web_fetch)。
6. 某个性能测试偶发擦线失败。 test_codec_roundtrip_p95_under_one_ms[cjson] 在高负载机器上可能测到 1.009 ms。 单独重跑确认即可,不要因此调阈值。 反过来说,可复现性类断言在空载下也失败就一定是代码缺陷 —— 这个区分我们踩过坑,写在了 handoff.md。
test_codec_roundtrip_p95_under_one_ms[cjson]
7. 我想看看不装任何可选包是什么效果。 python -m macc.cli doctor 会列出每个可选包的安装状态与缺失时的降级方式。 全部不装也能跑完 smoke / bench / pytest,只是 token 计量转为估算、 向量运算走纯 Python。
smoke
如实列出,不当 bug 修:
全部代码为本队原创,未引用任何第三方开源项目的源代码。 BM25、余弦相似度等为公开算法,按公式自行实现。 numpy / tiktoken / pytest / python-docx / python-pptx 仅作为可选依赖 通过公开 API 调用,未复制其源码。详见项目说明书「代码原创说明」章节。
这一声明不只是文字承诺,还有机器守卫: tools/originality_check.py 从他方版权声明(许可证里出现非本队的 Copyright 持有者)与异种技术栈(go.mod / Gemfile / Cargo.toml 等)两个角度扫描仓库, 并接入 tests/test_deliverables.py::test_no_third_party_source_in_repo。 新增第三方内容必须写进该工具的 ALLOWED 并说明理由, 而不是把检查关掉。
go.mod
Gemfile
Cargo.toml
tests/test_deliverables.py::test_no_third_party_source_in_repo
Apache License 2.0
版权所有:中国计算机学会技术支持:开源发展技术委员会 京ICP备13000930号-9 京公网安备 11010802047560号
MACC — 面向多智能体协作的低开销通信、状态传递与共享记忆机制
MACC(Multi-Agent Collaboration Core)为多智能体协作提供系统层基础设施: 用结构化协议替代自然语言通信、用共享内存直接传递中间状态、用可检索记忆实现跨任务复用。
它不是又一个 Agent 编排框架。现有框架解决的是”如何组织 Agent”, MACC 往下一层,约束消息如何编码、状态如何传递、结果如何复用 —— 这三件事恰好都是操作系统层面的老问题:序列化开销、进程间数据搬运、缓存与复用。 我们把它们放回系统层解决,而不是继续堆在 prompt 里。
macc/18,743 行 ·tests/14,547 行目录:演示视频 · 30 秒跑起来 · 给评审的复核路径 · 三端形态 · 仓库结构导览 · 解决什么问题 · 相关工作与差异定位 · 系统架构 · 三套机制怎么工作 · Agent 桌面执行环境 · 命令清单 · 实验设计 · 完整实测数据 · 工程质量 · 赛题符合性对照 · 关键设计取舍 · 依赖 · 文档 · 常见问题 · 已知限制 · 原创性说明
演示视频
演示视频为一次完整演示的连续录制,分三段存放, 请按 1 → 2 → 3 的顺序连续观看(三段合计 14:41)。 文件已随仓库提交在根目录,可直接下载:
分段只是为了控制单文件体积,内容前后衔接、不可跳看 —— 后一段的操作建立在前一段已完成的状态之上(例如已安装的扩展、 已积累的会话与记忆、已产出的工作区文件)。
三段以桌面客户端实机运行为准,整体覆盖:多轮对话与会话管理、 长短期记忆与上下文压缩、多模态解析(PDF / 视频 / 图片 / 音频)、 工具调用、工作区文件读写与执行、Skills 与 Plugins 的安装管理及对话内调用、 三个子 Agent 分工协作,以及赛题三套机制(ACP / STX / SMEM)的验证视图。
三个文件均在赛事 100 MB/文件 的上限内,未使用 Git LFS。 其中视频 1 与视频 3 的原始录屏分别为 263 MB 与 77 MB,超过上限, 已用 tools/compress_video.py 压缩: 保持原 2560×1600 分辨率不缩放(屏幕录制需保证界面文字可读), 仅提高 CRF 与降低音频码率,抽样 SSIM 0.996,肉眼无差异。 视频 2 本身未超限,未做压缩。
演示脚本与逐步操作见 docs/09-demo-script.md。
30 秒跑起来
openEuler 24.03-LTS-SP3 自带 Python 3.11,无需安装任何第三方包:
桌面端需要 Tk 支持;openEuler 上一条命令即可:
sudo dnf install -y python3-tkinter。 命令行部分不需要 Tk。完成后打开
reports/latest/report.html查看全部对比数据与图表。 一键复现全流程:sh scripts/run_all.sh环境要求
/dev/shm可写--shm-size=256m,否则 STX 降级dnf install python3-tkinterdoctor会把上面每一项逐条检查并打印结论,末行输出DOCTOR OK。 它同时会真的调一次模型接口验证凭据连通性(离线环境可加--no-llm-probe跳过, 录屏或正式演示前建议加--require-llm强校验)。配置大模型(可选)
复制
.env.example为.env,填入OPENAI_BASE_URL/OPENAI_API_KEY/MACC_LLM_MODEL。任何 OpenAI 兼容端点均可。给评审的复核路径
本项目所有对外声明的数字都可以在本地当场复核,报告中没有任何手工填写的数值。 下表给出”主张 → 命令 → 预期输出”的一对一映射,全程离线、约 5 分钟:
python -m macc.cli doctorDOCTOR OKpython -m macc.cli smoke[PASS]+SMOKE OK (14/14 项通过)python -m macc.cli agent-smoke[OK]+AGENT SMOKE OK (18/18 项通过)python -m macc.cli demopython -m macc.cli bench --rounds 12 --seed 20260729reports/latest/,数字与本文一致diff两份report.jsonpython -m macc.cli memory search --query "账单科目错配"matched_by归因python -m pytest tests -qpassed(live标记的 12 个默认不跑)python tools/check_docs.pyDOCS OK(模块/命令/指标名/交付文件四类一致性)python tools/originality_check.pypython tools/anonymity_check.pyANONYMITY OK一条命令跑完全部:
sh scripts/run_all.sh,或make verify。我们也把不利数据留在了报告里。 例如协作层新增的记忆检索开销(约 0.8 ms/轮)、 端到端时延方向随平台变化、LoCoMo 上与 BM25 的差异未达统计显著 —— 这些都写在正文而不是脚注,理由见已知限制。
三端形态
python -m macc.desktoppython -m macc.cliimport macc桌面端是一个完整的 Agent 桌面执行环境(对标 ChatGPT Desktop / Claude Desktop / Trae / 通义灵码 一类产品),同时保留赛题机制的验证视图。左侧导航共 12 个页面, 分成”Agent 能力”与”机制验证”两组:
matched_by归因Agent 侧七层架构齐备:多轮会话与 Session 管理、长短期记忆(含上下文压缩与跨会话引用)、 ReAct 推理行动循环、17 个工具(+记忆读写共 19)、工作区四档权限(默认 YOLO 完全放开,等价 Codex YOLO / Claude Code
--dangerously-skip-permissions)、 多模态解析(PDF/Word/Excel/PPT/音视频/图片,带页码与时间点定位)、 Skills 与 Plugins、五类子 Agent 编排。 详见 docs/14-agent-desktop-guide.md。关键设计:Agent 的长期记忆直接建在本项目 SMEM 之上;主/子 Agent 通信走 ACP 结构化协议(二进制、0 prompt token);代码执行走 CodeAct 沙箱 —— 赛题三套机制 在这里从”被展示”变成”被真实使用”。这一点值得强调:如果三套机制只是跑在评测脚本里, 它们的价值就只能靠数字说明;而当整个桌面端的记忆、通信、执行都压在它们身上时, “能用”本身就是一条证据。
运行截图见 docs/screenshots/(25 张:机制验证 16 张 + Agent 9 张, 均由脚本驱动真实窗口抓取并做内容去重校验 —— 有测试断言任意两张截图内容不得相同, 防止把过期画面当证据)。
仓库结构导览
interface/为参考用的外部项目,不属于 MACC 运行时,未被本项目任何代码引用, 已在tools/originality_check.py的ALLOWED中登记并注明理由。解决什么问题
赛题指出当前多 Agent 系统的三个痛点。MACC 针对每一个给出一套系统层机制:
(12 轮连续任务,种子 20260729,tiktoken 精确计量。24 轮时命中率升至 85.00%、执行步数 ↓27.78%)
为什么”少发 token”不等于”少办事”。 降开销最容易的做法是少传信息, 代价是答案变差 —— 那样的对比毫无意义。所以我们把”质量守恒”做成了断言: 端到端测试要求两种模式对同一任务产出的结论签名完全一致。 省下的 80% 字节和 100% token,没有以答案质量为代价换来。 这条断言在 tests/e2e/ 里,每次提交都会跑。
相关工作与差异定位
MACC 与现有工作并非只在单一算法指标上竞争,而是把控制面协议、数据/状态面载体、 知识面记忆复用统一进一个可在 openEuler 上执行和测量的运行时。相关工作的能力边界 与直接比较范围如下;完整论述、引用和实验口径见 technical supplement.pdf。
TensorRef生命周期,并计入发布、校验、传输和物化的端到端成本;Arrow 是本项目公开复现的 carrier baseline公平比较边界:
nl/json/cjson/acp1使用相同任务、Agent、DAG 和运行环境,属于 协议层同条件基线;Apache Arrow 属于状态载体同条件基线;SILO-BENCH 使用 Level-I exact-oracle replay 检查通信正确性和开销,不表述为完整端到端 SOTA 复现。 LoCoMo 的 1,977 个可评测问题上,MACC hybrid Recall@5 为 0.4977、BM25 为 0.4883,但 conversation-cluster 配对置信区间跨越 0,因此结论是“在显著降低 full-history 载荷的同时保持有竞争力的检索质量”,而不是“统计显著全面优于 BM25”。系统架构
对应赛题「具体要求 9」的五大模块:多 Agent 运行时(
runtime/+agents/)、 协议解析与调度(protocol/+runtime/scheduler.py)、状态交换(state/)、 共享记忆存储与检索(memory/)、评测(eval/)。一轮任务在系统里怎么流动
以任务族
billing的第 2 轮「生成根因报告」为例,一次完整往返如下 —— 每一步都能在「协作时间线」页看到对应的消息条目:纯文本基线模式(
--mode text)走的是同一条路径、同一套 Agent、同一个 DAG, 只把③的编码换成自然语言长文本、⑤的向量序列化进文本、④的记忆检索关掉。 差异只来自这三套机制 —— 这是整套 A/B 对比可信的前提。三套机制怎么工作
1. ACP 结构化协议
一条消息把协作信息收敛为四个语义单元,大块数据只传引用:
同一条逻辑消息的四种线上形态(
macc.cli demo可现场复现):nljsoncjsonacp1acp1的 prompt token 为 0 不是取巧:结构化模式下 Agent 间不再经过语言模型 的上下文窗口,消息直接在运行时之间流动,因此没有任何 token 被消耗。 这也正是赛题要求”不得仅用自然语言长文本透传”的直接体现。协议层强制执行这条要求:内联数值数组超 16 个元素、 单字段文本超 512 字符一律被
validate()拒绝 —— 这是代码级约束,不是口头承诺。 想绕过它就得改macc/protocol/schema.py并让相应测试变红。为什么保留
nl与文本映射器? 因为可观测性不能牺牲。mapper提供结构化 ⇄ 自然语言的双向映射并有往返语义等价测试:调试时人能读,运行时机器传二进制。 二者不是二选一。2. STX 非文本状态传递
已验证:张量 8 → 8000 元素(放大 1000 倍),消息大小差 < 16 字节; 子进程仅凭句柄即可读出父进程张量(含切片视图);引用计数归零自动 unlink; 12 轮后零泄漏。
这里省掉的不只是字节,是两次格式转换。 传统做法把 embedding 序列化成文本 再由下游解析回浮点数,一来一回既耗 CPU 又损精度;共享内存路径下, 下游拿到的就是同一块物理内存上的
memoryview,没有拷贝、没有解析、没有精度损失。 本次实验中基线为此内联了 2,668 个字符的向量文本,结构化模式为 0。安全性同样被钉住:段名注入、越界句柄、CRC 篡改、超大帧声明都有专门的拦截测试 —— 共享内存是把双刃剑,暴露物理内存就必须假定句柄可能是恶意的。
3. SMEM 共享记忆
每条命中带
matched_by归因,可解释”为什么被召回”。复用要过三道门: 分数达阈值、任务主题相关、content含必备键。三档结论REUSE(跳过计算)/AUGMENT(作提示但仍计算)/RECOMPUTE。三道门是必要的,不是保守。 只看相似度分数会把”看起来像”的记忆当成”能用”, 一旦复用了不该复用的中间结果,错误会沿任务链传播且难以定位。 所以门控除了分数,还要求主题相关且
content里确实有下游需要的键 —— 宁可退回AUGMENT(拿来当提示但照样算一遍),也不赌一次。AUGMENT这一档的存在本身就是承认:检索到了不等于可以跳过。质量守恒的证据:端到端测试断言两种模式对同一任务产出的结论签名完全一致 —— 省下的开销没有以答案质量为代价。
记忆单元支持赛题要求的六类内容(中间结果 / 摘要 / 经验 / 证据链 / 结论 / 策略), 每条强制五项元数据(记忆 ID、来源 Agent、创建时间、任务主题、摘要描述), 缺一即被 schema 拒绝写入。
Agent 桌面执行环境
赛题考核的是机制,但机制要有真实负载才能证明自己站得住。因此我们把 MACC 做成了一个能实际干活的 Agent 桌面端 —— 它的记忆层、通信层、执行层 就是上面三套机制本身。
工具清单(19 个 + 插件提供)
fs_readfs_writefs_editfs_deletefs_listfs_grepworkspace_treepython_exec(沙箱子进程)shell_runweb_search(三源冗余)web_fetchdoc_parse(PDF 带页码 / 音视频带时间点)git_statusgit_diffgit_loggit_addgit_commitmemory_searchmemory_write← 直接建在 SMEM 上插件可再注册工具(内置示例插件提供
notes_append)。四档权限 × 三档沙箱
readonlystrict(AST 白名单,32 种逃逸手法全拦)approvetrusted(30 个白名单模块)autotrustedyolo(默认)admin(无 AST 检查、完整 builtins、无限额)--dangerously-skip-permissions即便在
yolo档,仍有三条无条件拦截:路径含空字节、删除工作区根、 删除文件系统根。”完全放开”不等于”允许自毁”。 两处切换入口(「对话」页右下角与「工作区」页)双向同步。多模态解析(12 类)
PDF(带页码)· Word · Excel · PowerPoint · 图片 · 音频 · 音频元数据标签 · 视频 · 视频关键帧 · 文本/代码 · CSV · JSON。
Skills 与 Plugins:粘贴链接即可安装
「Skills / 插件」页贴入 git 链接后自动去抖检索(450 ms),有效才点亮
Install, 无效在下方黄字说明原因 —— “能不能装”在点击之前就已知。检索不做整仓克隆:先
git ls-remote确认可达,再做 blobless 无检出克隆取文件清单 判定类型(整仓克隆动辄数十 MB,而检索是交互动作必须快)。 归类按仓库实际内容而不是按用户填进哪个框:plugin.json声明了非空tools才算工具插件,只有SKILL.md则按技能包安装,两者皆无判为无效。 把技能包填进 Plugin 框也能装成,但界面会如实标注「技能包,无可调用工具」—— 不虚构不存在的工具,也不粗暴拒绝用户的输入。安装物落在
var/extensions/(已 gitignore),不混进参赛作品仓库;registry.json记录 url / commit / 许可 / 条目清单,评审 clone 后可据此复现安装。 社区技能包正文实测可达 42,362 字(≈8.5 万 token),因此注入时按 6,000 字截断 并给出文件路径供模型按需fs_read读全文(实测 10,127 → 1,656 token)。对话内调用:
Skill list ▾/Plugin list ▾选一项 →Invoke→ 输入框插入高亮的@skill:名称。显式引用优先于关键词自动匹配 —— 用户点选了哪个就用哪个,不让匹配算法再猜一次;引用了不存在的名字会被如实指出, 而不是静默忽略让用户误以为技能已生效。子 Agent 编排
五类角色(研究 / 编码 / 测试 / 文档 / 审查),支持流水线与并行两种拓扑, 每个角色可填独立任务描述(留空回落到共同目标)。主/子 Agent 之间走 ACP 协议通信 —— 实测三个子 Agent 协作产出三份报告,ACP 侧仅 6 条消息 / 4,192 字节 / 0 prompt token。这是三套机制在真实负载下的直接体现。
命令清单
常用开关:
--mode text/--mode structuredrun/bench)--seed N--json--require-llm/--no-llm-probedoctor是否强校验 / 跳过模型连通性--workspace PATHagent/desktop)--permission MODE--dangerously-skip-permissions等价yolo--max-steps N/--attach PATH桌面端的工作区可以在界面里随时切换(顶栏胶囊 / 📁 打开文件夹… / 最近 ▾), 不需要重启;切换会一起换掉工作区闸门、沙箱 cwd、工具注册表与编排器,并自动新建会话。
也可用 Makefile:
make doctor|test|smoke|bench|demo|lint|verify|clean实验设计
3 组关联任务族 × 4 轮 = 12 轮连续任务(满足”≥10 轮”要求):
billinglogauditcodereview任务族内有关联是关键:只有后续任务确实需要前序产物,记忆复用才有意义。 如果任务两两独立,命中率再高也说明不了什么。
关于基线公平性:纯文本基线不是稻草人,它就是主流做法 —— 自然语言消息体、 每轮重发全量上下文、向量序列化进文本、无记忆检索。两侧共用同一套 Agent、 同一个引擎、同一份语料、同一随机种子、同一 DAG。差异只来自这三套机制。
指标口径(怎么量的)
wire_bytestext_tokenscl100k_base精确计量;无 tiktoken 时退化为 CJK 感知估算并在报告中标注方式messagestensor_transfers/tensor_bytesmemory_hit_ratememory_hits / memory_lookups,只统计真实发起的检索recompute_skippedsteps_executedwall_ms可复现性:同种子两次运行,
messages/text_tokens/wire_bytes/tensor_transfers/memory_hits等十项指标完全相等,由回归测试断言。这条断言曾经真的抓到过缺陷:Executor 一度把沙箱的墙钟耗时(67~79 ms 抖动) 写进了消息载荷,导致文本模式下
wire_bytes随机差 2 字节 —— 表面上像测试抖动,实际是可复现性被破坏。修复后 12 轮验证从 3 次不一致降为 0 次。 判断依据是失败是否与机器负载相关:可复现性断言在空载下也失败,就一定是代码问题。完整实测数据
12 轮 / 3 任务族 / 种子 20260729 / tiktoken 精确计量。 原始数据
reports/latest/report.json, 图表报告reports/latest/report.html:关于耗时,必须如实说明。 本次 12 轮里结构化模式端到端慢了 3.96%(54 ms)。 拆开看就清楚了:两种模式跑了同样 6 次沙箱执行,而沙箱耗时差恰好也是 54 ms —— 也就是说这点差异全部落在沙箱子进程的墙钟抖动上,与三套机制无关。 剔除沙箱后的协作层反而快了 11.11%(复用整步跳过省下的时间超过了检索开销)。 即便如此,我们也不把它写成”时延下降 11%”: 记忆检索本身确实是新增开销(约 0.8 ms/轮),不应隐藏; 而端到端时延的方向依赖平台与负载(Windows 与 openEuler 容器上符号相反)。 因此本项目不宣称通用时延下降,只宣称跨平台一致成立的三项: **字节 ↓80%、token ↓100%、重复计算步数 ↓22%**。
轮次越多,复用效应越明显:24 轮时命中率 85.00%、跳过重算 40 次、 执行步数 ↓27.78%、线上字节 ↓81.98%。详见 docs/08-experiment-report.md。
工程质量
其中 Agent 桌面端相关 379 个(含 GUI 层 114 个,无显示环境下亦可跑)。 另有 12 个
live标记用例需真实模型,默认不执行(pytest -m live单独跑)。 用例数不是手写在文档里的 —— 由tools/count_tests.py采集到reports/latest/testcount.json,并有测试断言《项目说明书》里的数字与采集值一致。 说明书定稿时的采集快照为 1,593 个,其后又补入 4 个交付物校验用例, 当前工作树pytest --collect-only为 1,597 —— 两个数字都是真的, 差异就是这 4 个用例,此处一并说明以免被当作笔误。import os、eval、().__class__.__bases__[0].__subclasses__()等)全部在执行前被拒; 段名注入、越界句柄、CRC 篡改、超大帧声明均有拦截。report.json一致、PDF 是否比.docx旧、截图是否重复、 是否误提交大文件、是否用了 Git LFS —— 全部由测试把关,而非人工核对。tools/originality_check.py从”他方版权声明”与”异种技术栈” 两个角度扫描仓库。这条检查源于一次真实事故:某次提交误把一个 8.3 MB 的 Go 项目带进了仓库,而当时没有任何检查能发现它 —— 而说明书声称 “自创部分占代码总量的 100%”。检查是补上的,事故是记下来的。tools/lint.py除常规规则外,还限制单文件行数上限(1,200 行), 超限就必须拆分 —— 本项目有两个工具脚本因此被拆开。赛题符合性对照
赛题条款已逐条拆成 R-01 ~ R-35 可测需求,每条都绑定实现模块与测试文件, 由 tests/test_traceability.py 机器校验 “需求 ↔ 模块 ↔ 测试”三者不脱节;
tools/check_docs.py另行校验文档里的编号无遗漏。 按赛题「具体要求」归并如下:runtime/agents/protocol/runtime/broker.pyconfig.pyeval/harness.py--mode text/structured;十项指标同种子完全一致state/memory/unit.pymemory/eval/tasks.pyeval/metrics.pyeval/reporter.pyruntime/session.pytransport/state/sandbox/setrlimit「关于」页内置同一张自查表,可在桌面端现场逐条点开核对。
关键设计取舍
工程里没有免费的选择。这里列出几个可能被质疑的决定和我们的理由 —— 包括被否掉的方案,因为否掉的原因往往比选中的理由更能说明问题。
LLMEngine已实现,配置即切换,缺凭证直接报错不静默降级acp1二进制编码json/cjson/nl三种,任何人可换回来对比dnf即可AUGMENT中间档web_search用三源冗余,不换”更好的引擎”data['tried']里,排查时看那里fs_read读全文(已在提示里告知路径)依赖
核心运行时零第三方依赖 —— 只用 Python 标准库 (
multiprocessing.shared_memory、socket、sqlite3、array、struct、zlib、ast)。可选增强(Python 包与系统工具)缺失时自动降级:numpyarray+ 纯 Python,结果一致tiktokenpytestpython-docx/python-pptxcertifiweb_fetch对少数站点报证书错误ffmpeg/ffprobe“自动降级”是有测试保障的:关键路径都有在无可选依赖环境下运行的用例, 确保降级后结果一致而不是悄悄出错。
requirements-optional.txt列出可 pip 安装的包, 但评审复现完全不需要装它们。默认不接大模型:赛题考核系统层机制,而 LLM 采样噪声会淹没 A/B 信号。 默认使用确定性引擎保证离线可复现;
LLMEngine(OpenAI 兼容)已实现, 配置base_url+api_key即可切换,缺凭证直接报错不静默降级。文档
另有 项目说明书.pdf、原创承诺书.pdf、 演示PPT.pptx 三份提交材料在根目录(
.docx/.pptx为可编辑源文件)。常见问题
1.
.env填对了但一直 401 / “调用模型失败”。 shell 里可能残留一个失效的旧OPENAI_API_KEY—— 真实环境变量会覆盖.env(刻意设计的优先级)。排查:doctor会真的打一次接口并在 401 时直接提示这条遮挡关系。2.
doctor报 HTTP 502 / 503,说”凭据连通性 失败”。 先看/models通不通 —— 通了就不是凭据问题。实测同一 key、同一端点, 换个模型即可用(gpt-5.6-sol返 502,而gpt-5.6-terra、claude-opus-5正常), 故障在网关侧。在.env里改MACC_LLM_MODEL=<可用模型名>即可。 只有 404 才需要核对端点与模型名。这不影响机制验证部分 —— 那部分默认离线运行。3. 桌面端起不来,报找不到 Tk。
sudo dnf install -y python3-tkinter(openEuler / RHEL 系)。 命令行部分不需要 Tk,机制验证与全部实验照常可跑。4.
doctor说共享内存不可用。 容器没挂/dev/shm或给得太小,加--shm-size=256m。 宿主机上一般不会出现。5. 联网检索返回”没有检索到结果”。 免费检索入口按 IP 限流。已用三源冗余覆盖(DuckDuckGo 镜像 → DDG Instant Answer API → Wikipedia API),单源被挡不影响使用,界面也不会冒红字。 三源同时不可用时会如实说明并给出替代方案(换关键词,或已知网址直接用
web_fetch)。6. 某个性能测试偶发擦线失败。
test_codec_roundtrip_p95_under_one_ms[cjson]在高负载机器上可能测到 1.009 ms。 单独重跑确认即可,不要因此调阈值。 反过来说,可复现性类断言在空载下也失败就一定是代码缺陷 —— 这个区分我们踩过坑,写在了 handoff.md。7. 我想看看不装任何可选包是什么效果。
python -m macc.cli doctor会列出每个可选包的安装状态与缺失时的降级方式。 全部不装也能跑完smoke/bench/pytest,只是 token 计量转为估算、 向量运算走纯 Python。已知限制
如实列出,不当 bug 修:
setrlimit资源限额。原创性说明
全部代码为本队原创,未引用任何第三方开源项目的源代码。 BM25、余弦相似度等为公开算法,按公式自行实现。
numpy/tiktoken/pytest/python-docx/python-pptx仅作为可选依赖 通过公开 API 调用,未复制其源码。详见项目说明书「代码原创说明」章节。这一声明不只是文字承诺,还有机器守卫:
tools/originality_check.py从他方版权声明(许可证里出现非本队的 Copyright 持有者)与异种技术栈(go.mod/Gemfile/Cargo.toml等)两个角度扫描仓库, 并接入tests/test_deliverables.py::test_no_third_party_source_in_repo。 新增第三方内容必须写进该工具的ALLOWED并说明理由, 而不是把检查关掉。许可
Apache License 2.0