Tools - Extend Agent Capabilities
Give your agents access to external functionality with tools.
What are Tools?
Tools are functions that agents can call to interact with external systems, perform calculations, fetch data, and more. Agno-Go provides a flexible toolkit system for extending agent capabilities.
Built-in Tools
- Calculator: Basic math operations
- HTTP: Make web requests
- File: Read/write files with safety controls
- Google Sheets ⭐: Read/write Google Sheets data
- Claude Agent Skills ⭐ NEW (v1.2.6): Call Anthropic Agent Skills via
invoke_claude_skill - Tavily ⭐ NEW (v1.2.6): Perform quick answers and reader-mode extractions
- Gmail ⭐ NEW (v1.2.6): Mark messages as read or archive via Gmail API
- Jira Worklog ⭐ NEW (v1.2.6): Summarise and export Jira Cloud worklogs
- ElevenLabs Voice ⭐ NEW (v1.2.6): Generate speech audio clips on demand
Using Tools
Basic Example
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/rexleimo/agno-go/pkg/agno/agent"
"github.com/rexleimo/agno-go/pkg/agno/models/openai"
"github.com/rexleimo/agno-go/pkg/agno/tools/calculator"
"github.com/rexleimo/agno-go/pkg/agno/tools/toolkit"
)
func main() {
model, _ := openai.New("gpt-4o-mini", openai.Config{
APIKey: os.Getenv("OPENAI_API_KEY"),
})
agent, _ := agent.New(agent.Config{
Name: "Math Assistant",
Model: model,
Toolkits: []toolkit.Toolkit{calculator.New()},
})
output, _ := agent.Run(context.Background(), "What is 23 * 47?")
fmt.Println(output.Content) // Agent uses calculator automatically
}Calculator Tool
Perform mathematical operations.
Operations
add(a, b)- Additionsubtract(a, b)- Subtractionmultiply(a, b)- Multiplicationdivide(a, b)- Division
Example
import "github.com/rexleimo/agno-go/pkg/agno/tools/calculator"
agent, _ := agent.New(agent.Config{
Model: model,
Toolkits: []toolkit.Toolkit{calculator.New()},
})
// Agent will automatically use calculator
output, _ := agent.Run(ctx, "Calculate 15% tip on $85")HTTP Tool
Make HTTP requests to external APIs.
Methods
get(url)- HTTP GET requestpost(url, body)- HTTP POST request
Example
import "github.com/rexleimo/agno-go/pkg/agno/tools/http"
agent, _ := agent.New(agent.Config{
Model: model,
Toolkits: []toolkit.Toolkit{http.New()},
})
// Agent can fetch data from APIs
output, _ := agent.Run(ctx, "Get the latest GitHub status from https://www.githubstatus.com/api/v2/status.json")Configuration
Control allowed domains for security:
httpTool := http.New(http.Config{
AllowedDomains: []string{"api.github.com", "api.weather.com"},
Timeout: 10 * time.Second,
})File Tool
Read and write files with built-in safety controls.
Operations
read_file(path)- Read file contentwrite_file(path, content)- Write content to filelist_directory(path)- List directory contentsdelete_file(path)- Delete a file
Example
import "github.com/rexleimo/agno-go/pkg/agno/tools/file"
fileTool := file.New(file.Config{
AllowedPaths: []string{"/tmp", "./data"}, // Restrict access
MaxFileSize: 1024 * 1024, // 1MB limit
})
agent, _ := agent.New(agent.Config{
Model: model,
Toolkits: []toolkit.Toolkit{fileTool},
})
output, _ := agent.Run(ctx, "Read the contents of ./data/report.txt")Safety Features
- Path restrictions (whitelist)
- File size limits
- Read-only mode option
- Automatic path sanitization
Multiple Tools
Agents can use multiple tools:
agent, _ := agent.New(agent.Config{
Name: "Multi-Tool Agent",
Model: model,
Toolkits: []toolkit.Toolkit{
calculator.New(),
http.New(),
file.New(file.Config{
AllowedPaths: []string{"./data"},
}),
},
})
// Agent can now calculate, fetch data, and read files
output, _ := agent.Run(ctx,
"Fetch weather data, calculate average temperature, and save to file")Creating Custom Tools
Build your own tools by implementing the Toolkit interface.
Step 1: Create Toolkit Struct
package mytool
import "github.com/rexleimo/agno-go/pkg/agno/tools/toolkit"
type MyToolkit struct {
*toolkit.BaseToolkit
}
func New() *MyToolkit {
t := &MyToolkit{
BaseToolkit: toolkit.NewBaseToolkit("my_tools"),
}
// Register functions
t.RegisterFunction(&toolkit.Function{
Name: "greet",
Description: "Greet a person by name",
Parameters: map[string]toolkit.Parameter{
"name": {
Type: "string",
Description: "Person's name",
Required: true,
},
},
Handler: t.greet,
})
return t
}Step 2: Implement Handler
func (t *MyToolkit) greet(args map[string]interface{}) (interface{}, error) {
name, ok := args["name"].(string)
if !ok {
return nil, fmt.Errorf("name must be a string")
}
return fmt.Sprintf("Hello, %s!", name), nil
}Step 3: Use Your Tool
agent, _ := agent.New(agent.Config{
Model: model,
Toolkits: []toolkit.Toolkit{mytool.New()},
})
output, _ := agent.Run(ctx, "Greet Alice")
// Agent calls greet("Alice") and responds with "Hello, Alice!"Advanced Custom Tool Example
Database query tool:
type DatabaseToolkit struct {
*toolkit.BaseToolkit
db *sql.DB
}
func NewDatabaseToolkit(db *sql.DB) *DatabaseToolkit {
t := &DatabaseToolkit{
BaseToolkit: toolkit.NewBaseToolkit("database"),
db: db,
}
t.RegisterFunction(&toolkit.Function{
Name: "query_users",
Description: "Query users from database",
Parameters: map[string]toolkit.Parameter{
"limit": {
Type: "integer",
Description: "Maximum number of results",
Required: false,
},
},
Handler: t.queryUsers,
})
return t
}
func (t *DatabaseToolkit) queryUsers(args map[string]interface{}) (interface{}, error) {
limit := 10
if l, ok := args["limit"].(float64); ok {
limit = int(l)
}
rows, err := t.db.Query("SELECT id, name FROM users LIMIT ?", limit)
if err != nil {
return nil, err
}
defer rows.Close()
var users []map[string]interface{}
for rows.Next() {
var id int
var name string
rows.Scan(&id, &name)
users = append(users, map[string]interface{}{
"id": id,
"name": name,
})
}
return users, nil
}Tool Best Practices
1. Clear Descriptions
Help the agent understand when to use tools:
// Good ✅
Description: "Calculate the square root of a number. Use when user asks for square roots."
// Bad ❌
Description: "Math function"2. Validate Input
Always validate tool parameters:
func (t *MyToolkit) divide(args map[string]interface{}) (interface{}, error) {
b, ok := args["divisor"].(float64)
if !ok || b == 0 {
return nil, fmt.Errorf("divisor must be a non-zero number")
}
// ... perform division
}3. Error Handling
Return meaningful errors:
func (t *MyToolkit) fetchData(args map[string]interface{}) (interface{}, error) {
resp, err := http.Get(url)
if err != nil {
return nil, fmt.Errorf("failed to fetch data: %w", err)
}
// ... process response
}4. Security
Restrict tool capabilities:
// Whitelist allowed operations
fileTool := file.New(file.Config{
AllowedPaths: []string{"/safe/path"},
ReadOnly: true, // Prevent writes
})
// Validate domains
httpTool := http.New(http.Config{
AllowedDomains: []string{"api.trusted.com"},
})Tool Execution Flow
- User sends request to agent
- Agent (LLM) decides if tools are needed
- LLM generates tool call with parameters
- Agno-Go executes tool function
- Tool result returned to LLM
- LLM generates final response
Example Flow
User: "What is 25 * 17?"
↓
LLM: "I need to use calculator"
↓
Tool Call: multiply(25, 17)
↓
Tool Result: 425
↓
LLM: "The answer is 425"
↓
User receives: "The answer is 425"Troubleshooting
Agent Not Using Tools
Ensure clear instructions:
agent, _ := agent.New(agent.Config{
Model: model,
Toolkits: []toolkit.Toolkit{calculator.New()},
Instructions: "Use the calculator tool for any math operations.",
})Tool Errors
Check tool registration and parameter types:
// Tool expects float64 for numbers
args := map[string]interface{}{
"value": 42.0, // ✅ Correct
// "value": "42" // ❌ Wrong type
}Google Sheets Tool ⭐ NEW
Read and write data to Google Sheets using service account authentication.
Operations
read_range(spreadsheet_id, range)- Read data from specified rangewrite_range(spreadsheet_id, range, values)- Write data to specified rangeappend_rows(spreadsheet_id, range, values)- Append rows to spreadsheet
Setup
Create Service Account:
- Go to Google Cloud Console
- Create a service account
- Download JSON credentials file
Share Spreadsheet:
- Share your Google Sheet with the service account email
- Grant "Editor" permissions
Usage
import "github.com/rexleimo/agno-go/pkg/agno/tools/googlesheets"
// Load credentials from JSON file
sheetsTool, err := googlesheets.New(googlesheets.Config{
CredentialsFile: "./service-account.json",
})
// Or use JSON string
sheetsTool, err := googlesheets.New(googlesheets.Config{
CredentialsJSON: os.Getenv("GOOGLE_SHEETS_CREDENTIALS"),
})
agent, _ := agent.New(agent.Config{
Model: model,
Toolkits: []toolkit.Toolkit{sheetsTool},
})Example
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/rexleimo/agno-go/pkg/agno/agent"
"github.com/rexleimo/agno-go/pkg/agno/models/openai"
"github.com/rexleimo/agno-go/pkg/agno/tools/googlesheets"
"github.com/rexleimo/agno-go/pkg/agno/tools/toolkit"
)
func main() {
model, _ := openai.New("gpt-4o-mini", openai.Config{
APIKey: os.Getenv("OPENAI_API_KEY"),
})
sheetsTool, err := googlesheets.New(googlesheets.Config{
CredentialsFile: "./service-account.json",
})
if err != nil {
log.Fatal(err)
}
agent, _ := agent.New(agent.Config{
Name: "Data Analyst",
Model: model,
Toolkits: []toolkit.Toolkit{sheetsTool},
})
// Agent can read and analyze spreadsheet data
output, _ := agent.Run(context.Background(),
"Read the sales data from Sheet1!A1:D100 and summarize the total revenue")
fmt.Println(output.Content)
}Range Notation
Use standard A1 notation for ranges:
Sheet1!A1:B10- Cells A1 to B10 in Sheet1Sheet2!A:A- Entire column A in Sheet2Sheet1!1:5- Rows 1 to 5 in Sheet1
Security
- Service account authentication (no user interaction)
- Spreadsheet-level permissions
- Read/write access controlled by sharing settings
Next Steps
- Learn about Memory for conversation state
- Build Teams with specialized tool agents
- Explore Workflow for tool orchestration
- Check API Reference for detailed docs
Related Examples
- Simple Agent - Calculator tool usage
- Search Agent - HTTP tool for web search
- File Agent - File operations
