executeSingleTool executes one tool call and converts the response into a ToolResultContent.
(
ctx context.Context,
toolMap map[string]fantasy.AgentTool,
tc fantasy.ToolCallContent,
metrics *Metrics,
logger slog.Logger,
provider, model string,
builtinToolNames map[string]bool,
activeTools []string,
providerRunnerNames map[string]struct{},
resultProviderMetadata map[string]func(fantasy.ToolResponse) fantasy.ProviderMetadata,
)
| 1530 | // executeSingleTool executes one tool call and converts the |
| 1531 | // response into a ToolResultContent. |
| 1532 | func executeSingleTool( |
| 1533 | ctx context.Context, |
| 1534 | toolMap map[string]fantasy.AgentTool, |
| 1535 | tc fantasy.ToolCallContent, |
| 1536 | metrics *Metrics, |
| 1537 | logger slog.Logger, |
| 1538 | provider, model string, |
| 1539 | builtinToolNames map[string]bool, |
| 1540 | activeTools []string, |
| 1541 | providerRunnerNames map[string]struct{}, |
| 1542 | resultProviderMetadata map[string]func(fantasy.ToolResponse) fantasy.ProviderMetadata, |
| 1543 | ) fantasy.ToolResultContent { |
| 1544 | result := fantasy.ToolResultContent{ |
| 1545 | ToolCallID: tc.ToolCallID, |
| 1546 | ToolName: tc.ToolName, |
| 1547 | ProviderExecuted: false, |
| 1548 | } |
| 1549 | defer func() { |
| 1550 | metricLabel := tc.ToolName |
| 1551 | if metricLabel == "" { |
| 1552 | metricLabel = "unknown" |
| 1553 | } |
| 1554 | metrics.ToolResultSizeBytes.WithLabelValues(provider, model, metricLabel).Observe( |
| 1555 | float64(ToolResultSize(result)), |
| 1556 | ) |
| 1557 | if _, ok := result.Result.(fantasy.ToolResultOutputContentError); ok { |
| 1558 | metrics.RecordToolError(provider, model, metricLabel) |
| 1559 | } |
| 1560 | }() |
| 1561 | |
| 1562 | _, isProviderRunner := providerRunnerNames[tc.ToolName] |
| 1563 | if !isProviderRunner && !isToolActive(tc.ToolName, activeTools) { |
| 1564 | result.Result = fantasy.ToolResultOutputContentError{ |
| 1565 | Error: xerrors.New("Tool not active in this turn: " + tc.ToolName), |
| 1566 | } |
| 1567 | return result |
| 1568 | } |
| 1569 | |
| 1570 | tool, exists := toolMap[tc.ToolName] |
| 1571 | if !exists { |
| 1572 | result.Result = fantasy.ToolResultOutputContentError{ |
| 1573 | Error: xerrors.New("Tool not found: " + tc.ToolName), |
| 1574 | } |
| 1575 | return result |
| 1576 | } |
| 1577 | |
| 1578 | logger.Debug(ctx, "tool execution", |
| 1579 | slog.F("tool_name", tc.ToolName), |
| 1580 | slog.F("tool_call_id", tc.ToolCallID), |
| 1581 | slog.F("builtin", builtinToolNames[tc.ToolName]), |
| 1582 | slog.F("is_provider_runner", isProviderRunner), |
| 1583 | ) |
| 1584 | resp, err := tool.Run(ctx, fantasy.ToolCall{ |
| 1585 | ID: tc.ToolCallID, |
| 1586 | Name: tc.ToolName, |
| 1587 | Input: tc.Input, |
| 1588 | }) |
| 1589 | if err != nil { |