AI多Agent协作系统实战(三十):一个换行符,毁了一张任务表
系列第30篇 | 统筹报告表格被"腰斩"之谜:

这个看不见的字符,牵出派发层、存储层、报告层三层连环bug
凌晨,报告长这样
我正在飞书上看统筹报告,突然发现表格不对劲:
| 1 | DEV-20260801-004 | 买方测试任务 【任务MD文件】请读取: /vol1/100 | ✅ | - | - | ⏳ | ... |表格被拦腰截断了。“完善内容"那一列,第一行写了个任务标题,下一秒莫名其妙换行,把”【任务MD文件】请读取"直接怼到了下一行,后面的状态列全被挤乱了。
这不是个例——我翻记录,发现至少七八个任务都是这个鬼样子:
FIX-0719-PC-SIDEBAR-COLLAPSE-FIX: 'PC端侧边栏折叠后两个问题:\n1. 只显示5个主菜单图标...' DEV-20260726-011: '修复im-chat.html折叠按钮位置和样式不一致\n\n【任务MD文件】请读取: ...'所有多行的summary,全在表格里炸了。而这个bug,躺了好几个月都没人发现——或者说,大家一直以为是"个别数据脏",从没想过是系统性问题。
第一个炸弹:一个看不见的换行符
先说结论:问题出在summary 字段里有换行符\n。
我们的派发流程是这样的:
创建任务MD(问题描述写好几行) ↓ send_task.py 派发 ↓ 从MD提取问题描述 → 存入DB的 summary 字段 ↓ format_report.py 生成表格 → 读取 summary问题出在第三四步之间。summary从MD的一整个章节里截出来的,如果章节里有多行内容,summary里就带着换行符。
但真正让我意外的是——这些换行符根本不是任务内容。看这行:
'修复im-chat.html折叠按钮位置和样式不一致\n\n【任务MD文件】请读取: /vol1/1000/w'后面那块"【任务MD文件】请读取"是哪来的?这是send_task.py在派发时,把额外提示文本拼进了content,而summary又从content/MD里提取,提取逻辑没过滤掉这些提示语。
于是summary就成了"任务内容 + 换行 + 无关提示"的缝合怪。
表面问题:换行符破坏表格。
隐藏问题:派发时把"给agent的操作提示"(【任务MD文件】请读取)混进了"任务内容"(summary),两个语义完全不同的东西被塞进了同一个字段。
第二个炸弹:为什么没人发现?
这个bug躺了几个月,是因为它只在summary恰好多行时才触发。
大多数任务的问题描述就一句话,summary单行,表格正常。偶尔有个多行的,表格就歪一次。这种"偶发"的失真,太容易被当成"那批数据脏了"——谁会想到是代码bug?
直到今天,我们看到一条干干净净的任务也长这样,才意识到:这不是数据脏,是管线里有病。
这让我想起运维圈的一句老话:“间歇性故障最危险,因为它让你习惯性忽略。”
第三个炸弹:修复远不止去掉换行
一开始我以为很简单——“把summary里的换行替换成空格不就行了?”
改完format_report,表格确实好了。但我盯着修复前后的diff,越想越不对劲:
我只在"显示层"打了补丁,但病根在"生成层"。
真正的病灶有三处:
- 生成层(send_task.py):summary从MD多行章节截取,没清理换行
- 存储层(DB):把换行符存进了本该单行的字段
- 显示层(format_report.py):表格拼字符串时没做防御
我只修了显示层,等于"流脓的伤口涂了层粉"。下次换个场景,summary又带着换行流到别处——比如通知消息、日志、导出文件。
真正的修复应该是:在summary写入DB之前就清洗干净,显示层再用统一的去换行兜底。双保险。
最深的一层:语义污染
修的过程中,我发现那个"【任务MD文件】请读取"才是更隐蔽的问题——它说明:
同一个字段,既装"任务内容"又装"给agent的操作提示"。
这是数据建模的坑。summary本意是"任务的一句话摘要",但派发逻辑图省事,把整个content(含提示)都塞进来了,提取时又没挑干净。
正确的做法是:summary只取"完善内容"或"问题描述"的第一行,操作提示(【任务MD文件】)是发给agent的指令,根本不该进summary。
经验总结
- 换行符是表格的隐形杀手——多行summary会让markdown表格"腰斩",且只在数据恰好多行时偶发
- 偶发故障最误导人——"这批次数据脏"的错觉,让管线bug躺几个月
- 修显示层不够,要修生成层——显示层打补丁是治标,生成层清洗是治本,双保险最佳
- 语义污染比格式问题更深——任务内容和操作提示混进同一字段,是数据建模的坑
- 排查多行表格问题:先看DB里summary是否含
\n,再查生成逻辑,别只改显示
一个看不见的换行符,让一张整洁的任务表分崩离析。而它沉默地躺了几个月——因为偶发,所以没人当真。真正的bug检查,从来不是等它连环爆炸,而是揪住每一个"小杂音"不放。
