@@ -3,6 +3,7 @@ package conversation
33import (
44 "context"
55 "encoding/json"
6+ "fmt"
67 "strings"
78 "time"
89
@@ -31,6 +32,7 @@ type executeAssistantToolCallsResult struct {
3132 Rows []model.ToolCall
3233 ToolResults []llm.ToolResult
3334 ExecutedToolCalls []llm.ToolCall
35+ FatalErr error
3436}
3537
3638type toolExecutionRecord struct {
@@ -66,6 +68,7 @@ func (s *Service) executeAssistantToolCalls(ctx context.Context, input executeAs
6668 }
6769
6870 slots := make ([]toolExecutionSlot , len (toolCalls ))
71+ var fatalErr error
6972 for i , item := range toolCalls {
7073 modelToolName := strings .TrimSpace (item .ToolName )
7174 executionToolName := resolveExecutionToolName (modelToolName , input .ToolNameMap )
@@ -81,6 +84,23 @@ func (s *Service) executeAssistantToolCalls(ctx context.Context, input executeAs
8184 ErrorJSON : "" ,
8285 }
8386
87+ mcpConfig := resolveMCPConfig (modelToolName , input .MCPConfigs )
88+ if mcpConfig == nil {
89+ row .Status = "error"
90+ row .ErrorJSON = toolNotEnabledForRunMessage (modelToolName )
91+ slots [i ] = toolExecutionSlot {
92+ row : row ,
93+ result : buildToolResultForModel (row , modelToolName ),
94+ }
95+ if fatalErr == nil {
96+ fatalErr = fmt .Errorf ("model requested tool %q, but it is not enabled for this run" , modelToolName )
97+ }
98+ if input .Ledger != nil {
99+ input .Ledger .store (row .ToolName , row .InputJSON , toolExecutionRecord {row : row , result : slots [i ].result })
100+ }
101+ continue
102+ }
103+
84104 normalizedInput , validationErr := normalizeToolArguments (row .InputJSON , input .ToolSchemas [modelToolName ])
85105 if validationErr != nil {
86106 row .Status = "error"
@@ -110,7 +130,7 @@ func (s *Service) executeAssistantToolCalls(ctx context.Context, input executeAs
110130 RequestID : strings .TrimSpace (input .RequestID ),
111131 ToolName : row .ToolName ,
112132 ArgumentsJSON : row .InputJSON ,
113- MCPConfig : resolveMCPConfig ( modelToolName , input . MCPConfigs ) ,
133+ MCPConfig : mcpConfig ,
114134 })
115135 row .LatencyMS = time .Since (toolStartedAt ).Milliseconds ()
116136 if row .LatencyMS < 0 {
@@ -151,6 +171,7 @@ func (s *Service) executeAssistantToolCalls(ctx context.Context, input executeAs
151171 Rows : rows ,
152172 ToolResults : toolResults ,
153173 ExecutedToolCalls : executedToolCalls ,
174+ FatalErr : fatalErr ,
154175 }
155176}
156177
@@ -218,6 +239,14 @@ func buildToolResultForModel(row model.ToolCall, modelToolName string) llm.ToolR
218239 }
219240}
220241
242+ func toolNotEnabledForRunMessage (toolName string ) string {
243+ name := strings .TrimSpace (toolName )
244+ if name == "" {
245+ return "tool is not enabled for this run"
246+ }
247+ return fmt .Sprintf ("tool %s is not enabled for this run" , name )
248+ }
249+
221250func budgetToolOutputForModel (raw string , maxChars int ) string {
222251 value := strings .TrimSpace (raw )
223252 if value == "" || maxChars <= 0 || len ([]rune (value )) <= maxChars {
0 commit comments