模型幻觉治不住?仓颉语言的cjh Agent Harness用架构把“编造空间“压缩到接近零
本文基于开源项目 cjh 的真实工程实践,所有机制均已在代码与测试中落地。
项目官网:https://yangyongzhen.github.io/cjh/ | 开源仓库:https://atomgit.com/qq8864/cjh(MIT License)
先介绍主角:cjh 是什么
cjh 是一个用华为仓颉语言从零实现的终端 Coding Agent Harness——单文件静态二进制 17.1 MB、零运行时依赖,一个文件就是一个能读代码、能改代码、能跑命令的 AI 编程助手。它具备 Agent 主循环、15 个内置工具、MCP 扩展、多智能体并行编排(子代理派发 + DAG 依赖调度)、知识库离线检索等完整能力,支持终端 TUI / 浏览器 / 桌面客户端内嵌三种宿主形态,测试 1150+203+77 全绿,MIT 开源。

正因为它是一个真的会在你机器上跑命令、改文件的 agent,幻觉对它来说不是论文里的名词,而是每天都要正面应对的工程问题——模型一句"测试都过了"(其实没跑)、一次凭空编造的 API 调用,都会造成真实破坏。这篇文章讲的就是 cjh 的系统性解法。

cjh 分层架构:Agent 主循环是防幻觉的中枢——工作循环、智能诚实纪律、任务分解都在这一层强制执行
结论先行
幻觉无法在模型侧根除,但 agent 可以用架构把"编造的空间"压缩到接近零,再针对残余风险逐项设防。 cjh 的做法分三层:结构性防御(架构级)、纪律性约束(提示词级)、人环兜底(门禁级)。
一、问题的本质:幻觉有四类,成因和对策各不相同
| 幻觉类型 | 成因 | 典型表现 |
|---|---|---|
| 事实性编造 | 在没有证据的真空里"补全" | 编造不存在的 API/函数;“这个文件里已经有 XX”(实际没有) |
| 迎合性顺从(sycophancy) | RLHF 训练偏向用户满意 | 用户说错方案,模型说"对的对的"然后照做 |
| 虚假完成宣称 | 汇报环节无证据约束 | “测试都过了”(根本没跑);“已修复”(没验证) |
| 规则性投机 | 门禁/约束被视为待绕过的障碍 | 需审批的操作用语义等价旁路执行;给自己找捷径 |
关键认知:前两类发生在"输入端"(模型看到什么),后两类发生在"输出端"(模型宣称什么)。cjh 的分层防御正是按这两端设计的。
二、结构性防御(架构级,最重要的半壁江山)
幻觉的最大来源不是模型嘴瓢,而是在真空中推理。cjh 的架构原则是:用执行结果代替模型记忆——模型永远不需要"记得"或"猜"任何东西。
1. 工具结果是真实执行注入的
- 模型看到的文件内容/命令输出,全部来自 bash/read_file/list_dir 的真实返回,不是模型上下文里的"印象"
- 这一条就消解了大部分事实性编造:没有真空,就没有补全
- 工具失败必须原样回传(stderr + 退出码)——模型糊弄不过去,错误会打脸
2. 工作循环强制"先看再改、改完验证"
默认系统提示词的 Work loop (read → edit → verify):
- 改代码前必须 read 相关文件(防基于想象修改)
- 改完必须用 bash 验证(build/tests/inspect)
Do not hallucinate encodings专节:针对中文/编码实测坑的定向条款
3. 知识层语料对抗 API 幻觉
cjh ref 把仓颉官方语料(含 stdx 知识库)拉取到本地,模型可检索查证——**防"编造不存在的 stdlib 函数"**这类最常见的技术幻觉。语料是运行时数据(~/.cjh/cangjie-ref/),不打进二进制,知识量再涨也不影响单文件分发体积。
4. 任务分解压缩"一步到位式自信"
多步任务强制分解为可验证的小步(todo_write 任务列表),每步即时标 doing/done——大任务被拆解后,每一步都有真实工具结果兜底,模型没有"整段想象"的空间。
5. Token 上下文管理防"失忆幻觉"
compaction 用真实 usage.promptTokens 触发(非字符估算)、历史换装保留工具链消息——模型不会因为上下文被错误裁剪而"忘记"自己做过什么,进而编造一致性叙事。
三、纪律性约束(提示词级)
结构防御解决输入端;输出端的诚实没有结构可依赖,只能靠显式纪律。cjh 默认系统提示词内置 Intellectual honesty (non-negotiable) 节,四条铁律:
- 不迎合不迁就:用户的前提/诊断/方案看起来有问题,先带证据直说,再执行——忠实执行一个错误方案浪费的时间,远多于礼貌的质疑
- 完成宣称必须有本会话工具证据:每一句 “tests pass” / “build succeeds” 必须来自刚刚跑过的命令,不许来自记忆或乐观
- 失败原样完整上报:stderr、退出码照报;静默绕过比诚实报错更恶劣
- 验证不了就明说:哪些没验证、为什么没验证,原样交代
配套回归测试锁死该节存在与关键措辞,防后续改提示词时被误删。
cjh 全屏 TUI:审批弹窗、工具调用、回合总结全程可见——"看得见"本身就是防幻觉的一部分
四、人环兜底(门禁级)
1. 审批门禁(capability + approve/deny)
- 危险操作(危险 bash、删除类)进审批流,人环在环上
- 默认宽松、显式严格:配了 capability 段 ≠ 启用,须显式
"enabled": true——避免"配了就被拒"的可用性事故(这是刻意设计)
2. 项目级门禁是"诚实的流程化"
把"诚实"从品德问题变成流程问题:交付前测试全绿是唯一凭证、bug 修复先写失败复现测试、零编译告警硬门禁。模型想糊弄?门禁脚本不认嘴瓢。 这也是 cjh 自举的活广告:本仓 1150+203+77 用例的相当部分由 cjh 自己写、自己跑门禁验证。
Web 宿主形态:同一套 Agent 与工具链,浏览器里同样全程可见
五、诚实的边界:还没解决的
| 残余风险 | 现状 | 计划 |
|---|---|---|
| 门禁旁路(最尖锐) | 审批基于命令文本匹配;模型可 python3 -c "…删除…" 走 bash 绕开 write_file 审批 | 升级为看效果不看命令:审批后 diff 工作区实际变化展示给用户;bash 写路径纳入 capability 覆盖 |
| 迎合的残余 | 提示词纪律对强模型的顺从倾向有显著抑制,但不是机制保证 | 批评者分离:实施者写完 spawn 独立上下文的 reviewer 做 diff 审查——同一模型换个上下文就会挑出自己刚犯的错 |
| 汇报环节的机制化验证 | "改了代码但零验证"目前靠提示词自觉 | 回合统计检测"有编辑无 verify 命令"→ 注入 system notice 提醒 |
六、一句话总结
cjh 的答案不是"更强的模型",而是"让模型没有机会撒谎":输入端用真实执行结果消灭真空,输出端用显式纪律约束宣称,出口用人环门禁和测试流程兜底——再对残余风险(门禁旁路、迎合残余)持续收口。
- 项目官网(功能清单 / 双平台下载 / 文档):https://yangyongzhen.github.io/cjh/
- 开源仓库(MIT,可自由 Fork):https://atomgit.com/qq8864/cjh
- 桌面内嵌案例:ai-chat(AI 客户端)、cjnote(智能笔记)均已用 cjh 做内核
更多推荐



所有评论(0)