Skip to content

v0.10.0 — AX Integration for Intelligent Error Handling

Agent Experience (AX) integration bringing intelligent error handling, automatic retry with backoff, and seamless OmniVoice-core resilience support.

Highlights

  • Error Classification: Classify ElevenLabs API errors into actionable categories
  • Automatic Retry: TTS provider retries transient errors with exponential backoff
  • OmniVoice Integration: Helper functions bridge elevenlabs-go/ax with omnivoice-core/resilience

New Features

Error Classifier

The new omnivoice.Classifier classifies errors using both AX error codes and HTTP status codes:

import "github.com/plexusone/elevenlabs-go/omnivoice"

classifier := omnivoice.NewClassifier()
info := classifier.Classify(err)

// info.Category   = "rate_limit"
// info.Retryable  = true
// info.Code       = "RATE_LIMITED"
// info.Suggestion = "Wait and retry the request"

Error categories:

Category HTTP Codes Retryable Example
rate_limit 429 Yes Rate limit exceeded
server 500, 502, 503 Yes Internal server error
auth 401, 403 No Invalid API key
validation 400, 422 No Missing required field
not_found 404 No Voice not found

Automatic Retry in TTS Provider

The TTS provider now automatically retries transient errors:

import (
    elevenlabs "github.com/plexusone/elevenlabs-go"
    "github.com/plexusone/elevenlabs-go/omnivoice/tts"
    "github.com/plexusone/omnivoice-core/resilience"
)

client, _ := elevenlabs.NewClient(elevenlabs.WithAPIKey("..."))
provider := tts.NewWithClient(client)

// Configure retry behavior (optional - defaults are sensible)
provider.SetRetryConfig(resilience.RetryConfig{
    MaxAttempts: 5,
    Backoff: &resilience.ExponentialBackoff{
        Initial:    1 * time.Second,
        Max:        30 * time.Second,
        Multiplier: 2.0,
        Jitter:     0.1,
    },
    Classifier: provider.Classifier(),
    OnRetry: func(attempt int, err error, delay time.Duration) {
        log.Printf("Retry %d after %v: %v", attempt, delay, err)
    },
})

// Synthesize with automatic retry
result, err := provider.Synthesize(ctx, "Hello world", config)

Default retry behavior:

  • Max Attempts: 3
  • Initial Delay: 1 second
  • Max Delay: 30 seconds
  • Backoff Multiplier: 2.0
  • Jitter: 10%

OmniVoice Helper Functions

New ax/omnivoice.go provides helper functions for OmniVoice integration:

import "github.com/plexusone/elevenlabs-go/ax"

// Map AX code to resilience category
category := ax.CategoryForCode(ax.ErrNotLoggedIn)
// category = resilience.CategoryAuth

// Check if error is retryable
retryable := ax.IsRetryableCode(ax.ErrDocumentNotFound)
// retryable = false

// Get recovery suggestion
suggestion := ax.SuggestionForCode(ax.ErrNeedsAuthorization)
// suggestion = "Verify your API key is valid and has required permissions"

// Get required fields for an operation
fields := ax.OperationRequiredFields(ax.OpTextToSpeech)
// fields = [{Name: "voice_id", Description: "...", Example: "..."},
//           {Name: "text", Description: "...", Example: "..."}]

// Convert AX code to full ErrorInfo
info := ax.ToErrorInfo(ax.ErrNotLoggedIn)
// info.Category = CategoryAuth, info.Retryable = false, ...

// Classify HTTP status code
info := ax.ClassifyHTTPStatus(429, "rate limit exceeded")
// info.Category = CategoryRateLimit, info.Retryable = true

Operations with Required Fields

The following operations have required field metadata:

Operation Required Fields
text_to_speech voice_id, text
speech_to_text audio
voice_clone name, files
voice_design text, voice_description, gender, age
sound_generation text
audio_isolation audio
dubbing source_url, target_language
projects name
pronunciation name
conversational_ai agent_id

Integration with OmniVoice Smart Fallback

When used with omnivoice-core v0.8.0+, errors are now properly classified for smart fallback:

// OmniVoice client only falls back on permanent errors
client := tts.NewClient(
    tts.WithProvider("elevenlabs", elevenLabsProvider),
    tts.WithProvider("deepgram", deepgramProvider),
    tts.WithFallbacks("deepgram"),
)

// Rate limit (429) → retry within ElevenLabs → succeed
// Auth error (401) → no retry → fallback to Deepgram
result, err := client.Synthesize(ctx, "Hello", config)

Performance

Benchmarks confirm minimal overhead:

Operation Time Target
Error classification ~520ns <1ms ✓
Retry decision ~77ns <0.1ms ✓
Backoff calculation <30ns -

Migration Guide

From v0.9.0

No breaking changes. To enable the new features:

  1. Update dependencies:
go get github.com/plexusone/elevenlabs-go@v0.10.0
go get github.com/plexusone/omnivoice-core@v0.8.0
  1. (Optional) Configure retry behavior:
provider := tts.NewWithClient(client)
provider.SetRetryConfig(omnivoice.DefaultRetryConfig())
  1. (Optional) Add retry callbacks for logging:
provider.SetRetryConfig(omnivoice.RetryConfigWithCallback(
    func(attempt int, err error, delay time.Duration) {
        log.Printf("Retry %d: %v", attempt, err)
    },
))

Dependencies

  • Requires github.com/plexusone/omnivoice-core v0.8.0+

Full Changelog | Compare to v0.9.0