@@ -17,6 +17,7 @@ import {
1717 OutputGuardrailTripwireTriggered ,
1818 Session ,
1919 ModelInputData ,
20+ type OutputGuardrailFunctionArgs ,
2021 type AgentInputItem ,
2122 run ,
2223 Runner ,
@@ -436,6 +437,92 @@ describe('Runner.run', () => {
436437 ) ;
437438 } ) ;
438439
440+ it ( 'passes run details to output guardrails' , async ( ) => {
441+ let receivedArgs : OutputGuardrailFunctionArgs | undefined ;
442+ let guardrailValidatedTool = false ;
443+ const guardrailFn = vi . fn ( async ( args : OutputGuardrailFunctionArgs ) => {
444+ receivedArgs = args ;
445+ const toolCall = args . details ?. output ?. find (
446+ ( item ) : item is protocol . FunctionCallItem =>
447+ item . type === 'function_call' &&
448+ ( item as protocol . FunctionCallItem ) . name === 'queryPerson' ,
449+ ) ;
450+ expect ( toolCall ?. arguments ) . toContain ( 'person-1' ) ;
451+ guardrailValidatedTool = true ;
452+ return { tripwireTriggered : false , outputInfo : { } } ;
453+ } ) ;
454+ const runner = new Runner ( {
455+ outputGuardrails : [ { name : 'og' , execute : guardrailFn } ] ,
456+ } ) ;
457+ const queryPerson = tool ( {
458+ name : 'queryPerson' ,
459+ description : 'Look up a person by id' ,
460+ parameters : z . object ( { personId : z . string ( ) } ) ,
461+ execute : async ( { personId } ) => `${ personId } result` ,
462+ } ) ;
463+ const responses : ModelResponse [ ] = [
464+ {
465+ output : [
466+ {
467+ id : 'call-1' ,
468+ type : 'function_call' ,
469+ name : 'queryPerson' ,
470+ callId : 'call-1' ,
471+ status : 'completed' ,
472+ arguments : '{"personId":"person-1"}' ,
473+ } ,
474+ ] ,
475+ usage : new Usage ( ) ,
476+ } ,
477+ {
478+ output : [ fakeModelMessage ( 'done' ) ] ,
479+ usage : new Usage ( ) ,
480+ } ,
481+ ] ;
482+ const agent = new Agent ( {
483+ name : 'Out' ,
484+ model : new FakeModel ( responses ) ,
485+ tools : [ queryPerson ] ,
486+ } ) ;
487+
488+ await runner . run ( agent , 'input' ) ;
489+
490+ expect ( guardrailFn ) . toHaveBeenCalledTimes ( 1 ) ;
491+
492+ const outputItems = receivedArgs ?. details ?. output ?? [ ] ;
493+ expect ( outputItems . length ) . toBeGreaterThan ( 0 ) ;
494+ const toolCall = outputItems . find (
495+ ( item ) : item is protocol . FunctionCallItem =>
496+ item . type === 'function_call' && ( item as any ) . name === 'queryPerson' ,
497+ ) ;
498+ expect ( toolCall ?. arguments ) . toContain ( 'person-1' ) ;
499+
500+ const toolResult = outputItems . find (
501+ ( item ) : item is protocol . FunctionCallResultItem =>
502+ item . type === 'function_call_result' &&
503+ ( item as any ) . callId === 'call-1' ,
504+ ) ;
505+ expect ( toolResult ) . toBeDefined ( ) ;
506+ const toolOutput = toolResult ?. output ;
507+ if ( typeof toolOutput === 'string' ) {
508+ expect ( toolOutput ) . toBe ( 'person-1 result' ) ;
509+ } else if ( Array . isArray ( toolOutput ) ) {
510+ expect (
511+ toolOutput . some (
512+ ( item ) =>
513+ 'text' in item &&
514+ typeof ( item as { text ?: unknown } ) . text === 'string' &&
515+ ( item as { text : string } ) . text === 'person-1 result' ,
516+ ) ,
517+ ) . toBe ( true ) ;
518+ } else {
519+ expect ( ( toolOutput as { text ?: string } | undefined ) ?. text ) . toBe (
520+ 'person-1 result' ,
521+ ) ;
522+ }
523+ expect ( guardrailValidatedTool ) . toBe ( true ) ;
524+ } ) ;
525+
439526 it ( 'executes tool calls and records output' , async ( ) => {
440527 const first : ModelResponse = {
441528 output : [
0 commit comments