Skip to main content

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.

FieldTypeDescription
Modelprovider.LanguageModelLanguage model for the agent
SystemstringSystem prompt for the agent
Tools[]types.ToolTools available to the agent
ActiveTools[]stringRestricts the available tools by name before model calls
StopWhen[]ai.StopConditionConditions that terminate the tool-calling loop, e.g. []ai.StopCondition{ai.IsStepCount(20)} (default)
MaxStepsintDeprecated — use StopWhen with ai.IsStepCount instead
Temperature*float64Sampling temperature
MaxTokens*intMaximum tokens per generation
ToolChoicetypes.ToolChoiceControls how the model may call tools
ProviderOptionsmap[string]interfaceProvider-specific options
Skills*SkillRegistryReusable agent behaviors, registered with AddSkill
Subagents*SubagentRegistrySpecialized agents that can be delegated to
PrepareCallfunc(ctx, PrepareCallConfig) PrepareCallConfigCalled before each generation step to adjust settings dynamically
OnStepEndfunc(types.StepResult)Called after each step completes
OnFinishfunc(*AgentResult)Called when agent execution completes
ToolApprovalRequiredboolWhether 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​

FieldTypeDescription
TextstringAgent's final text output
OutputinterfaceParsed/structured output when an output strategy is configured
Steps[]types.StepResultAll steps in the loop
ToolResults[]types.ToolResultAll tool results from execution
FinishReasontypes.FinishReasonFinal finish reason
StopReasonstringWhy the loop stopped
Usagetypes.UsageTotal token usage
Warnings[]types.WarningWarnings 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​