diff --git a/apps/web/app/components/agent/agent-conversation.tsx b/apps/web/app/components/agent/agent-conversation.tsx
index 68218be0..2f9d6512 100644
--- a/apps/web/app/components/agent/agent-conversation.tsx
+++ b/apps/web/app/components/agent/agent-conversation.tsx
@@ -196,7 +196,9 @@ function ToolRow({ call, audit }: { call: ToolCallView; audit?: InvocationAudit
const [open, setOpen] = useState(false);
const meta = capabilityMeta(call.capabilityId);
const denied = isDenied(call);
- const summary = denied ? deniedReason(call).text : toolSummary(call);
+ const raw = denied ? deniedReason(call).text : toolSummary(call);
+ // 旧会话的错误文字里带能力 ID / 原因码:和最终汇报一样换成能力标题与人话
+ const summary = raw ? humanizeReport(raw).text : raw;
return (
),
)}
diff --git a/apps/web/app/components/agent/agui3.test.ts b/apps/web/app/components/agent/agui3.test.ts
index df5e6380..18bac1ba 100644
--- a/apps/web/app/components/agent/agui3.test.ts
+++ b/apps/web/app/components/agent/agui3.test.ts
@@ -571,3 +571,24 @@ describe("进度行时长(FIX-9):从这一轮开始算到结论正文", () => {
expect(t).toMatch(/· 7 秒/);
});
});
+
+describe("步骤明细(FIX-9):能力 ID 换成能力标题", () => {
+ it("失败原因与工具之间的话里的能力 ID 走能力标题", () => {
+ const activity: ActivityItem[] = [
+ { kind: "note", key: "n1", text: "site.health_check 被拒,改用 site.list。", at: AT },
+ {
+ kind: "tool",
+ key: "c1",
+ call: call({
+ capabilityId: "download.inspect",
+ status: "failed",
+ outputSummary: '{"error":{"code":"x","message":"site.health_check 调用失败"}}',
+ }),
+ },
+ ];
+ const t = text(render(createElement(StepSummary, { activity, running: false })));
+ expect(t).not.toContain("site.health_check");
+ expect(t).not.toContain("site.list");
+ expect(t).toContain("检测站点 被拒");
+ });
+});