# 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

```go
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.ToolCall`
- `ai.GenerateTextResult.DynamicToolResults []types.ToolResult`
- `ai.StreamTextResult.DynamicToolCalls() []types.ToolCall`
- `ai.StreamTextResult.DynamicToolResults() []types.ToolResult`
- `types.ToolCall.Dynamic bool` and `types.ToolResult.Dynamic bool`

## Examples

### Registering a dynamic tool

```go
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

```go
for _, tr := range result.ToolResults {
    if tr.Dynamic {
        fmt.Printf("dynamic tool %s returned %v\n", tr.ToolName, tr.Result)
    }
}
```

## See Also

- [Tool](https://goaisdk.com/docs/reference/ai/tool.md) - Static tool definition
- [Tool Calling Guide](https://goaisdk.com/docs/ai-sdk-core/tools-and-tool-calling.md)
