gains

package module
v0.2.11 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 23, 2025 License: MIT Imports: 9 Imported by: 0

README

gains mascot

gains

Go AI Native Scaffold - A Go-idiomatic generative AI library. Not yet production ready.

gains provides a unified interface for building AI applications across Anthropic, OpenAI, and Google. Built from the ground up for Go with first-class streaming, tool orchestration, and composable workflows.

Most AI agent frameworks either don't support Go or treat it as an afterthought. gains was built to give Go developers a first-class experience.

Principles

  • Go Idiomatic - Follows Go conventions: interfaces, functional options, channels, context
  • Type Safe - Generics and typed keys wherever possible to catch errors at compile time
  • Composable - Small, focused components that combine into larger systems
  • Flexible - Sensible defaults with full control when you need it
  • Easy to Use - Trivial for simple cases, capable for complex problems

Features

  • Model-Centric Routing - Models know their provider; client routes automatically
  • Unified Client - Single interface for chat, embeddings, and image generation
  • Agent Orchestration - Autonomous tool-calling loops with approval workflows
  • Composable Workflows - Chain, Parallel, Router, and Loop patterns for complex pipelines
  • Built-in Tools - File, HTTP, search, and client tools ready to use
  • AG-UI Protocol - Frontend integration via event mapping and shared state
  • A2A Protocol - Agent-to-agent communication (testing)
  • MCP Protocol - Model Context Protocol for tool interoperability (testing)
  • Streaming First - Channel-based streaming throughout the entire API
  • Automatic Retry - Exponential backoff with jitter for transient errors

Installation

go get github.com/spetersoncode/gains

Import Convention

We recommend importing with the ai alias for cleaner, more readable code:

import ai "github.com/spetersoncode/gains"

// Now you can write:
msg := ai.Message{Role: ai.RoleUser, Content: "Hello"}

Quick Start

package main

import (
    "context"
    "fmt"
    "os"

    ai "github.com/spetersoncode/gains"
    "github.com/spetersoncode/gains/client"
    "github.com/spetersoncode/gains/model"
)

func main() {
    ctx := context.Background()

    c := client.New(client.Config{
        APIKeys: client.APIKeys{
            Anthropic: os.Getenv("ANTHROPIC_API_KEY"),
        },
        Defaults: client.Defaults{
            Chat: model.ClaudeSonnet45,
        },
    })

    resp, _ := c.Chat(ctx, []ai.Message{
        {Role: ai.RoleUser, Content: "Hello!"},
    })

    fmt.Println(resp.Content)
}

Providers

Models determine their provider automatically. Configure API keys for the providers you use:

Provider Chat Images Embeddings
Anthropic - -
OpenAI
Google
c := client.New(client.Config{
    APIKeys: client.APIKeys{
        Anthropic: os.Getenv("ANTHROPIC_API_KEY"),
        OpenAI:    os.Getenv("OPENAI_API_KEY"),
        Google:    os.Getenv("GOOGLE_API_KEY"),
    },
    Defaults: client.Defaults{
        Chat:      model.ClaudeSonnet45,      // Routes to Anthropic
        Embedding: model.TextEmbedding3Small, // Routes to OpenAI
        Image:     model.Imagen4,             // Routes to Google
    },
})

// Uses default model (ClaudeSonnet45 -> Anthropic)
resp, _ := c.Chat(ctx, messages)

// Override with different model (routes to OpenAI)
resp, _ = c.Chat(ctx, messages, ai.WithModel(model.GPT52))

Chat & Streaming

// Basic chat
resp, _ := c.Chat(ctx, messages)
fmt.Println(resp.Content)

// Streaming
stream, _ := c.ChatStream(ctx, messages)
for event := range stream {
    if event.Err != nil {
        break
    }
    fmt.Print(event.Delta)
}

Schema Generation

Define schemas using struct tags. The library auto-generates JSON schemas from Go structs:

type WeatherArgs struct {
    Location string `json:"location" desc:"City name" required:"true"`
    Unit     string `json:"unit" enum:"celsius,fahrenheit"`
    Days     int    `json:"days" min:"1" max:"7"`
}

// Generate schema from struct tags
schema := ai.MustSchemaFor[WeatherArgs]()

Supported tags: json, desc, required, enum, min, max, minLength, maxLength, pattern, default, minItems, maxItems

Agent Orchestration

The agent package handles autonomous tool-calling loops:

import (
    "github.com/spetersoncode/gains/agent"
    "github.com/spetersoncode/gains/tool"
)

type SearchArgs struct {
    Query string `json:"query"`
}

// Create a tool registry
registry := tool.NewRegistry()
tool.MustRegisterFunc(registry, "search", "Search the web",
    func(ctx context.Context, args SearchArgs) (string, error) {
        return "search results for: " + args.Query, nil
    },
)

// Create and run agent
a := agent.New(c, registry)

result, _ := a.Run(ctx, messages,
    agent.WithMaxSteps(10),
    agent.WithTimeout(2*time.Minute),
)
fmt.Println(result.Response.Content)
Human-in-the-Loop

Require approval for sensitive operations:

result, _ := a.Run(ctx, messages,
    agent.WithApprovalRequired("delete_file", "send_email"),
    agent.WithApprover(func(ctx context.Context, call ai.ToolCall) (bool, string) {
        fmt.Printf("Allow %s? [y/n]: ", call.Name)
        // Get user input...
        return approved, ""
    }),
)

Workflows

Build complex pipelines with composable patterns. See docs/workflows.md for comprehensive documentation.

import "github.com/spetersoncode/gains/workflow"

// Chain - sequential execution
chain := workflow.NewChain("pipeline",
    workflow.NewPromptStep("analyze", c, analyzePrompt, "analysis"),
    workflow.NewPromptStep("summarize", c, summarizePrompt, "summary"),
)

// Parallel - concurrent execution
parallel := workflow.NewParallel("research",
    []workflow.Step{step1, step2, step3},
    aggregator,
)

// Router - conditional branching
router := workflow.NewRouter("route",
    []workflow.Route{
        {Name: "question", Condition: isQuestion, Step: questionHandler},
    },
    defaultHandler,
)

// Execute workflow
wf := workflow.New("my-workflow", chain)
result, _ := wf.Run(ctx, workflow.NewState(nil))
Typed Workflow Steps

Use TypedPromptStep[T] with Key[T] for compile-time type safety:

type Analysis struct {
    Sentiment  string   `json:"sentiment"`
    Keywords   []string `json:"keywords"`
}

// Define typed key
var KeyAnalysis = workflow.NewKey[*Analysis]("analysis")

// Create typed step - result auto-unmarshaled
step := workflow.NewTypedPromptStep[Analysis](
    "analyze", c, promptFn, responseSchema, KeyAnalysis.Name(),
)

// Type-safe state access
analysis, ok := workflow.Get(state, KeyAnalysis)
analysis = workflow.MustGet(state, KeyAnalysis)

Built-in Tools

The tool package provides ready-to-use tools:

import "github.com/spetersoncode/gains/tool"

// File tools: read_file, write_file, list_directory, edit_file
fileTools := tool.FileTools(tool.WithBasePath("/allowed/path"))

// HTTP tool: http_request
httpTool := tool.WebTools(tool.WithAllowedHosts("api.example.com"))

// Search tool: search_files
searchTools := tool.SearchTools()

// Client tools: generate_image, embed_text, ask_assistant
clientTools := tool.ClientTools(c)

// Register all tools
tool.RegisterAll(registry, tool.StandardTools())

AG-UI Protocol

The agui package maps gains events to AG-UI format for frontend integration:

import "github.com/spetersoncode/gains/agui"

mapper := agui.NewMapper(threadID, runID)
writeEvent(mapper.RunStarted())

for event := range agent.RunStream(ctx, messages) {
    for _, aguiEvent := range mapper.MapEvent(event) {
        writeEvent(aguiEvent)
    }
}

writeEvent(mapper.RunFinished())

Structured Output

type Result struct {
    Name  string `json:"name" required:"true"`
    Score int    `json:"score" min:"0" max:"100"`
}

resp, _ := c.Chat(ctx, messages,
    ai.WithResponseSchema(ai.ResponseSchema{
        Name:   "result",
        Schema: ai.MustSchemaFor[Result](),
    }),
)

Embeddings & Images

// Embeddings
resp, _ := c.Embed(ctx, []string{"Hello world"})
fmt.Printf("Dimensions: %d\n", len(resp.Embeddings[0]))

// Image generation
resp, _ := c.GenerateImage(ctx, "A sunset over mountains",
    ai.WithImageSize(ai.ImageSize1024x1024),
)
fmt.Println(resp.Images[0].URL)

Models

The model package provides type-safe model selection:

import "github.com/spetersoncode/gains/model"

// Auto-updating aliases
ai.WithModel(model.ClaudeSonnet45)  // Anthropic
ai.WithModel(model.GPT52)           // OpenAI
ai.WithModel(model.Gemini25Flash)   // Google

// Pinned versions for stability
ai.WithModel(model.ClaudeSonnet45_20250929)

Request Options

resp, _ := c.Chat(ctx, messages,
    ai.WithModel(model.ClaudeOpus45),
    ai.WithMaxTokens(4096),
    ai.WithTemperature(0.7),
    ai.WithTools(tools),
    ai.WithToolChoice(ai.ToolChoiceAuto),
)

Configuration

Retry
c := client.New(client.Config{
    APIKeys: client.APIKeys{OpenAI: os.Getenv("OPENAI_API_KEY")},
    RetryConfig: &retry.Config{
        MaxAttempts:  5,
        InitialDelay: time.Second,
        MaxDelay:     30 * time.Second,
    },
})
Events
events := make(chan client.Event, 100)
c := client.New(client.Config{
    APIKeys: client.APIKeys{OpenAI: os.Getenv("OPENAI_API_KEY")},
    Events:  events,
})

go func() {
    for e := range events {
        fmt.Printf("[%s] %s %v\n", e.Type, e.Operation, e.Duration)
    }
}()

Environment Variables

Provider Variable
Anthropic ANTHROPIC_API_KEY
OpenAI OPENAI_API_KEY
Google GOOGLE_API_KEY

Examples

See the cmd/demo directory for complete examples including:

  • Basic chat and streaming
  • Agent orchestration
  • Multi-agent scenarios
  • Workflow patterns (chain, parallel, router, loop)
  • AG-UI integration
  • Structured output
  • Vision and embeddings
AG-UI Server

The cmd/serve directory contains a reference HTTP server that exposes a gains agent via the AG-UI protocol over SSE.

Features:

  • ✅ Chat streaming
  • ✅ Client-side tools
  • ✅ Server-side tools
  • ✅ Generative UI elements
  • ✅ Shared state
  • ✅ Human in the loop
GAINS_PROVIDER=anthropic go run ./cmd/serve
# POST http://localhost:8000/api/agent

License

MIT

Documentation

Overview

Package gains provides a unified interface for interacting with LLM providers.

The gains library abstracts away provider-specific APIs, allowing you to write code once and use models from Anthropic (Claude), OpenAI (GPT), and Google (Gemini). Models know their provider, so routing happens automatically.

Import Convention

We recommend importing with the "ai" alias for cleaner code:

import ai "github.com/spetersoncode/gains"

All examples in this documentation use this convention.

Core Types

The library defines these key types:

  • Provider: Identifies a provider (Anthropic, OpenAI, Google)
  • Model: Interface for models that know their provider
  • Message: Conversation messages with roles and content
  • Response: Chat responses with content, tool calls, and usage

Use the github.com/spetersoncode/gains/client package as the entry point and the github.com/spetersoncode/gains/model package for model selection.

Basic Usage

Create a client with API keys and default models:

c := client.New(client.Config{
    APIKeys: client.APIKeys{
        Anthropic: os.Getenv("ANTHROPIC_API_KEY"),
    },
    Defaults: client.Defaults{
        Chat: model.ClaudeSonnet45,
    },
})

messages := []ai.Message{
    {Role: ai.RoleUser, Content: "What is the capital of France?"},
}

resp, err := c.Chat(ctx, messages)
if err != nil {
    log.Fatal(err)
}
fmt.Println(resp.Content)

Model-Centric Routing

Models determine their provider. Override the default with WithModel:

// Uses default (routes to Anthropic)
resp, _ := c.Chat(ctx, messages)

// Override with GPT (routes to OpenAI)
resp, _ := c.Chat(ctx, messages, ai.WithModel(model.GPT52))

Streaming Responses

For real-time output, use ChatStream:

stream, err := c.ChatStream(ctx, messages)
if err != nil {
    log.Fatal(err)
}

for event := range stream {
    if event.Err != nil {
        log.Fatal(event.Err)
    }
    fmt.Print(event.Delta)
}

Configuration Options

Customize requests with functional options:

resp, err := c.Chat(ctx, messages,
    ai.WithModel(model.ClaudeOpus45),
    ai.WithMaxTokens(1000),
    ai.WithTemperature(0.7),
)

Higher-Level Abstractions

For more complex use cases, see:

Index

Constants

This section is empty.

Variables

View Source
var ErrEmptyInput = errors.New("empty input")

ErrEmptyInput is returned when a required input slice is empty.

Functions

func GenerateMessageID added in v0.2.4

func GenerateMessageID() string

GenerateMessageID creates a unique message identifier.

func IsPermanent added in v0.2.4

func IsPermanent(err error) bool

IsPermanent returns true if the error is categorized as permanent. It checks if the error or any wrapped error implements CategorizedError.

func IsTransient added in v0.2.4

func IsTransient(err error) bool

IsTransient returns true if the error is categorized as transient. It checks if the error or any wrapped error implements CategorizedError.

func IsUserInput added in v0.2.4

func IsUserInput(err error) bool

IsUserInput returns true if the error is categorized as user input error. It checks if the error or any wrapped error implements CategorizedError.

func ModelSupportsImageOutput added in v0.2.10

func ModelSupportsImageOutput(m Model) bool

ModelSupportsImageOutput checks if a model supports image output. Returns true if the model implements ImageOutputCapable and returns true.

func MustSchemaFor added in v0.2.4

func MustSchemaFor[T any]() json.RawMessage

MustSchemaFor is like SchemaFor but panics on error.

func RetryAfterOf added in v0.2.4

func RetryAfterOf(err error) time.Duration

RetryAfterOf returns the retry delay from a categorized error, or 0.

func SchemaFor added in v0.2.4

func SchemaFor[T any]() (json.RawMessage, error)

SchemaFor generates a JSON schema from a struct type T. The schema is generated by inspecting struct field tags.

Supported tags:

  • json:"name" - Property name (required for inclusion)
  • desc:"text" - Description
  • required:"true" - Mark as required
  • enum:"a,b,c" - Enum values (comma-separated)
  • min:"0" - Minimum value (numbers)
  • max:"100" - Maximum value (numbers)
  • minLength:"1" - Minimum string length
  • maxLength:"100" - Maximum string length
  • pattern:"regex" - String pattern
  • default:"value" - Default value
  • minItems:"1" - Minimum array items
  • maxItems:"10" - Maximum array items

Example:

type Args struct {
    Query  string `json:"query" desc:"Search query" required:"true"`
    Limit  int    `json:"limit" desc:"Max results" min:"1" max:"100"`
}

schema := gains.MustSchemaFor[Args]()

func StatusCodeOf added in v0.2.4

func StatusCodeOf(err error) int

StatusCodeOf returns the HTTP status code from a categorized error, or 0.

Types

type CategorizedError added in v0.2.4

type CategorizedError interface {
	error
	Category() ErrorCategory
	Retryable() bool           // convenience: returns true if Category == ErrorTransient
	StatusCode() int           // HTTP status code if applicable, 0 otherwise
	RetryAfter() time.Duration // suggested retry delay from server, 0 if not available
}

CategorizedError is an error that provides information about how it should be handled.

type ChatProvider

type ChatProvider interface {
	// Chat sends a conversation and returns a complete response.
	Chat(ctx context.Context, messages []Message, opts ...Option) (*Response, error)

	// ChatStream sends a conversation and returns a channel of streaming events.
	// The channel is closed when the stream is complete or an error occurs.
	// Callers should check StreamEvent.Err for any errors.
	ChatStream(ctx context.Context, messages []Message, opts ...Option) (<-chan StreamEvent, error)
}

ChatProvider defines the interface for AI chat providers.

type ContentPart

type ContentPart struct {
	// Type indicates the content type: "text" or "image".
	Type ContentPartType `json:"type"`
	// Text contains the text content. Only used when Type is "text".
	Text string `json:"text,omitempty"`
	// ImageURL contains a URL to an image. Only used when Type is "image".
	// Mutually exclusive with Base64.
	ImageURL string `json:"imageUrl,omitempty"`
	// Base64 contains base64-encoded image data. Only used when Type is "image".
	// Mutually exclusive with ImageURL.
	Base64 string `json:"base64,omitempty"`
	// MimeType specifies the image format (e.g., "image/jpeg", "image/png").
	// Required when using Base64, optional for ImageURL (may be inferred).
	MimeType string `json:"mimeType,omitempty"`
}

ContentPart represents a single part of multimodal content. Use either Text (for text parts) or ImageURL/Base64 (for image parts).

func NewImageBase64Part

func NewImageBase64Part(base64Data, mimeType string) ContentPart

NewImageBase64Part creates an image content part from base64 data.

func NewImageURLPart

func NewImageURLPart(url string) ContentPart

NewImageURLPart creates an image content part from a URL.

func NewTextPart

func NewTextPart(text string) ContentPart

NewTextPart creates a text content part.

type ContentPartType

type ContentPartType string

ContentPartType represents the type of content in a multimodal message part.

const (
	ContentPartTypeText  ContentPartType = "text"
	ContentPartTypeImage ContentPartType = "image"
)

type EmbeddingOption

type EmbeddingOption func(*EmbeddingOptions)

EmbeddingOption is a functional option for configuring embedding requests.

func WithEmbeddingDimensions

func WithEmbeddingDimensions(dims int) EmbeddingOption

WithEmbeddingDimensions sets the output dimensions for the embedding vectors. Note: Only supported by OpenAI (text-embedding-3-*) and Google. For OpenAI, valid values depend on the model (e.g., 256, 512, 1024, 1536, 3072).

func WithEmbeddingModel

func WithEmbeddingModel(model Model) EmbeddingOption

WithEmbeddingModel sets the model to use for embedding generation.

func WithEmbeddingRetry added in v0.2.8

func WithEmbeddingRetry(cfg RetryConfig) EmbeddingOption

WithEmbeddingRetry overrides the client's default retry configuration for this request.

func WithEmbeddingRetryDisabled added in v0.2.8

func WithEmbeddingRetryDisabled() EmbeddingOption

WithEmbeddingRetryDisabled disables retry for this request (single attempt).

func WithEmbeddingTaskType

func WithEmbeddingTaskType(taskType EmbeddingTaskType) EmbeddingOption

WithEmbeddingTaskType sets the intended task type for embeddings. This helps the model optimize the embedding for specific use cases. Note: Only supported by Google; ignored by OpenAI.

type EmbeddingOptions

type EmbeddingOptions struct {
	Model       Model
	Dimensions  int
	TaskType    EmbeddingTaskType
	RetryConfig *RetryConfig // Per-call retry config override (nil = use client default)
}

EmbeddingOptions contains configuration for an embedding request.

func ApplyEmbeddingOptions

func ApplyEmbeddingOptions(opts ...EmbeddingOption) *EmbeddingOptions

ApplyEmbeddingOptions applies functional options to an EmbeddingOptions struct.

type EmbeddingProvider

type EmbeddingProvider interface {
	// Embed generates embeddings for the provided texts.
	// Returns an error if texts is empty.
	Embed(ctx context.Context, texts []string, opts ...EmbeddingOption) (*EmbeddingResponse, error)
}

EmbeddingProvider defines the interface for AI embedding providers.

type EmbeddingResponse

type EmbeddingResponse struct {
	// Embeddings contains one embedding vector per input text.
	// The order matches the input texts order.
	Embeddings [][]float64
	// Usage contains token usage information.
	Usage Usage
}

EmbeddingResponse represents a complete response from an embedding provider.

type EmbeddingTaskType

type EmbeddingTaskType string

EmbeddingTaskType specifies the intended use case for embeddings. This helps the model optimize the embedding for specific tasks. Note: Only supported by Google; ignored by OpenAI.

const (
	// EmbeddingTaskTypeRetrievalQuery optimizes for search queries.
	EmbeddingTaskTypeRetrievalQuery EmbeddingTaskType = "RETRIEVAL_QUERY"
	// EmbeddingTaskTypeRetrievalDocument optimizes for documents to be searched.
	EmbeddingTaskTypeRetrievalDocument EmbeddingTaskType = "RETRIEVAL_DOCUMENT"
	// EmbeddingTaskTypeSemanticSimilarity optimizes for measuring text similarity.
	EmbeddingTaskTypeSemanticSimilarity EmbeddingTaskType = "SEMANTIC_SIMILARITY"
	// EmbeddingTaskTypeClassification optimizes for classification tasks.
	EmbeddingTaskTypeClassification EmbeddingTaskType = "CLASSIFICATION"
	// EmbeddingTaskTypeClustering optimizes for clustering tasks.
	EmbeddingTaskTypeClustering EmbeddingTaskType = "CLUSTERING"
)

type Error added in v0.2.4

type Error struct {
	Msg        string
	Cat        ErrorCategory
	Code       int           // HTTP status code, 0 if not applicable
	RetryDelay time.Duration // from Retry-After header, 0 if not available
	Cause      error         // underlying error
}

Error is a categorized error with metadata for error handling decisions.

func NewPermanentError added in v0.2.4

func NewPermanentError(msg string, statusCode int, cause error) *Error

NewPermanentError creates a permanent error that should not be retried.

func NewTransientError added in v0.2.4

func NewTransientError(msg string, statusCode int, cause error) *Error

NewTransientError creates a transient error that can be retried.

func NewTransientErrorWithRetry added in v0.2.4

func NewTransientErrorWithRetry(msg string, statusCode int, retryAfter time.Duration, cause error) *Error

NewTransientErrorWithRetry creates a transient error with a suggested retry delay.

func NewUserInputError added in v0.2.4

func NewUserInputError(msg string, statusCode int, cause error) *Error

NewUserInputError creates an error indicating invalid user input.

func (*Error) Category added in v0.2.4

func (e *Error) Category() ErrorCategory

Category returns the error category.

func (*Error) Error added in v0.2.4

func (e *Error) Error() string

Error returns the error message.

func (*Error) RetryAfter added in v0.2.4

func (e *Error) RetryAfter() time.Duration

RetryAfter returns the suggested retry delay, or 0 if not available.

func (*Error) Retryable added in v0.2.4

func (e *Error) Retryable() bool

Retryable returns true if the error is transient and can be retried.

func (*Error) StatusCode added in v0.2.4

func (e *Error) StatusCode() int

StatusCode returns the HTTP status code, or 0 if not applicable.

func (*Error) Unwrap added in v0.2.4

func (e *Error) Unwrap() error

Unwrap returns the underlying error.

type ErrorCategory added in v0.2.4

type ErrorCategory string

ErrorCategory classifies errors by how they should be handled.

const (
	// ErrorTransient indicates the error is temporary and the operation can be retried.
	// Examples: rate limits, temporary network issues, server overload.
	ErrorTransient ErrorCategory = "transient"

	// ErrorPermanent indicates the error is not recoverable through retry.
	// Examples: invalid API key, insufficient permissions, model not found.
	ErrorPermanent ErrorCategory = "permanent"

	// ErrorUserInput indicates the user provided invalid input that must be corrected.
	// Examples: malformed request, invalid parameters, content policy violation.
	ErrorUserInput ErrorCategory = "user_input"
)

type GeneratedImage

type GeneratedImage struct {
	// URL contains the URL to the generated image (if URL format was requested).
	URL string
	// Base64 contains the base64-encoded image data (if Base64 format was requested).
	Base64 string
	// RevisedPrompt contains the prompt that was actually used.
	// DALL-E 3 rewrites prompts for better results.
	RevisedPrompt string
}

GeneratedImage represents a single generated image.

type ImageAspectRatio added in v0.2.11

type ImageAspectRatio string

ImageAspectRatio specifies the aspect ratio for generated images in chat responses. Only supported by Google/Vertex AI models with image output capability.

const (
	ImageAspectRatio1x1  ImageAspectRatio = "1:1"
	ImageAspectRatio2x3  ImageAspectRatio = "2:3"
	ImageAspectRatio3x2  ImageAspectRatio = "3:2"
	ImageAspectRatio3x4  ImageAspectRatio = "3:4"
	ImageAspectRatio4x3  ImageAspectRatio = "4:3"
	ImageAspectRatio9x16 ImageAspectRatio = "9:16"
	ImageAspectRatio16x9 ImageAspectRatio = "16:9"
	ImageAspectRatio21x9 ImageAspectRatio = "21:9"
)

type ImageError

type ImageError struct {
	Op  string // "decode" or "fetch"
	URL string // the image URL or "base64"
	Err error  // underlying error
}

ImageError represents an error during image processing.

func (*ImageError) Error

func (e *ImageError) Error() string

Error returns a formatted error message describing the image processing failure.

func (*ImageError) Unwrap

func (e *ImageError) Unwrap() error

Unwrap returns the underlying error for use with errors.Is and errors.As.

type ImageFormat

type ImageFormat string

ImageFormat specifies the output format for generated images.

const (
	// ImageFormatURL returns images as URLs.
	ImageFormatURL ImageFormat = "url"
	// ImageFormatBase64 returns images as base64-encoded data.
	ImageFormatBase64 ImageFormat = "b64_json"
)

type ImageOption

type ImageOption func(*ImageOptions)

ImageOption is a functional option for configuring image generation requests.

func WithImageCount

func WithImageCount(n int) ImageOption

WithImageCount sets the number of images to generate. Note: DALL-E 3 only supports n=1; Google Imagen supports up to 4.

func WithImageFormat

func WithImageFormat(f ImageFormat) ImageOption

WithImageFormat sets the output format for generated images. Supported values: "url", "b64_json"

func WithImageModel

func WithImageModel(model Model) ImageOption

WithImageModel sets the model to use for image generation.

func WithImageQuality

func WithImageQuality(q ImageQuality) ImageOption

WithImageQuality sets the quality level for generated images. Supported values: "standard", "hd" Note: Only supported by DALL-E 3.

func WithImageRetry added in v0.2.8

func WithImageRetry(cfg RetryConfig) ImageOption

WithImageRetry overrides the client's default retry configuration for this request.

func WithImageRetryDisabled added in v0.2.8

func WithImageRetryDisabled() ImageOption

WithImageRetryDisabled disables retry for this request (single attempt).

func WithImageSize

func WithImageSize(size ImageSize) ImageOption

WithImageSize sets the dimensions for generated images.

func WithImageStyle

func WithImageStyle(s ImageStyle) ImageOption

WithImageStyle sets the visual style for generated images. Supported values: "vivid", "natural" Note: Only supported by DALL-E 3.

type ImageOptions

type ImageOptions struct {
	Model       Model
	Size        ImageSize
	Count       int
	Quality     ImageQuality
	Style       ImageStyle
	Format      ImageFormat
	RetryConfig *RetryConfig // Per-call retry config override (nil = use client default)
}

ImageOptions contains configuration for an image generation request.

func ApplyImageOptions

func ApplyImageOptions(opts ...ImageOption) *ImageOptions

ApplyImageOptions applies functional options to an ImageOptions struct.

type ImageOutputCapable added in v0.2.10

type ImageOutputCapable interface {
	SupportsImageOutput() bool
}

ImageOutputCapable is an optional interface that models can implement to indicate they support image generation in chat responses.

type ImageOutputSize added in v0.2.11

type ImageOutputSize string

ImageOutputSize specifies the resolution for generated images in chat responses. Only supported by Google/Vertex AI models with image output capability.

const (
	ImageOutputSize1K ImageOutputSize = "1K" // Default
	ImageOutputSize2K ImageOutputSize = "2K"
	ImageOutputSize4K ImageOutputSize = "4K"
)

type ImageProvider

type ImageProvider interface {
	// GenerateImage creates images from a text prompt.
	GenerateImage(ctx context.Context, prompt string, opts ...ImageOption) (*ImageResponse, error)
}

ImageProvider defines the interface for AI image generation providers.

type ImageQuality

type ImageQuality string

ImageQuality specifies the quality level for generated images. Note: Only supported by DALL-E 3.

const (
	ImageQualityStandard ImageQuality = "standard"
	ImageQualityHD       ImageQuality = "hd"
)

type ImageResponse

type ImageResponse struct {
	Images []GeneratedImage
}

ImageResponse represents a complete response from an image generation provider.

type ImageSize

type ImageSize string

ImageSize represents predefined image dimensions.

const (
	ImageSize1024x1024 ImageSize = "1024x1024"
	ImageSize1024x1792 ImageSize = "1024x1792" // Portrait
	ImageSize1792x1024 ImageSize = "1792x1024" // Landscape
)

type ImageStyle

type ImageStyle string

ImageStyle specifies the visual style for generated images. Note: Only supported by DALL-E 3.

const (
	ImageStyleVivid   ImageStyle = "vivid"
	ImageStyleNatural ImageStyle = "natural"
)

type Message

type Message struct {
	// ID is an optional unique identifier for the message.
	// Used for message correlation and AG-UI protocol compatibility.
	ID      string `json:"id,omitempty"`
	Role    Role   `json:"role"`
	Content string `json:"content,omitempty"`
	// Parts contains multimodal content parts (text, images).
	// If populated, Content is ignored for providers that support multimodal.
	Parts []ContentPart `json:"parts,omitempty"`
	// ToolCalls contains tool invocation requests from an assistant message.
	// Only populated when Role is RoleAssistant and the model wants to use tools.
	ToolCalls []ToolCall `json:"toolCalls,omitempty"`
	// ToolResults contains results from tool executions.
	// Only populated when Role is RoleTool.
	ToolResults []ToolResult `json:"toolResults,omitempty"`
}

Message represents a single message in a conversation.

func NewToolResultMessage

func NewToolResultMessage(results ...ToolResult) Message

NewToolResultMessage creates a message containing tool results. This is a convenience function for returning tool results to the model.

func (Message) HasParts

func (m Message) HasParts() bool

HasParts returns true if the message has multimodal content parts.

type Model

type Model interface {
	String() string
	Provider() Provider
}

Model is an interface implemented by all provider model types. It allows strongly-typed model selection while maintaining a unified API. Every model must identify its provider for automatic routing.

type Option

type Option func(*Options)

Option is a functional option for configuring chat requests.

func WithImageAspectRatio added in v0.2.11

func WithImageAspectRatio(ratio ImageAspectRatio) Option

WithImageAspectRatio sets the aspect ratio for generated images in chat responses. Supported values: "1:1", "2:3", "3:2", "3:4", "4:3", "9:16", "16:9", "21:9". Note: Only supported by Google and Vertex AI with image output enabled.

func WithImageOutput added in v0.2.10

func WithImageOutput() Option

WithImageOutput enables image generation in chat responses. When enabled, models that support image output (e.g., Gemini image models) will include generated images in Response.Parts. Note: Only supported by Google and Vertex AI with specific models.

func WithImageOutputSize added in v0.2.11

func WithImageOutputSize(size ImageOutputSize) Option

WithImageOutputSize sets the resolution for generated images in chat responses. Supported values: "1K" (default), "2K", "4K". Note: Only supported by Google and Vertex AI with image output enabled.

func WithJSONMode

func WithJSONMode() Option

WithJSONMode forces the model to output valid JSON. Note: For Anthropic, this uses a tool-based approach since native JSON mode is not available.

func WithMaxTokens

func WithMaxTokens(n int) Option

WithMaxTokens sets the maximum number of tokens to generate.

func WithModel

func WithModel(model Model) Option

WithModel sets the model to use for the request.

func WithResponseSchema

func WithResponseSchema(schema ResponseSchema) Option

WithResponseSchema sets a JSON schema for structured output. This automatically enables JSON mode.

func WithRetry added in v0.2.8

func WithRetry(cfg RetryConfig) Option

WithRetry overrides the client's default retry configuration for this request. Use DefaultRetryConfig(), DisabledRetryConfig(), or NewRetryConfig() to create configs.

func WithRetryDisabled added in v0.2.8

func WithRetryDisabled() Option

WithRetryDisabled disables retry for this request (single attempt).

func WithTemperature

func WithTemperature(t float64) Option

WithTemperature sets the sampling temperature (0.0 to 2.0).

func WithToolChoice

func WithToolChoice(choice ToolChoice) Option

WithToolChoice controls how the model uses tools.

func WithTools

func WithTools(tools []Tool) Option

WithTools sets the tools available to the model. This is used internally by the agent package. For tool-calling use cases, prefer github.com/spetersoncode/gains/agent which handles the tool loop.

type Options

type Options struct {
	Model            Model
	MaxTokens        int
	Temperature      *float64
	Tools            []Tool
	ToolChoice       ToolChoice
	ResponseFormat   ResponseFormat
	ResponseSchema   *ResponseSchema
	RetryConfig      *RetryConfig     // Per-call retry config override (nil = use client default)
	ImageOutput      bool             // Enable image output for models that support it
	ImageAspectRatio ImageAspectRatio // Aspect ratio for generated images (Google/Vertex only)
	ImageOutputSize  ImageOutputSize  // Resolution for generated images (Google/Vertex only)
}

Options contains configuration for a chat request.

func ApplyOptions

func ApplyOptions(opts ...Option) *Options

ApplyOptions applies functional options to an Options struct.

type Provider

type Provider string

Provider identifies an AI provider.

const (
	ProviderAnthropic Provider = "anthropic"
	ProviderOpenAI    Provider = "openai"
	ProviderGoogle    Provider = "google"
	ProviderVertex    Provider = "vertex"
)

Supported providers.

func (Provider) String

func (p Provider) String() string

String returns the provider identifier.

type Response

type Response struct {
	Content      string `json:"content,omitempty"`
	FinishReason string `json:"finishReason,omitempty"`
	Usage        Usage  `json:"usage"`
	// ToolCalls contains any tool invocation requests from the model.
	// Check if len(ToolCalls) > 0 to determine if tools should be executed.
	ToolCalls []ToolCall `json:"toolCalls,omitempty"`
	// Parts contains multimodal output content (text, images).
	// Populated when the model generates non-text content (e.g., images).
	// For text-only responses, this may be empty and Content is used instead.
	Parts []ContentPart `json:"parts,omitempty"`
}

Response represents a complete response from a chat provider.

func (Response) HasParts added in v0.2.10

func (r Response) HasParts() bool

HasParts returns true if the response has multimodal content parts.

type ResponseFormat

type ResponseFormat string

ResponseFormat specifies how the model should format its response.

const (
	// ResponseFormatText is the default text response format.
	ResponseFormatText ResponseFormat = "text"
	// ResponseFormatJSON forces the model to output valid JSON.
	ResponseFormatJSON ResponseFormat = "json"
)

type ResponseSchema

type ResponseSchema struct {
	// Name is a descriptive name for the schema (required by some providers).
	Name string
	// Description explains what this schema represents (optional).
	Description string
	// Schema is the JSON Schema definition.
	Schema json.RawMessage
	// Strict enables strict schema enforcement (OpenAI only, defaults to true).
	Strict bool
}

ResponseSchema defines a JSON schema for structured output.

type RetryConfig added in v0.2.8

type RetryConfig struct {
	// MaxAttempts is the maximum number of attempts (default: 10).
	// The initial request counts as attempt 1.
	MaxAttempts int

	// InitialDelay is the base delay before the first retry (default: 1s).
	InitialDelay time.Duration

	// MaxDelay is the maximum delay between retries (default: 60s).
	MaxDelay time.Duration

	// Multiplier is the exponential backoff multiplier (default: 2.0).
	Multiplier float64

	// Jitter adds randomness to prevent thundering herd (default: 0.1 = 10%).
	// Delay is multiplied by (1 + random(-jitter, +jitter)).
	Jitter float64
}

RetryConfig holds retry configuration parameters. Use DefaultRetryConfig() for sensible defaults or create custom configs.

func DefaultRetryConfig added in v0.2.8

func DefaultRetryConfig() RetryConfig

DefaultRetryConfig returns the default retry configuration.

  • 10 max attempts
  • 1 second initial delay
  • 60 second max delay
  • 2x exponential multiplier
  • 10% jitter

func DisabledRetryConfig added in v0.2.8

func DisabledRetryConfig() RetryConfig

DisabledRetryConfig returns a configuration that disables retries (single attempt).

func NewRetryConfig added in v0.2.8

func NewRetryConfig(maxAttempts int, initialDelay, maxDelay time.Duration, multiplier, jitter float64) RetryConfig

NewRetryConfig creates a custom retry configuration. Parameters:

  • maxAttempts: maximum number of attempts (including initial request)
  • initialDelay: base delay before first retry
  • maxDelay: maximum delay between retries
  • multiplier: exponential backoff multiplier (e.g., 2.0 doubles delay each retry)
  • jitter: random jitter factor (e.g., 0.1 adds ±10% randomness)

type Role

type Role string

Role represents the role of a message sender in a conversation.

const (
	RoleUser      Role = "user"
	RoleAssistant Role = "assistant"
	RoleSystem    Role = "system"
	RoleTool      Role = "tool"
)

type StreamEvent

type StreamEvent struct {
	// Delta contains the incremental content for this event.
	Delta string
	// Done indicates if this is the final event in the stream.
	Done bool
	// Response contains the final response data when Done is true.
	Response *Response
	// Err contains any error that occurred during streaming.
	Err error
}

StreamEvent represents a single event in a streaming response.

type Tool

type Tool struct {
	// Name is the unique identifier for the tool.
	Name string
	// Description explains what the tool does (helps the model decide when to use it).
	Description string
	// Parameters is a JSON Schema object defining the function parameters.
	Parameters json.RawMessage
}

Tool defines a function that can be called by the model.

type ToolCall

type ToolCall struct {
	// ID is a unique identifier for this tool call (used to match results).
	ID string `json:"id"`
	// Name is the name of the tool to invoke.
	Name string `json:"name"`
	// Arguments is a JSON string containing the arguments to pass.
	Arguments string `json:"arguments"`
}

ToolCall represents a request from the model to invoke a tool.

type ToolChoice

type ToolChoice string

ToolChoice controls how the model uses tools.

const (
	// ToolChoiceAuto lets the model decide when to use tools (default).
	ToolChoiceAuto ToolChoice = "auto"
	// ToolChoiceNone disables tool use for the request.
	ToolChoiceNone ToolChoice = "none"
	// ToolChoiceRequired forces the model to use a tool.
	ToolChoiceRequired ToolChoice = "required"
)

type ToolResult

type ToolResult struct {
	// ToolCallID matches the ID from the corresponding ToolCall.
	ToolCallID string `json:"toolCallId"`
	// Content is the result content to return to the model.
	Content string `json:"content"`
	// IsError indicates if the result represents an error.
	IsError bool `json:"isError,omitempty"`
}

ToolResult represents the result of executing a tool call.

type UnmarshalError added in v0.2.6

type UnmarshalError struct {
	Content    string // Raw response content for debugging
	TargetType string // The type we tried to unmarshal into
	Context    string // Optional context (e.g., step name) for error messages
	Err        error  // The underlying unmarshal error
}

UnmarshalError is returned when an LLM response cannot be unmarshaled into the expected type.

func (*UnmarshalError) Error added in v0.2.6

func (e *UnmarshalError) Error() string

Error returns a formatted error message.

func (*UnmarshalError) Unwrap added in v0.2.6

func (e *UnmarshalError) Unwrap() error

Unwrap returns the underlying error for use with errors.Is and errors.As.

type Usage

type Usage struct {
	InputTokens  int `json:"inputTokens"`
	OutputTokens int `json:"outputTokens"`
}

Usage contains token usage information for a request.

Directories

Path Synopsis
Package a2a provides utilities for integrating gains with the A2A (Agent-to-Agent) protocol.
Package a2a provides utilities for integrating gains with the A2A (Agent-to-Agent) protocol.
Package agent provides autonomous tool-calling agent functionality for the gains library.
Package agent provides autonomous tool-calling agent functionality for the gains library.
Package agui provides utilities for integrating gains with the AG-UI protocol.
Package agui provides utilities for integrating gains with the AG-UI protocol.
Package chat provides the canonical ChatClient interface.
Package chat provides the canonical ChatClient interface.
Package client provides a unified multi-provider client for AI capabilities.
Package client provides a unified multi-provider client for AI capabilities.
cmd
demo command
mcp command
Command mcp is a reference MCP server that exposes gains tools over stdio.
Command mcp is a reference MCP server that exposes gains tools over stdio.
serve command
Package main provides a reference AG-UI HTTP server that exposes a gains agent via the AG-UI protocol over Server-Sent Events (SSE).
Package main provides a reference AG-UI HTTP server that exposes a gains agent via the AG-UI protocol over Server-Sent Events (SSE).
Package event provides a unified event system for streaming responses across client, agent, and workflow packages.
Package event provides a unified event system for streaming responses across client, agent, and workflow packages.
internal
provider/anthropic
Package anthropic provides an Anthropic Claude API client implementing [gains.ChatProvider].
Package anthropic provides an Anthropic Claude API client implementing [gains.ChatProvider].
provider/google
Package google provides a Google Gemini API client implementing gains provider interfaces.
Package google provides a Google Gemini API client implementing gains provider interfaces.
provider/openai
Package openai provides an OpenAI API client implementing gains provider interfaces.
Package openai provides an OpenAI API client implementing gains provider interfaces.
provider/vertex
Package vertex provides a Vertex AI client for the gains library.
Package vertex provides a Vertex AI client for the gains library.
retry
Package retry provides retry logic with exponential backoff for transient errors.
Package retry provides retry logic with exponential backoff for transient errors.
store
Package store provides pluggable state management for gains workflows and agents.
Package store provides pluggable state management for gains workflows and agents.
Package mcp provides MCP (Model Context Protocol) integration for gains.
Package mcp provides MCP (Model Context Protocol) integration for gains.
Package model provides model constants for all supported AI providers.
Package model provides model constants for all supported AI providers.
Package tool provides tool infrastructure for the gains library.
Package tool provides tool infrastructure for the gains library.
Package workflow provides composable patterns for orchestrating AI-powered pipelines.
Package workflow provides composable patterns for orchestrating AI-powered pipelines.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL