package llm import ( "context" "fmt" "log/slog" "strings" ) // callTools executes each tool call in the message and returns the // resulting tool result messages. func (c *Client) callTools(ctx context.Context, msg Message) ( results []Message, err error, ) { for _, tc := range msg.ToolCalls { c.log.InfoContext( ctx, "calling tool", slog.String("name", tc.Function.Name), slog.String("args", tc.Function.Arguments), ) result, err := c.registry.Execute( ctx, tc.Function.Name, tc.Function.Arguments, ) if err != nil { c.log.ErrorContext( ctx, "failed to call tool", slog.Any("error", err), slog.String("name", tc.Function.Name), ) result = fmt.Sprintf( `{"ok": false, "error": %q}`, err, ) } else { c.log.InfoContext( ctx, "called tool", slog.String("name", tc.Function.Name), ) } // Content cannot be empty. if strings.TrimSpace(result) == "" { result = `{"ok": true, "result": null}` } toolResult := Message{ Role: RoleTool, ContentParts: []ContentPart{{ Type: ContentTypeText, Text: result, }}, Name: tc.Function.Name, ToolCallID: tc.ID, } results = append(results, toolResult) } return results, nil }