diff --git a/packages/agent/src/agent-loop.ts b/packages/agent/src/agent-loop.ts index 5e25c35ce..029aae278 100644 --- a/packages/agent/src/agent-loop.ts +++ b/packages/agent/src/agent-loop.ts @@ -936,7 +936,7 @@ async function executePreparedToolCall( ); acceptingUpdates = false; await Promise.all(updateEvents); - return { result, isError: false }; + return { result, isError: result.isError === true }; } catch (error) { acceptingUpdates = false; await Promise.all(updateEvents); diff --git a/packages/agent/src/types.ts b/packages/agent/src/types.ts index 44617bb66..89c0ad5ab 100644 --- a/packages/agent/src/types.ts +++ b/packages/agent/src/types.ts @@ -447,6 +447,12 @@ export interface AgentToolResult { structuredContent?: JsonValue; /** Usage from the final tool execution itself, if available. Not used for main LLM context accounting. */ usage?: Usage; + /** + * Report a failure without throwing. The model sees `content` as an error result, like a thrown + * error, but `details` and `structuredContent` are kept, so the UI and programmatic callers can + * still read partial output or a structured failure (for example an MCP result with `isError`). + */ + isError?: boolean; /** * Hint that the agent should stop after the current tool batch. * Early termination only happens when every finalized tool result in the batch sets this to true. @@ -511,7 +517,8 @@ export interface AgentTool