@@ -56,6 +56,10 @@ type FunctionToolCallDeps<TContext = UnknownContext> = {
5656
5757const TOOL_APPROVAL_REJECTION_MESSAGE = 'Tool execution was not approved.' ;
5858
59+ type ParseToolArgumentsResult =
60+ | { success : true ; args : any }
61+ | { success : false ; error : Error } ;
62+
5963/**
6064 * @internal
6165 * Normalizes tool outputs once so downstream code works with fully structured protocol items.
@@ -109,11 +113,17 @@ export async function executeFunctionToolCalls<TContext = UnknownContext>(
109113 try {
110114 const results = await Promise . all (
111115 toolRuns . map ( async ( toolRun ) => {
112- const parsedArgs = parseToolArguments ( toolRun ) ;
116+ const parseResult = parseToolArguments ( toolRun ) ;
117+
118+ // Handle parse errors gracefully instead of crashing
119+ if ( ! parseResult . success ) {
120+ return buildParseErrorResult ( deps , toolRun , parseResult . error ) ;
121+ }
122+
113123 const approvalOutcome = await handleFunctionApproval (
114124 deps ,
115125 toolRun ,
116- parsedArgs ,
126+ parseResult . args ,
117127 ) ;
118128 if ( approvalOutcome !== 'approved' ) {
119129 return approvalOutcome ;
@@ -131,16 +141,25 @@ export async function executeFunctionToolCalls<TContext = UnknownContext>(
131141 }
132142}
133143
134- function parseToolArguments < TContext > ( toolRun : ToolRunFunction < TContext > ) {
135- let parsedArgs : any = toolRun . toolCall . arguments ;
136- if ( toolRun . tool . parameters ) {
137- if ( isZodObject ( toolRun . tool . parameters ) ) {
138- parsedArgs = toolRun . tool . parameters . parse ( parsedArgs ) ;
139- } else {
140- parsedArgs = JSON . parse ( parsedArgs ) ;
144+ function parseToolArguments < TContext > (
145+ toolRun : ToolRunFunction < TContext > ,
146+ ) : ParseToolArgumentsResult {
147+ try {
148+ let parsedArgs : any = toolRun . toolCall . arguments ;
149+ if ( toolRun . tool . parameters ) {
150+ if ( isZodObject ( toolRun . tool . parameters ) ) {
151+ parsedArgs = toolRun . tool . parameters . parse ( parsedArgs ) ;
152+ } else {
153+ parsedArgs = JSON . parse ( parsedArgs ) ;
154+ }
141155 }
156+ return { success : true , args : parsedArgs } ;
157+ } catch ( error ) {
158+ logger . debug (
159+ `Failed to parse tool arguments for ${ toolRun . tool . name } : ${ error } ` ,
160+ ) ;
161+ return { success : false , error : error as Error } ;
142162 }
143- return parsedArgs ;
144163}
145164
146165function buildApprovalRequestResult < TContext > (
@@ -154,6 +173,24 @@ function buildApprovalRequestResult<TContext>(
154173 } ;
155174}
156175
176+ function buildParseErrorResult < TContext > (
177+ deps : FunctionToolCallDeps < TContext > ,
178+ toolRun : ToolRunFunction < TContext > ,
179+ error : Error ,
180+ ) : FunctionToolResult < TContext > {
181+ const errorMessage = `An error occurred while parsing tool arguments. Please try again with valid JSON. Error: ${ error . message } ` ;
182+ return {
183+ type : 'function_output' ,
184+ tool : toolRun . tool ,
185+ output : errorMessage ,
186+ runItem : new RunToolCallOutputItem (
187+ getToolCallOutputItem ( toolRun . toolCall , errorMessage ) ,
188+ deps . agent ,
189+ errorMessage ,
190+ ) ,
191+ } ;
192+ }
193+
157194async function buildApprovalRejectionResult < TContext > (
158195 deps : FunctionToolCallDeps < TContext > ,
159196 toolRun : ToolRunFunction < TContext > ,
0 commit comments