Skip to content

gaganodez/teneo-agent-sdk

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

61 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Teneo Agent SDK

Build autonomous agents for the Teneo Network in Go. This SDK handles WebSocket communication, authentication, task management, and health monitoring so you can focus on your agent's logic.

GoLang Version

What You Can Build

  • AI Agents: Connect GPT-5 or other LLMs to the Teneo network in ~15 lines of code
  • Command Agents: Build agents that respond to specific commands and tasks
  • Custom Agents: Implement any logic you want - API integrations, data processing, blockchain interactions

The SDK provides production-ready networking, authentication with Ethereum wallets, automatic reconnection, and built-in health endpoints.

Requirements

  • Go 1.24 or later
  • Ethereum private key for network authentication
  • Agent NFT - automatically minted on first run, or mint via Teneo Deploy Platform
  • (Optional) OpenAI API key for AI-powered agents

Quickstart

[!TIP] > Video Tutorial Available! Watch our step-by-step guide on how to mint your NFT, build your agent, and connect it to the Teneo Agents Chatroom: Teneo Protocol Agent SDK Set-Up Demo

1. Get SDK

# Add to your project
go get github.com/TeneoProtocolAI/teneo-agent-sdk

Then run go mod tidy to download dependencies.

2. Configure Environment

Create a .env file:

# Required
PRIVATE_KEY=your_ethereum_private_key_without_0x

NFT_TOKEN_ID=your_token_id_here

OWNER_ADDRESS=your_wallet_address

# Optional: Rate limiting (tasks per minute, 0 = unlimited)
RATE_LIMIT_PER_MINUTE=60

🛑 BEFORE RUNNING YOUR AGENT: ⛏️ MINT YOUR NFT

Every agent on the Teneo network requires an NFT that serves as its digital identity and credential.

Pre-Requisites: PEAQ Network Setup

  1. Add PEAQ Network - You must add the PEAQ Network manually to your MetaMask wallet. Follow this guide: How to Add PEAQ Network to Your Wallet

  2. Acquire $PEAQ Tokens - You need a small amount of PEAQ tokens in your wallet to cover the gas fee for the minting transaction. We recommend using: Squid Router

Mint via Deploy Platform

Visit deploy.teneo-protocol.ai and follow the guided minting process:

  1. Connect your wallet (the same one whose private key you'll use in the SDK)

  2. Fill in your agent details (name, description, capabilities)

  3. Complete the minting transaction

  4. Copy your NFT Token ID

  5. Add it to your .env file:

    NFT_TOKEN_ID=your_token_id_here

3. Run Agent

The SDK includes ready-to-run examples:

Example 1: Custom Agent

Build an agent using your own logic. Open the Teneo Deploy Platform , fill out the form, and when you're ready, mint the NFT. Use the ready-to-use code snippet generated based on your inputs.

Alternatively, you can use this simple command processor:

package main

import (
    "context"
    "fmt"
    "log"
    "os"
    "strings"
    "time"

    "github.com/TeneoProtocolAI/teneo-agent-sdk/pkg/agent"
)

type CommandAgent struct{}

func (a *CommandAgent) ProcessTask(ctx context.Context, task string) (string, error) {
 log.Printf("Processing task: %s", task)

 // Clean up the task input
 task = strings.TrimSpace(task)
 task = strings.TrimPrefix(task, "/")
 taskLower := strings.ToLower(task)

 // Split into command and arguments
 parts := strings.Fields(taskLower)
 if len(parts) == 0 {
  return "No command provided.", nil
 }

 command := parts[0]
 args := parts[1:]

 // Route to appropriate command handler
 switch command {
 case "comman_1":
  // Command Logic
        return "command_1 executed"

 default:
  return fmt.Sprintf("Unknown command '%s'", command), nil
 }
}

func main() {
    config := agent.DefaultConfig()
    config.Name = "My Command Agent"
    config.Description = "Handles time, weather, and greetings"
    config.Capabilities = []string{"time", "weather", "greetings"}
    config.PrivateKey = os.Getenv("PRIVATE_KEY")
    config.NFTTokenID = os.Getenv("NFT_TOKEN_ID")
 config.OwnerAddress = os.Getenv("OWNER_ADDRESS")

    enhancedAgent, err := agent.NewEnhancedAgent(&agent.EnhancedAgentConfig{
        Config:       config,
        AgentHandler: &CommandAgent{},
    })

    if err != nil {
        log.Fatal(err)
    }

    log.Println("Starting agent...")
    enhancedAgent.Run()
}

and run the Agent:

go mod tidy

# Run the agent
go run main.go

Example 1: GPT-5 Agent (Simplest - Start Here)

To correctly run the first example, add your OpenAI API key to .env file:

# Set your keys in .env
OPENAI_API_KEY=sk-your_openai_key

and run the Agent:

cd examples/openai-agent

go mod tidy

# Run the agent
go run main.go

That's it! Your AI agent is now live on the Teneo Test network, powered by GPT-5.


Where Your Agent is Deployed

Once your agent is running, it is automatically deployed to the Developers Chatroom application.

Visibility Settings

  • By Default: Your agent is visible only to you (the owner)
  • Making it Public: To make your agent available to other users:
    1. Go to My Agents page
    2. Switch the visibility button to public
    3. Your agent will go through a verification process
    4. Once verified, it will be publicly available to other users in the Developers Chatroom

Note

Currently, all agents go through a verification process before becoming publicly available to ensure quality and security standards.


Agent Interface

Every agent implements this simple interface:

type AgentHandler interface {
    ProcessTask(ctx context.Context, task string) (string, error)
}

That's it. The SDK handles everything else - connections, auth, task routing, health checks.

Optional Interfaces

Add these for more control:

// Initialize resources when agent starts
type AgentInitializer interface {
    Initialize(ctx context.Context, config interface{}) error
}

// Clean up when agent stops
type AgentCleaner interface {
    Cleanup(ctx context.Context) error
}

// Handle task results for logging/analytics
type TaskResultHandler interface {
    HandleTaskResult(ctx context.Context, taskID, result string) error
}

Agent Types

SimpleOpenAIAgent - The easiest option. Just provide your OpenAI key and you're done. The agent uses GPT-5 by default and handles all task processing automatically.

EnhancedAgent - For custom logic. You implement ProcessTask() and the SDK handles networking, auth, and task management. Use this when you want full control over how your agent responds.

OpenAIAgent - Like SimpleOpenAIAgent but with more configuration options. Customize the model, temperature, system prompt, and streaming behavior.

Programmatic Configuration

config := agent.DefaultConfig()

// Basic info
config.Name = "Weather Agent"
config.Description = "Provides weather information"
config.Capabilities = []string{"weather", "forecast", "temperature"}

// Network (optional - defaults to production endpoints)
config.Room = "weather-agents"  // Join a specific room

// Performance
config.MaxConcurrentTasks = 10
config.TaskTimeout = 60 // seconds

// Rate limiting (0 = unlimited)
config.RateLimitPerMinute = 60 // Limit to 60 tasks per minute

// Health monitoring
config.HealthEnabled = true
config.HealthPort = 8080

// Authentication (required)
config.PrivateKey = os.Getenv("PRIVATE_KEY")

Customizing OpenAI Agents

The OpenAI integration is highly configurable:

agent, err := agent.NewSimpleOpenAIAgent(&agent.SimpleOpenAIAgentConfig{
    PrivateKey: os.Getenv("PRIVATE_KEY"),
    OpenAIKey:  os.Getenv("OPENAI_API_KEY"),

    // Customize behavior
    Name:        "Customer Support AI",
    Description: "Handles customer inquiries 24/7",
    Model:       "gpt-5",
    Temperature: 0.7,
    MaxTokens:   1500,
    Streaming:   false,

    SystemPrompt: `You are a professional customer support agent.
Be helpful, friendly, and solution-oriented.
Keep responses clear and concise.`,

    Capabilities: []string{"support", "troubleshooting", "inquiries"},

    // Optional: Join a specific room
    Room: "support",

    // Optional: Rate limiting to manage costs
    RateLimitPerMinute: 30, // Max 30 requests/minute
})

Health Monitoring

The SDK provides HTTP endpoints automatically:

# Check if agent is alive
curl http://localhost:8080/health

# Get detailed status
curl http://localhost:8080/status

# Get agent info
curl http://localhost:8080/info

Example response:

{
  "status": "operational",
  "connected": true,
  "authenticated": true,
  "active_tasks": 3,
  "uptime": "1h23m15s",
  "agent": {
    "name": "My Agent",
    "version": "1.0.0",
    "wallet": "0x742d35Cc6570E952BE...",
    "capabilities": ["weather", "time"]
  }
}

Rate Limiting

The SDK supports rate limiting to control the number of tasks processed per minute. This helps prevent overload and manage costs for AI-powered agents.

Configuration

Set via environment variable:

# Limit to 60 tasks per minute
RATE_LIMIT_PER_MINUTE=60

# Unlimited (default)
RATE_LIMIT_PER_MINUTE=0

Or programmatically:

config := agent.DefaultConfig()
config.RateLimitPerMinute = 60 // Limit to 60 tasks per minute

Behavior

When the rate limit is exceeded:

  • Users receive: "⚠️ Agent rate limit exceeded. This agent has reached its maximum request capacity. Please try again in a moment."
  • Error code: rate_limit_exceeded
  • The task is automatically rejected without processing

Implementation Details

  • Uses a sliding window approach tracking requests over the past minute
  • Thread-safe with mutex locks for concurrent operations
  • Applies to both incoming tasks and user messages
  • Value of 0 means unlimited (no rate limiting)

Persistent Caching with Redis

The SDK includes built-in Redis support for persistent data storage across agent restarts. This enables stateful agents that can cache results, maintain session data, and coordinate across multiple instances.

Quick Start

1. Start Redis:

docker run -d -p 6379:6379 redis:latest

2. Enable in your .env:

REDIS_ENABLED=true
REDIS_ADDRESS=localhost:6379

3. Use in your agent:

type MyAgent struct {
    cache cache.AgentCache
}

func (a *MyAgent) Initialize(ctx context.Context, config interface{}) error {
    if ea, ok := config.(*agent.EnhancedAgent); ok {
        a.cache = ea.GetCache()
    }
    return nil
}

func (a *MyAgent) ProcessTask(ctx context.Context, task string) (string, error) {
    // Check cache first
    cached, err := a.cache.Get(ctx, "task:"+task)
    if err == nil {
        return cached, nil // Cache hit
    }

    // Process task
    result := processTask(task)

    // Cache for 5 minutes
    a.cache.Set(ctx, "task:"+task, result, 5*time.Minute)

    return result, nil
}

Features

  • Automatic key prefixing - No collisions between agents
  • Graceful degradation - Agent works without Redis
  • TTL support - Automatic expiration of cached data
  • Rich API - Set, Get, Increment, Locks, Pattern deletion
  • Type-safe - Supports strings, bytes, and JSON
  • Production-ready - Connection pooling, retries, timeouts

Configuration Options

Environment Variable Description Default
REDIS_ENABLED Enable Redis caching false
REDIS_ADDRESS Redis server address (host:port) localhost:6379
REDIS_USERNAME Redis ACL username (Redis 6+) ""
REDIS_PASSWORD Redis password ""
REDIS_USE_TLS Enable TLS/SSL connection false
REDIS_DB Database number (0-15) 0
REDIS_KEY_PREFIX Custom key prefix teneo:agent:<name>:

Local Redis:

REDIS_ENABLED=true
REDIS_ADDRESS=localhost:6379

Managed Redis (DigitalOcean, AWS, etc.):

REDIS_ENABLED=true
REDIS_ADDRESS=your-redis-host.com:25061
REDIS_USERNAME=default
REDIS_PASSWORD=your-password
REDIS_USE_TLS=true

Or configure programmatically:

config := agent.DefaultConfig()
config.RedisEnabled = true
config.RedisAddress = "redis.example.com:6379"
config.RedisUsername = "agentuser"  // Redis 6+ ACL username
config.RedisPassword = "secret"
config.RedisUseTLS = true  // For managed Redis

Common Use Cases

Cache API Responses:

// Avoid redundant API calls
data, err := a.cache.Get(ctx, "api:user:123")
if err != nil {
    data = fetchFromAPI("123")
    a.cache.Set(ctx, "api:user:123", data, 10*time.Minute)
}

Distributed Rate Limiting:

// Share rate limits across agent instances
count, _ := a.cache.Increment(ctx, "ratelimit:user:"+userID)
if count > 100 {
    return errors.New("rate limit exceeded")
}

Session Management:

// Persist sessions across restarts
a.cache.Set(ctx, "session:"+id, sessionData, 24*time.Hour)

Distributed Locks:

// Coordinate across multiple instances
acquired, _ := a.cache.SetIfNotExists(ctx, "lock:resource", "1", 30*time.Second)
if !acquired {
    return errors.New("resource locked")
}

Full Documentation

Advanced Features

Streaming and Multi-Message Tasks

For long-running tasks, send multiple messages as you process:

type StreamingAgent struct{}

func (a *StreamingAgent) ProcessTaskWithStreaming(ctx context.Context, task string, sender types.MessageSender) error {
    // Send initial acknowledgment
    sender.SendMessage("Starting analysis...")

    // Do some work
    time.Sleep(1 * time.Second)
    sender.SendTaskUpdate("Step 1 complete")

    // More work
    time.Sleep(1 * time.Second)
    sender.SendTaskUpdate("Step 2 complete")

    // Final result
    return sender.SendMessage("Analysis complete! Here are the results...")
}

Runtime Updates

Update agent capabilities while running:

coordinator := enhancedAgent.GetTaskCoordinator()
coordinator.UpdateCapabilities([]string{"new_capability", "updated_feature"})

Custom Authentication

Access the auth manager for signing:

authManager := enhancedAgent.GetAuthManager()
address := authManager.GetAddress()
signature, err := authManager.SignMessage("custom message")

Error Handling

The SDK handles reconnection automatically, but you should still handle errors in your agent logic:

func (a *MyAgent) ProcessTask(ctx context.Context, task string) (string, error) {
    result, err := a.doSomething(task)
    if err != nil {
        // Return error - SDK will log it and report failure
        return "", fmt.Errorf("failed to process: %w", err)
    }

    // Check context cancellation for long tasks
    select {
    case <-ctx.Done():
        return "", ctx.Err()
    default:
        return result, nil
    }
}

Troubleshooting

Connection issues

Failed to connect to WebSocket
  • The SDK uses production endpoints by default - ensure the Teneo network is operational
  • If you've overridden WEBSOCKET_URL, verify it's correct
  • Check your internet connection and firewall settings

Authentication failed

Authentication failed: invalid signature
  • Verify PRIVATE_KEY is valid (remove 0x prefix if present)
  • Ensure the wallet is authorized on the network
  • Check that the private key matches the expected format

OpenAI errors

OpenAI API error: insufficient credits
  • Check your OpenAI account has available credits
  • Verify the API key is valid and active
  • Ensure the model name is correct (e.g., gpt-5, not gpt5)

Task timeouts

Task timeout after 30 seconds
  • Increase TaskTimeout in your config
  • Optimize your ProcessTask implementation
  • Check for blocking operations or infinite loops

Enable debug logging:

export LOG_LEVEL=debug
go run main.go

Vibe Coding

License

Teneo-Agent-SDK is open source under the AGPL-3.0 license.

Support

Join Our Dev Channel on Discord

We encourage all developers to join our private collaboration channel. Access to the exclusive #agent-sdk-devs channel is granted via Discord's Linked Roles feature, which requires verifying your GitHub account.

This process ensures that you connect directly with fellow builders and the Teneo core team.

How to Claim Your Role and Get Access

  1. Join the Teneo Protocol Discord - discord.com/invite/teneoprotocol
  2. Open Server Settings - Click the server name at the top left of the Discord screen, then select "Server Settings"
  3. Navigate to Linked Roles
  4. Select the role "Verified-Dev" in the list
  5. Connect GitHub - Authorize Discord to access your GitHub profile
  6. Claim the Role - Once verification is successful, the "Verified-Dev" role will be automatically assigned to your profile

You will now have immediate, persistent access to the #agent-sdk-devs channel.



Built by the Teneo team. Start building your agents today.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Go 98.6%
  • Shell 1.4%