ToolLoopAgent
ToolLoopAgent is an agent that loops through tool calls until the task
completes. It lives in github.com/digitallysavvy/go-ai/pkg/agent (not
pkg/ai) and implements the agent.Agent interface.
Signature
func NewToolLoopAgent(config AgentConfig) *ToolLoopAgent
Parameters
AgentConfig (selected fields)
AgentConfig has many fields; these are the ones most commonly used.
| Field | Type | Description |
|---|---|---|
| Model | provider.LanguageModel | Language model for the agent |
| System | string | System prompt for the agent |
| Tools | []types.Tool | Tools available to the agent |
| ActiveTools | []string | Restricts the available tools by name before model calls |
| StopWhen | []ai.StopCondition | Conditions that terminate the tool-calling loop, e.g. []ai.StopCondition{ai.IsStepCount(20)} (default) |
| MaxSteps | int | Deprecated — use StopWhen with ai.IsStepCount instead |
| Temperature | *float64 | Sampling temperature |
| MaxTokens | *int | Maximum tokens per generation |
| ToolChoice | types.ToolChoice | Controls how the model may call tools |
| ProviderOptions | map[string]interface | Provider-specific options |
| Skills | *SkillRegistry | Reusable agent behaviors, registered with AddSkill |
| Subagents | *SubagentRegistry | Specialized agents that can be delegated to |
| PrepareCall | func(ctx, PrepareCallConfig) PrepareCallConfig | Called before each generation step to adjust settings dynamically |
| OnStepEnd | func(types.StepResult) | Called after each step completes |
| OnFinish | func(*AgentResult) | Called when agent execution completes |
| ToolApprovalRequired | bool | Whether tools require approval before execution |
See go doc ./pkg/agent AgentConfig for the complete field list, including
telemetry, retry, timeout, and callback-event options.
Methods
func (a *ToolLoopAgent) Execute(ctx context.Context, prompt string) (*AgentResult, error)
func (a *ToolLoopAgent) ExecuteWithMessages(ctx context.Context, messages []types.Message) (*AgentResult, error)
func (a *ToolLoopAgent) Generate(ctx context.Context, opts AgentGenerateOptions) (*ai.GenerateTextResult, error)
func (a *ToolLoopAgent) GenerateAgent(ctx context.Context, opts AgentGenerateOptions) (*AgentResult, error)
func (a *ToolLoopAgent) Stream(ctx context.Context, opts AgentStreamOptions) (*ai.StreamTextResult, error)
func (a *ToolLoopAgent) AddTool(tool types.Tool)
func (a *ToolLoopAgent) RemoveTool(toolName string)
func (a *ToolLoopAgent) Tools() []types.Tool
func (a *ToolLoopAgent) AddSkill(skill *Skill) error
func (a *ToolLoopAgent) AddSubagent(name string, subagent Agent) error
func (a *ToolLoopAgent) DelegateToSubagent(ctx context.Context, name string, prompt string) (*AgentResult, error)
func (a *ToolLoopAgent) SetMaxSteps(maxSteps int)
func (a *ToolLoopAgent) SetStopConditions(conditions []ai.StopCondition)
func (a *ToolLoopAgent) SetSystem(system string)
func (a *ToolLoopAgent) ID() string
func (a *ToolLoopAgent) Version() string
Return Value
AgentResult
| Field | Type | Description |
|---|---|---|
| Text | string | Agent's final text output |
| Output | interface | Parsed/structured output when an output strategy is configured |
| Steps | []types.StepResult | All steps in the loop |
| ToolResults | []types.ToolResult | All tool results from execution |
| FinishReason | types.FinishReason | Final finish reason |
| StopReason | string | Why the loop stopped |
| Usage | types.Usage | Total token usage |
| Warnings | []types.Warning | Warnings from any step |
Examples
Basic Tool Loop Agent
package main
import (
"context"
"fmt"
"log"
"github.com/digitallysavvy/go-ai/pkg/agent"
"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"}
priceCompareTool := types.Tool{Name: "price_compare"}
a := agent.NewToolLoopAgent(agent.AgentConfig{
Model: model,
Tools: []types.Tool{searchTool, priceCompareTool},
})
result, err := a.Execute(context.Background(), "Find and compare prices of three popular smartphones")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Answer: %s\n", result.Text)
fmt.Printf("Tool calls: %d\n", len(result.ToolResults))
}
With a Custom Stop Condition
a := agent.NewToolLoopAgent(agent.AgentConfig{
Model: model,
Tools: tools,
StopWhen: []ai.StopCondition{
ai.HasToolCall("final_answer"),
ai.IsStepCount(5),
},
})
result, err := a.Execute(ctx, "Research topic and gather 3 key facts")
With Step and Tool Callbacks
a := agent.NewToolLoopAgent(agent.AgentConfig{
Model: model,
Tools: tools,
OnStepEnd: func(step types.StepResult) {
fmt.Printf("Step finished, %d tool calls\n", len(step.ToolCalls))
},
OnToolResult: func(result types.ToolResult) {
fmt.Printf("Tool result: %+v\n", result.Result)
if result.Error != nil {
fmt.Printf("Tool error: %v\n", result.Error)
}
},
})
result, err := a.Execute(ctx, "Complex multi-step research task")
See Also
- Agent - The
agent.Agentinterface - Tool - Tool definition
- Agents Guide