Dynamic Tools
The Go AI SDK does not have a DynamicTool helper function. Instead, a tool
is marked as dynamic by setting its Type field to types.ToolTypeDynamic.
Dynamic tools are registered and typed at runtime (for example, tools loaded
from an MCP server or built from user-supplied configuration) rather than
being known at compile time. The SDK tracks dynamic tool calls and results
separately from statically defined ones.
Tool.Type
const (
ToolTypeFunction = "function" // default: locally executed function tool
ToolTypeDynamic = "dynamic" // dynamic tool whose schema can vary at runtime
ToolTypeProviderDefined = "provider" // provider-defined native tool
ToolTypeProviderExecuted = "provider-executed"
)
Setting Type: types.ToolTypeDynamic on a types.Tool tells the SDK this
tool's shape isn't known statically. It otherwise has the same fields as any
other tool: Name, Description, Parameters, and Execute.
Tracking dynamic tool calls and results
Results that come from dynamic tools are split out from static ones:
ai.GenerateTextResult.DynamicToolCalls []types.ToolCallai.GenerateTextResult.DynamicToolResults []types.ToolResultai.StreamTextResult.DynamicToolCalls() []types.ToolCallai.StreamTextResult.DynamicToolResults() []types.ToolResulttypes.ToolCall.Dynamic boolandtypes.ToolResult.Dynamic bool
Examples
Registering a dynamic tool
package main
import (
"context"
"fmt"
"log"
"github.com/digitallysavvy/go-ai/pkg/ai"
"github.com/digitallysavvy/go-ai/pkg/provider/types"
"github.com/digitallysavvy/go-ai/pkg/providers/openai"
)
func main() {
p := openai.New(openai.Config{APIKey: "your-api-key"})
model, _ := p.LanguageModel("gpt-4")
searchTool := types.Tool{
Name: "search_db",
Type: types.ToolTypeDynamic,
Description: "Search the database",
Parameters: map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"query": map[string]interface{}{"type": "string"},
},
"required": []string{"query"},
},
Execute: func(ctx context.Context, input map[string]interface{}, opts types.ToolExecutionOptions) (interface{}, error) {
query := input["query"].(string)
return []string{"result for " + query}, nil
},
}
result, err := ai.GenerateText(context.Background(), ai.GenerateTextOptions{
Model: model,
Prompt: "Search the database for invoices",
Tools: []types.Tool{searchTool},
StopWhen: []ai.StopCondition{ai.IsStepCount(5)},
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Dynamic tool calls: %d\n", len(result.DynamicToolCalls))
}
Checking whether a result came from a dynamic tool
for _, tr := range result.ToolResults {
if tr.Dynamic {
fmt.Printf("dynamic tool %s returned %v\n", tr.ToolName, tr.Result)
}
}
See Also
- Tool - Static tool definition
- Tool Calling Guide