66 "fmt"
77 "log/slog"
88 "strings"
9+ "sync"
910 "time"
1011 "unicode/utf8"
1112
@@ -20,7 +21,7 @@ func encodeBase64(data []byte) string {
2021}
2122
2223const (
23- maxToolIterations = 5
24+ maxToolIterations = 10
2425 semanticRecentN = 10 // always include last N messages in current session
2526 semanticTopK = 20 // up to K older turns selected by similarity within session
2627
@@ -170,29 +171,7 @@ func (a *Agent) Process(ctx context.Context, chatID int64, userMsg llm.Message,
170171 ToolCalls : resp .ToolCalls ,
171172 })
172173
173- for _ , tc := range resp .ToolCalls {
174- if onToolCall != nil {
175- onToolCall (tc .Name )
176- }
177- a .logger .Info ("tool call" , "tool" , tc .Name )
178- result , err := a .callTool (ctx , tc .Name , tc .Arguments )
179- if err != nil {
180- a .logger .Warn ("tool call failed" , "tool" , tc .Name , "err" , err )
181- result = fmt .Sprintf ("Error: %s" , err .Error ())
182- }
183- if len (result ) > toolResultSummarizeThreshold {
184- if summarized , sErr := a .summarizeToolResult (ctx , tc .Name , result ); sErr == nil {
185- a .logger .Info ("tool result summarized" , "tool" , tc .Name , "original_len" , len (result ), "summary_len" , len (summarized ))
186- result = summarized
187- }
188- }
189- a .logger .Info ("tool result" , "tool" , tc .Name , "result_len" , len (result ))
190- a .store .AddMessage (chatID , llm.Message {
191- Role : "tool" ,
192- Content : result ,
193- ToolCallID : tc .ID ,
194- })
195- }
174+ a .executeToolCalls (ctx , chatID , resp .ToolCalls , onToolCall )
196175 }
197176
198177 return "" , fmt .Errorf ("exceeded maximum tool iterations (%d)" , maxToolIterations )
@@ -279,11 +258,36 @@ func (a *Agent) ProcessStream(ctx context.Context, chatID int64, userMsg llm.Mes
279258 ToolCalls : toolCalls ,
280259 })
281260
282- for _ , tc := range toolCalls {
283- if onToolCall != nil {
284- onToolCall (tc .Name )
285- }
286- a .logger .Info ("tool call" , "tool" , tc .Name )
261+ a .executeToolCalls (ctx , chatID , toolCalls , onToolCall )
262+ }
263+
264+ return "" , fmt .Errorf ("exceeded maximum tool iterations (%d)" , maxToolIterations )
265+ }
266+
267+ // SupportsStreaming returns true if the current provider supports streaming.
268+ func (a * Agent ) SupportsStreaming () bool {
269+ return a .router .SupportsStreaming ()
270+ }
271+
272+ // executeToolCalls runs tool calls in parallel and stores results in order.
273+ func (a * Agent ) executeToolCalls (ctx context.Context , chatID int64 , toolCalls []llm.ToolCall , onToolCall func (string )) {
274+ type toolResult struct {
275+ tc llm.ToolCall
276+ result string
277+ }
278+
279+ results := make ([]toolResult , len (toolCalls ))
280+ var wg sync.WaitGroup
281+
282+ for i , tc := range toolCalls {
283+ if onToolCall != nil {
284+ onToolCall (tc .Name )
285+ }
286+ a .logger .Info ("tool call" , "tool" , tc .Name )
287+
288+ wg .Add (1 )
289+ go func (idx int , tc llm.ToolCall ) {
290+ defer wg .Done ()
287291 result , err := a .callTool (ctx , tc .Name , tc .Arguments )
288292 if err != nil {
289293 a .logger .Warn ("tool call failed" , "tool" , tc .Name , "err" , err )
@@ -296,20 +300,20 @@ func (a *Agent) ProcessStream(ctx context.Context, chatID int64, userMsg llm.Mes
296300 }
297301 }
298302 a .logger .Info ("tool result" , "tool" , tc .Name , "result_len" , len (result ))
299- a .store .AddMessage (chatID , llm.Message {
300- Role : "tool" ,
301- Content : result ,
302- ToolCallID : tc .ID ,
303- })
304- }
303+ results [idx ] = toolResult {tc : tc , result : result }
304+ }(i , tc )
305305 }
306306
307- return "" , fmt .Errorf ("exceeded maximum tool iterations (%d)" , maxToolIterations )
308- }
307+ wg .Wait ()
309308
310- // SupportsStreaming returns true if the current provider supports streaming.
311- func (a * Agent ) SupportsStreaming () bool {
312- return a .router .SupportsStreaming ()
309+ // Store results in original order.
310+ for _ , r := range results {
311+ a .store .AddMessage (chatID , llm.Message {
312+ Role : "tool" ,
313+ Content : r .result ,
314+ ToolCallID : r .tc .ID ,
315+ })
316+ }
313317}
314318
315319func (a * Agent ) ClearHistory (chatID int64 ) {
0 commit comments