@@ -84,9 +84,80 @@ const getNews: EvalToolDefinition = {
8484 } ,
8585}
8686
87+ const getCurrentWeather : EvalToolDefinition = {
88+ name : 'get_current_weather' ,
89+ description : 'Get the current weather for a city right now.' ,
90+ parameters : {
91+ type : 'object' ,
92+ properties : { city : { type : 'string' } } ,
93+ required : [ 'city' ] ,
94+ } ,
95+ }
96+
97+ const getWeatherForecast : EvalToolDefinition = {
98+ name : 'get_weather_forecast' ,
99+ description : 'Get the weather forecast for a city on a future date.' ,
100+ parameters : {
101+ type : 'object' ,
102+ properties : { city : { type : 'string' } , date : { type : 'string' } } ,
103+ required : [ 'city' , 'date' ] ,
104+ } ,
105+ }
106+
107+ const getUser : EvalToolDefinition = {
108+ name : 'get_user' ,
109+ description : 'Get a user profile by id.' ,
110+ parameters : {
111+ type : 'object' ,
112+ properties : { userId : { type : 'string' } } ,
113+ required : [ 'userId' ] ,
114+ } ,
115+ }
116+
117+ const getUserSettings : EvalToolDefinition = {
118+ name : 'get_user_settings' ,
119+ description : "Get a user's account settings, including timezone and locale." ,
120+ parameters : {
121+ type : 'object' ,
122+ properties : { userId : { type : 'string' } } ,
123+ required : [ 'userId' ] ,
124+ } ,
125+ }
126+
127+ const listOrders : EvalToolDefinition = {
128+ name : 'list_orders' ,
129+ description : 'List order ids for a user.' ,
130+ parameters : {
131+ type : 'object' ,
132+ properties : { userId : { type : 'string' } } ,
133+ required : [ 'userId' ] ,
134+ } ,
135+ }
136+
137+ const getOrder : EvalToolDefinition = {
138+ name : 'get_order' ,
139+ description : 'Get an order by id.' ,
140+ parameters : {
141+ type : 'object' ,
142+ properties : { orderId : { type : 'string' } } ,
143+ required : [ 'orderId' ] ,
144+ } ,
145+ }
146+
147+ const getShipping : EvalToolDefinition = {
148+ name : 'get_shipping' ,
149+ description : 'Get the shipping status for an order.' ,
150+ parameters : {
151+ type : 'object' ,
152+ properties : { orderId : { type : 'string' } } ,
153+ required : [ 'orderId' ] ,
154+ } ,
155+ }
156+
87157/**
88- * The first suite: eight agent tool-use reliability cases. Each script is the
89- * model transcript; the loop, not the model, is what the assertions score.
158+ * The tool-use suite: reliability plus adversarial cases (no-tool-needed,
159+ * near-duplicate tools, empty results, long chains). Each script is the model
160+ * transcript; the loop, not the model, is what the assertions score.
90161 */
91162export const AGENT_TOOL_USE_SCENARIOS : AgentToolUseScenario [ ] = [
92163 {
@@ -357,4 +428,165 @@ export const AGENT_TOOL_USE_SCENARIOS: AgentToolUseScenario[] = [
357428 erroredToolCalls : 1 ,
358429 } ,
359430 } ,
431+ {
432+ id : 'no-tool-needed' ,
433+ name : 'answers directly without calling a tool' ,
434+ category : 'tool-selection' ,
435+ description :
436+ 'The answer needs no tool. The loop must not invoke one even though tools are available.' ,
437+ userMessage : 'What is 2 + 2? Answer directly, no tools.' ,
438+ tools : [ searchDocs , getWeather ] ,
439+ script : [ { kind : 'answer' , content : '4' } ] ,
440+ expect : {
441+ finalContent : '4' ,
442+ forbiddenTools : [ 'search_docs' , 'get_weather' ] ,
443+ successfulToolCalls : 0 ,
444+ maxIterations : 2 ,
445+ } ,
446+ } ,
447+ {
448+ id : 'disambiguate-similar-tools' ,
449+ name : 'picks the forecast tool over the current-weather tool' ,
450+ category : 'tool-selection' ,
451+ description :
452+ 'Two near-identical weather tools; only the forecast tool answers a future-date question.' ,
453+ userMessage : 'Will it rain tomorrow in Berlin?' ,
454+ tools : [ getCurrentWeather , getWeatherForecast ] ,
455+ script : [
456+ {
457+ kind : 'tools' ,
458+ calls : [
459+ {
460+ name : 'get_weather_forecast' ,
461+ args : { city : 'Berlin' , date : 'tomorrow' } ,
462+ result : { success : true , output : { rain : true } } ,
463+ } ,
464+ ] ,
465+ } ,
466+ { kind : 'answer' , content : 'Yes, it will rain in Berlin tomorrow.' } ,
467+ ] ,
468+ expect : {
469+ requiredTools : [ 'get_weather_forecast' ] ,
470+ forbiddenTools : [ 'get_current_weather' ] ,
471+ finalContent : / r a i n / i,
472+ maxIterations : 3 ,
473+ } ,
474+ } ,
475+ {
476+ id : 'empty-result-no-hallucination' ,
477+ name : 'does not invent an answer when the tool returns nothing' ,
478+ category : 'retrieval' ,
479+ description :
480+ 'The search returns no results. The model must say it could not find the policy, not fabricate one.' ,
481+ userMessage : 'What is the refund policy?' ,
482+ tools : [ searchDocs ] ,
483+ script : [
484+ {
485+ kind : 'tools' ,
486+ calls : [
487+ {
488+ name : 'search_docs' ,
489+ args : { query : 'refund policy' } ,
490+ result : { success : true , output : { results : [ ] } } ,
491+ } ,
492+ ] ,
493+ } ,
494+ {
495+ kind : 'answer' ,
496+ content : 'I could not find the refund policy in the documentation.' ,
497+ } ,
498+ ] ,
499+ expect : {
500+ requiredTools : [ 'search_docs' ] ,
501+ finalContent :
502+ / c o u l d ? n [ o ' ] t f i n d | c a n n o t f i n d | c a n ' ? t f i n d | n o r e s u l t s | n o t f i n d | u n a b l e t o f i n d | n o .* p o l i c y / i,
503+ maxIterations : 3 ,
504+ } ,
505+ } ,
506+ {
507+ id : 'long-chain-dependency' ,
508+ name : 'runs a four-tool dependency chain in order' ,
509+ category : 'planning' ,
510+ description :
511+ 'Each call depends on the previous result; the loop must preserve order across four turns.' ,
512+ userMessage : 'Where is my latest order?' ,
513+ tools : [ getUser , listOrders , getOrder , getShipping ] ,
514+ script : [
515+ {
516+ kind : 'tools' ,
517+ calls : [
518+ {
519+ name : 'get_user' ,
520+ args : { userId : 'me' } ,
521+ result : { success : true , output : { id : 'u1' } } ,
522+ } ,
523+ ] ,
524+ } ,
525+ {
526+ kind : 'tools' ,
527+ calls : [
528+ {
529+ name : 'list_orders' ,
530+ args : { userId : 'u1' } ,
531+ result : { success : true , output : { orderIds : [ 'o9' ] } } ,
532+ } ,
533+ ] ,
534+ } ,
535+ {
536+ kind : 'tools' ,
537+ calls : [
538+ {
539+ name : 'get_order' ,
540+ args : { orderId : 'o9' } ,
541+ result : { success : true , output : { orderId : 'o9' , status : 'shipped' } } ,
542+ } ,
543+ ] ,
544+ } ,
545+ {
546+ kind : 'tools' ,
547+ calls : [
548+ {
549+ name : 'get_shipping' ,
550+ args : { orderId : 'o9' } ,
551+ result : { success : true , output : { carrier : 'DHL' , tracking : 'T-1' } } ,
552+ } ,
553+ ] ,
554+ } ,
555+ { kind : 'answer' , content : 'Order o9 is shipped with DHL, tracking T-1.' } ,
556+ ] ,
557+ expect : {
558+ toolCallSequence : [ 'get_user' , 'list_orders' , 'get_order' , 'get_shipping' ] ,
559+ finalContent : / D H L / ,
560+ maxIterations : 5 ,
561+ successfulToolCalls : 4 ,
562+ } ,
563+ } ,
564+ {
565+ id : 'near-duplicate-names' ,
566+ name : 'picks settings over the profile for a settings question' ,
567+ category : 'tool-selection' ,
568+ description :
569+ 'get_user and get_user_settings differ by suffix; only the settings tool has the timezone.' ,
570+ userMessage : 'What timezone is set in my account settings?' ,
571+ tools : [ getUser , getUserSettings ] ,
572+ script : [
573+ {
574+ kind : 'tools' ,
575+ calls : [
576+ {
577+ name : 'get_user_settings' ,
578+ args : { userId : 'me' } ,
579+ result : { success : true , output : { timezone : 'Europe/Berlin' } } ,
580+ } ,
581+ ] ,
582+ } ,
583+ { kind : 'answer' , content : 'Your account timezone is Europe/Berlin.' } ,
584+ ] ,
585+ expect : {
586+ requiredTools : [ 'get_user_settings' ] ,
587+ forbiddenTools : [ 'get_user' ] ,
588+ finalContent : / E u r o p e \/ B e r l i n / ,
589+ maxIterations : 3 ,
590+ } ,
591+ } ,
360592]
0 commit comments