What happened? / 问题描述
子智能体的单次响应若因模型输出上限被截断,最终状态仍是 completed,交付内容只是被截断的前半段。主智能体因此无法区分「真的做完了」与「写到一半被砍」。
- 环境:PI-Desktop
0.15.10,Windows 11,Electron 打包版。
- 触发条件与模型相关:使用的模型单次响应输出上限约 34k tokens。并非所有模型都会触发,这使得问题难以排查。
- 代码位置:
resources/agent-runtime/sidecar.js,子智能体运行时类 fae。
run() 的终态判定只检查「最后一条助手消息有没有文本」,从不检查 stopReason:
: this.lastReportText.trim()
? this.result("completed", this.lastReportText) // ← 有文本就算完成
: this.result("failed", "", { code: "SUBAGENT_NO_REPORT",
message: "The subagent finished without writing a report." })
lastReportText 的赋值同样忽略 stopReason:
r.hasText && r.text.trim() && !a && (this.lastReportText = r.text); // 流式处理中
this.currentAssistant.content.trim() && (this.lastReportText = this.currentAssistant.content);
Steps to reproduce / 复现步骤
- 选择一个单次响应输出上限较低的模型(本例约 34k)。
- 准备一个拥有全部工具的子智能体定义(
Read / Glob / Grep / Bash / Edit / Write)。
- 派发一个必然产生超长输出的任务,并在 brief 里明确要求它把完整分析直接写在报告里、不要写入任何文件。
- 用
TaskWait 取回结果。
- 用
ls / Read 核对报告里提到的产物是否存在。
Expected behavior / 预期行为
终态不应是 completed。应满足下列任一:
- 判为失败并带明确错误码(例如
SUBAGENT_OUTPUT_TRUNCATED);或
- 自动续跑一轮把报告补完;或
- 至少在结算载荷里带布尔标记(如
outputTruncated: true),或把截断标记注入报告首行使其可见。
Actual behavior / 实际行为
status = completed,report 在句子中间断掉、末尾没有收尾语。
turns / toolCalls 数值偏低,与「写了很长内容」的预期不符。
- 报告中声称的产物在磁盘上不存在(需事后自行
ls 才发现)。
关键的不对称:平台对工具调用被截断是有保护的 —— D1n 会插入显式错误并让循环继续:
async function D1n(t, e) {
... result: i_(`Tool call "${r.name}" was not executed: the response hit the output token limit,
so its arguments may be truncated. Re-issue the tool call with complete arguments.`),
isError: !0
return { messages: n, terminate: !1 }; // 不终止,循环继续
}
因此只有「响应带 tool call 且 stopReason === "length"」这条路被覆盖。纯文本被截断走不到它,于是静默变成 completed。
对照:平台自己的报告长度上限(12000 字符,H5t = 12e3)是可见的 —— 超出时保留首尾并插入 [subagent report truncated]。同样的可见性没有用在模型截断上。
App version / 应用版本
0.15.10
Operating system / 操作系统
Windows
Extra environment / 其他环境信息
No response
Logs / 日志
Screenshots / 截图
No response
What happened? / 问题描述
子智能体的单次响应若因模型输出上限被截断,最终状态仍是
completed,交付内容只是被截断的前半段。主智能体因此无法区分「真的做完了」与「写到一半被砍」。0.15.10,Windows 11,Electron 打包版。resources/agent-runtime/sidecar.js,子智能体运行时类fae。run()的终态判定只检查「最后一条助手消息有没有文本」,从不检查stopReason:lastReportText的赋值同样忽略stopReason:Steps to reproduce / 复现步骤
Read/Glob/Grep/Bash/Edit/Write)。TaskWait取回结果。ls/Read核对报告里提到的产物是否存在。Expected behavior / 预期行为
终态不应是
completed。应满足下列任一:SUBAGENT_OUTPUT_TRUNCATED);或outputTruncated: true),或把截断标记注入报告首行使其可见。Actual behavior / 实际行为
status = completed,report在句子中间断掉、末尾没有收尾语。turns/toolCalls数值偏低,与「写了很长内容」的预期不符。ls才发现)。关键的不对称:平台对工具调用被截断是有保护的 ——
D1n会插入显式错误并让循环继续:因此只有「响应带 tool call 且
stopReason === "length"」这条路被覆盖。纯文本被截断走不到它,于是静默变成completed。对照:平台自己的报告长度上限(12000 字符,
H5t = 12e3)是可见的 —— 超出时保留首尾并插入[subagent report truncated]。同样的可见性没有用在模型截断上。App version / 应用版本
0.15.10
Operating system / 操作系统
Windows
Extra environment / 其他环境信息
No response
Logs / 日志
Screenshots / 截图
No response