Stablev1.0.0

Go SDK

github.com/skyaiapp/sdk-go

Official Go SDK, high-performance and concurrency-friendly, supports Go 1.21+.

Stable

The Go SDK is stable (v1.0). It follows SemVer with backwards-compatible minor releases.

Installation

go get github.com/skyaiapp/sdk-go
Requirements: Go 1.21+

Quick Start

package main

import (
    "context"
    "fmt"
    "log"
    "os"

    "github.com/skyaiapp/sdk-go"
)

func main() {
    // Initialize client
    client := skyai.NewClient(os.Getenv("SKYAIAPP_API_KEY"))

    // Make a routing request
    resp, err := client.Route(context.Background(), &skyai.RouteRequest{
        Goal:     skyai.GoalCost,
        Strategy: skyai.StrategyBalanced,
        Messages: []skyai.Message{
            {Role: "system", Content: "You are a helpful assistant."},
            {Role: "user", Content: "Hello, world!"},
        },
    })
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(resp.Choices[0].Message.Content)
    fmt.Printf("Model: %s\n", resp.Model)
    fmt.Printf("Cost: $%.6f\n", resp.Routing.CostUSD)
}

Core Features

Context & Cancellation

// With timeout
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

resp, err := client.Route(ctx, &skyai.RouteRequest{
    Goal:     skyai.GoalQuality,
    Messages: messages,
})

// With cancellation
ctx, cancel := context.WithCancel(context.Background())

go func() {
    // Cancel after some condition
    time.Sleep(5 * time.Second)
    cancel()
}()

resp, err := client.Route(ctx, req)
if errors.Is(err, context.Canceled) {
    fmt.Println("Request was cancelled")
}

Streaming

stream, err := client.RouteStream(ctx, &skyai.RouteRequest{
    Goal:     skyai.GoalQuality,
    Messages: messages,
})
if err != nil {
    log.Fatal(err)
}
defer stream.Close()

for {
    chunk, err := stream.Recv()
    if err == io.EOF {
        break
    }
    if err != nil {
        log.Fatal(err)
    }
    
    if chunk.Choices[0].Delta.Content != "" {
        fmt.Print(chunk.Choices[0].Delta.Content)
    }
}

// Get final usage
usage := stream.Usage()
fmt.Printf("\nTokens: %d\n", usage.TotalTokens)

Concurrent Requests

import (
    "golang.org/x/sync/errgroup"
)

func processBatch(queries []string) ([]string, error) {
    g, ctx := errgroup.WithContext(context.Background())
    results := make([]string, len(queries))

    for i, query := range queries {
        i, query := i, query // capture loop variables
        g.Go(func() error {
            resp, err := client.Route(ctx, &skyai.RouteRequest{
                Goal:     skyai.GoalCost,
                Messages: []skyai.Message{{Role: "user", Content: query}},
            })
            if err != nil {
                return err
            }
            results[i] = resp.Choices[0].Message.Content
            return nil
        })
    }

    if err := g.Wait(); err != nil {
        return nil, err
    }
    return results, nil
}

Agent Runtime

// Create an agent
agent := client.NewAgent(&skyai.AgentConfig{
    Tools:    []string{"web_search", "calculator"},
    MaxSteps: 10,
    Timeout:  2 * time.Minute,
})

// Run with step callback
result, err := agent.Run(ctx, &skyai.AgentRunRequest{
    Task: "Find the current Bitcoin price",
    OnStep: func(step skyai.AgentStep) {
        fmt.Printf("Step %d: %s (%dms)\n", 
            step.Number, step.Action, step.DurationMS)
    },
})
if err != nil {
    log.Fatal(err)
}

fmt.Println("Result:", result.Output)
fmt.Printf("Cost: $%.4f\n", result.Usage.TotalCostUSD)

Guardrails

resp, err := client.Route(ctx, &skyai.RouteRequest{
    Goal:     skyai.GoalQuality,
    Messages: messages,
    Guardrails: &skyai.Guardrails{
        PII: &skyai.PIIConfig{
            Enabled: true,
            Types:   []string{"email", "phone", "ssn"},
            Action:  skyai.PIIActionRedact,
        },
        Moderation: &skyai.ModerationConfig{
            Enabled:    true,
            Categories: []string{"hate", "violence"},
            Threshold:  0.7,
        },
    },
})

if resp.Guardrails != nil && resp.Guardrails.Blocked {
    fmt.Printf("Content blocked: %s\n", resp.Guardrails.Reason)
}

Error Handling

import "github.com/skyaiapp/sdk-go/errors"

resp, err := client.Route(ctx, req)
if err != nil {
    var rateLimitErr *errors.RateLimitError
    var authErr *errors.AuthenticationError
    var apiErr *errors.APIError

    switch {
    case errors.As(err, &rateLimitErr):
        fmt.Printf("Rate limited. Retry after %d seconds\n", rateLimitErr.RetryAfter)
        time.Sleep(time.Duration(rateLimitErr.RetryAfter) * time.Second)
    case errors.As(err, &authErr):
        log.Fatal("Invalid API key")
    case errors.As(err, &apiErr):
        fmt.Printf("API error %d: %s\n", apiErr.Code, apiErr.Message)
    default:
        log.Fatal(err)
    }
}

// With automatic retry
client := skyai.NewClient(
    os.Getenv("SKYAIAPP_API_KEY"),
    skyai.WithMaxRetries(3),
    skyai.WithRetryDelay(time.Second),
)

Client Options

client := skyai.NewClient(
    os.Getenv("SKYAIAPP_API_KEY"),
    
    // Custom base URL
    skyai.WithBaseURL("https://api.skyaiapp.com/v1"),
    
    // Custom HTTP client
    skyai.WithHTTPClient(&http.Client{
        Timeout: 60 * time.Second,
        Transport: &http.Transport{
            MaxIdleConns:        100,
            MaxIdleConnsPerHost: 10,
        },
    }),
    
    // Retry configuration
    skyai.WithMaxRetries(3),
    skyai.WithRetryDelay(time.Second),
    
    // Debug logging
    skyai.WithDebug(true),
)

See more examples

Full example projects available on GitHub

Was this page helpful?

Let us know how we can improve

Go SDK | SkyAIApp Docs — SkyAIApp