Skip to content
Arian Amiramjadi edited this page Dec 24, 2025 · 1 revision

Agents

Agents provide an agentic interface for complex reasoning tasks using the ReAct (Reasoning + Acting) pattern.

Quick Start

// Create an agent with tools
result := ai.Claude().Agent().
    Tool("search", "Search the web", ai.Params().
        String("query", "Search query", true).
        Build(),
        func(args map[string]any) (string, error) {
            return searchWeb(args["query"].(string)), nil
        }).
    Tool("calculate", "Do math", ai.Params().
        String("expression", "Math expression", true).
        Build(),
        func(args map[string]any) (string, error) {
            return calculate(args["expression"].(string)), nil
        }).
    MaxSteps(10).
    Run("What is the population of France divided by the area of Texas?")

fmt.Println(result.Answer)

Creating Agents

From a Builder

// Agent inherits model, system prompt, temperature from builder
agent := ai.Claude().
    System("You are a helpful research assistant").
    ThinkHigh().
    Agent()

Quick Helpers

// Quick agent with common defaults
agent := ai.QuickAgent(ai.ModelGPT5)

// Research agent (high thinking, more steps)
agent := ai.ResearchAgent(ai.ModelClaudeOpus)

// Code agent (GPT-5 Codex, high thinking)
agent := ai.CodeAgent()

Adding Tools

Inline Definition

agent.Tool("get_weather", "Get current weather for a city", 
    ai.Params().
        String("city", "City name", true).
        String("units", "Temperature units", false).
        Build(),
    func(args map[string]any) (string, error) {
        city := args["city"].(string)
        // Call weather API...
        return fmt.Sprintf("Weather in %s: 22°C, sunny", city), nil
    })

Using ToolDef

weatherTool := ai.ToolDef{
    Name:        "get_weather",
    Description: "Get current weather",
    Parameters:  ai.Params().String("city", "City name", true).Build(),
    Handler: func(args map[string]any) (string, error) {
        return getWeather(args["city"].(string)), nil
    },
}

agent.ToolDef(weatherTool)

Multiple Tools

agent.
    Tool("search", "Search the web", searchParams, searchHandler).
    Tool("read_url", "Read a webpage", readParams, readHandler).
    Tool("calculate", "Do math", calcParams, calcHandler)

Configuration

Max Steps

agent.MaxSteps(20) // Allow up to 20 reasoning steps

Timeout

agent.Timeout(5 * time.Minute)

Context

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

agent.WithContext(ctx)

Agent State

Pass data that persists across steps:

agent.
    Set("user_id", "12345").
    Set("preferences", map[string]any{"language": "en"}).
    State(map[string]any{
        "session_start": time.Now(),
    })

Access state in tool handlers:

agent.Tool("personalize", "Get user preferences", params,
    func(args map[string]any) (string, error) {
        // State is included in the agent's context
        return "Preferences loaded", nil
    })

Callbacks & Observability

On Each Step

agent.OnStep(func(step ai.AgentStep) {
    log.Printf("Step %d: action=%s, tokens=%d",
        step.Number, step.Action, step.Tokens)
})

On Thoughts

agent.OnThought(func(thought string) {
    fmt.Printf("💭 %s\n", thought)
})

On Actions

agent.OnAction(func(action string, input map[string]any) {
    fmt.Printf("🔧 Calling %s with %v\n", action, input)
})

On Observations

agent.OnObservation(func(action, result string) {
    fmt.Printf("👁 %s returned: %s\n", action, result)
})

On Completion

agent.OnComplete(func(result ai.AgentResult) {
    log.Printf("Agent completed in %v with %d steps",
        result.Duration, result.TotalSteps)
})

Human-in-the-Loop

Require approval before executing actions:

agent.RequireApproval(func(step ai.AgentStep) bool {
    fmt.Printf("Agent wants to call %s with %v\n", step.Action, step.ActionInput)
    fmt.Print("Approve? (y/n): ")
    
    var input string
    fmt.Scanln(&input)
    return input == "y" || input == "yes"
})

Working with Results

Basic Usage

result := agent.Run("Find the capital of France")

if result.Success() {
    fmt.Println("Answer:", result.Answer)
} else {
    fmt.Println("Error:", result.Error)
}

Accessing Steps

for _, step := range result.Steps {
    fmt.Printf("Step %d:\n", step.Number)
    if step.Action != "" {
        fmt.Printf("  Action: %s\n", step.Action)
        fmt.Printf("  Input: %v\n", step.ActionInput)
        fmt.Printf("  Observation: %s\n", step.Observation)
    }
}

Metadata

fmt.Printf("Total steps: %d\n", result.TotalSteps)
fmt.Printf("Duration: %v\n", result.Duration)
fmt.Printf("Tokens used: %d\n", result.TotalTokens)

Complete Example

package main

import (
    "fmt"
    ai "gopkg.in/dragon-born/go-llm.v1"
)

func main() {
    // Define tools
    searchTool := func(args map[string]any) (string, error) {
        query := args["query"].(string)
        // Simulate search results
        return fmt.Sprintf("Search results for '%s': ...", query), nil
    }

    calcTool := func(args map[string]any) (string, error) {
        expr := args["expression"].(string)
        // Evaluate expression
        return "42", nil
    }

    // Create and run agent
    result := ai.GPT5().
        System("You are a research assistant. Be thorough but concise.").
        ThinkHigh().
        Agent().
        Tool("search", "Search for information", 
            ai.Params().String("query", "Search query", true).Build(),
            searchTool).
        Tool("calculate", "Evaluate math expression",
            ai.Params().String("expression", "Math expression", true).Build(),
            calcTool).
        MaxSteps(15).
        OnStep(func(s ai.AgentStep) {
            fmt.Printf("📍 Step %d: %s\n", s.Number, s.Action)
        }).
        Run("What is 15% of the US population?")

    if result.Success() {
        fmt.Printf("\n✅ Answer: %s\n", result.Answer)
        fmt.Printf("   Completed in %d steps, %v\n", result.TotalSteps, result.Duration)
    } else {
        fmt.Printf("❌ Error: %v\n", result.Error)
    }
}

Best Practices

  1. Keep tools focused - Each tool should do one thing well
  2. Return structured data - Make tool outputs easy for the model to parse
  3. Set reasonable limits - Use MaxSteps and Timeout to prevent runaway agents
  4. Log everything - Use callbacks for observability in production
  5. Handle errors gracefully - Tool errors become observations the agent can work with
  6. Use state sparingly - Only pass what's necessary for the task

Clone this wiki locally