SDKs

Official client SDKs for integrating Edesy Voice Agent into your applications.

SDKs

Official client libraries for JavaScript/TypeScript, Python, and Go to integrate voice agents into your applications.

Available SDKs

Language Package Status
JavaScript/TypeScript @edesy/voice-agent Stable
Python edesy-voice-agent Stable
Go github.com/edesy-ai/voice-agent-go Stable

JavaScript/TypeScript SDK

Installation

npm install @edesy/voice-agent
# or
yarn add @edesy/voice-agent
# or
pnpm add @edesy/voice-agent

Quick Start

import { EdesyClient, Agent } from '@edesy/voice-agent';

// Initialize client
const client = new EdesyClient({
  apiKey: process.env.EDESY_API_KEY,
});

// Create an agent
const agent = await client.agents.create({
  name: 'Customer Support',
  language: 'en-US',
  llmProvider: 'gemini-2.5',
  llmModel: 'gemini-2.5-flash-lite',
  sttProvider: 'deepgram',
  ttsProvider: 'cartesia',
  ttsVoice: '95856005-0332-41b0-935f-352e296aa0df',
  prompt: 'You are a helpful customer support agent.',
  greetingMessage: 'Hello! How can I help you today?',
});

// Initiate a call
const call = await client.calls.create({
  agentId: agent.id,
  to: '+1234567890',
  from: '+0987654321',
  variables: {
    customerName: 'John Smith',
  },
});

console.log(`Call started: ${call.id}`);

Agents API

// List agents
const agents = await client.agents.list();

// Get agent by ID
const agent = await client.agents.get('agent_123');

// Update agent
const updated = await client.agents.update('agent_123', {
  name: 'Updated Support',
  prompt: 'New system prompt...',
});

// Delete agent
await client.agents.delete('agent_123');

Calls API

// Create outbound call
const call = await client.calls.create({
  agentId: 'agent_123',
  to: '+1234567890',
  from: '+0987654321',
  variables: { customerName: 'John' },
});

// Get call details
const callDetails = await client.calls.get(call.id);

// List calls
const calls = await client.calls.list({
  agentId: 'agent_123',
  status: 'completed',
  limit: 10,
});

// End call
await client.calls.end(call.id);

Transcripts API

// Get transcript
const transcript = await client.transcripts.get('trans_123');

// Get transcript text
const text = await client.transcripts.getText('trans_123');

// List transcripts for a call
const transcripts = await client.transcripts.list({
  callId: 'call_123',
});

WebSocket Streaming

import { EdesyWebSocket } from '@edesy/voice-agent';

const ws = new EdesyWebSocket({
  apiKey: process.env.EDESY_API_KEY,
  agentId: 'agent_123',
});

ws.on('connected', () => {
  console.log('Connected to voice agent');
});

ws.on('transcript', (data) => {
  console.log(`${data.role}: ${data.text}`);
});

ws.on('audio', (data) => {
  // Handle audio output
  playAudio(data.audio);
});

// Send audio
ws.sendAudio(audioBuffer);

// Send text (for testing)
ws.sendText('Hello, I need help with my order');

// Close connection
ws.close();

TypeScript Types

interface Agent {
  id: string;
  name: string;
  language: string;
  llmProvider: string;
  llmModel: string;
  sttProvider: string;
  sttModel?: string;
  ttsProvider: string;
  ttsVoice: string;
  prompt: string;
  greetingMessage?: string;
  tools?: Tool[];
  createdAt: Date;
  updatedAt: Date;
}

interface Call {
  id: string;
  agentId: string;
  direction: 'inbound' | 'outbound';
  status: 'queued' | 'ringing' | 'in-progress' | 'completed' | 'failed';
  from: string;
  to: string;
  duration?: number;
  startedAt?: Date;
  endedAt?: Date;
}

interface Transcript {
  id: string;
  callId: string;
  turns: TranscriptTurn[];
  summary?: string;
  createdAt: Date;
}

interface TranscriptTurn {
  id: string;
  role: 'user' | 'assistant';
  text: string;
  timestamp: number;
  confidence?: number;
}

Python SDK

Installation

pip install edesy-voice-agent

Quick Start

from edesy import EdesyClient

# Initialize client
client = EdesyClient(api_key="your-api-key")

# Create an agent
agent = client.agents.create(
    name="Customer Support",
    language="en-US",
    llm_provider="gemini-2.5",
    llm_model="gemini-2.5-flash-lite",
    stt_provider="deepgram",
    tts_provider="cartesia",
    tts_voice="95856005-0332-41b0-935f-352e296aa0df",
    prompt="You are a helpful customer support agent.",
    greeting_message="Hello! How can I help you today?",
)

# Initiate a call
call = client.calls.create(
    agent_id=agent.id,
    to="+1234567890",
    from_="+0987654321",
    variables={"customer_name": "John Smith"},
)

print(f"Call started: {call.id}")

Async Support

import asyncio
from edesy import AsyncEdesyClient

async def main():
    client = AsyncEdesyClient(api_key="your-api-key")

    # Async operations
    agents = await client.agents.list()

    # Create call
    call = await client.calls.create(
        agent_id="agent_123",
        to="+1234567890",
        from_="+0987654321",
    )

    # Wait for completion
    while call.status not in ["completed", "failed"]:
        await asyncio.sleep(1)
        call = await client.calls.get(call.id)

    print(f"Call ended with status: {call.status}")

asyncio.run(main())

Agents API

# List agents
agents = client.agents.list()

# Get agent
agent = client.agents.get("agent_123")

# Update agent
agent = client.agents.update(
    "agent_123",
    name="Updated Support",
    prompt="New system prompt...",
)

# Delete agent
client.agents.delete("agent_123")

Calls API

# Create call
call = client.calls.create(
    agent_id="agent_123",
    to="+1234567890",
    from_="+0987654321",
)

# Get call
call = client.calls.get(call.id)

# List calls
calls = client.calls.list(
    agent_id="agent_123",
    status="completed",
    limit=10,
)

# End call
client.calls.end(call.id)

WebSocket Streaming

from edesy import EdesyWebSocket

def on_transcript(data):
    print(f"{data['role']}: {data['text']}")

def on_audio(data):
    # Handle audio output
    play_audio(data['audio'])

ws = EdesyWebSocket(
    api_key="your-api-key",
    agent_id="agent_123",
)

ws.on("transcript", on_transcript)
ws.on("audio", on_audio)

# Connect and start
ws.connect()

# Send audio
ws.send_audio(audio_buffer)

# Close
ws.close()

Error Handling

from edesy import EdesyError, RateLimitError, AuthenticationError

try:
    call = client.calls.create(agent_id="agent_123", to="+1234567890")
except AuthenticationError:
    print("Invalid API key")
except RateLimitError as e:
    print(f"Rate limited. Retry after {e.retry_after} seconds")
except EdesyError as e:
    print(f"API error: {e.message}")

Go SDK

Installation

go get github.com/edesy-ai/voice-agent-go

Quick Start

package main

import (
    "context"
    "fmt"
    "log"

    edesy "github.com/edesy-ai/voice-agent-go"
)

func main() {
    // Initialize client
    client := edesy.NewClient("your-api-key")

    ctx := context.Background()

    // Create an agent
    agent, err := client.Agents.Create(ctx, edesy.CreateAgentRequest{
        Name:            "Customer Support",
        Language:        "en-US",
        LLMProvider:     "gemini-2.5",
        LLMModel:        "gemini-2.5-flash-lite",
        STTProvider:     "deepgram",
        TTSProvider:     "cartesia",
        TTSVoice:        "95856005-0332-41b0-935f-352e296aa0df",
        Prompt:          "You are a helpful customer support agent.",
        GreetingMessage: "Hello! How can I help you today?",
    })
    if err != nil {
        log.Fatal(err)
    }

    // Initiate a call
    call, err := client.Calls.Create(ctx, edesy.CreateCallRequest{
        AgentID: agent.ID,
        To:      "+1234567890",
        From:    "+0987654321",
        Variables: map[string]string{
            "customerName": "John Smith",
        },
    })
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("Call started: %s\n", call.ID)
}

Agents API

// List agents
agents, err := client.Agents.List(ctx, edesy.ListAgentsParams{})

// Get agent
agent, err := client.Agents.Get(ctx, "agent_123")

// Update agent
agent, err := client.Agents.Update(ctx, "agent_123", edesy.UpdateAgentRequest{
    Name:   "Updated Support",
    Prompt: "New system prompt...",
})

// Delete agent
err := client.Agents.Delete(ctx, "agent_123")

Calls API

// Create call
call, err := client.Calls.Create(ctx, edesy.CreateCallRequest{
    AgentID: "agent_123",
    To:      "+1234567890",
    From:    "+0987654321",
})

// Get call
call, err := client.Calls.Get(ctx, call.ID)

// List calls
calls, err := client.Calls.List(ctx, edesy.ListCallsParams{
    AgentID: "agent_123",
    Status:  "completed",
    Limit:   10,
})

// End call
err := client.Calls.End(ctx, call.ID)

WebSocket Streaming

import (
    edesy "github.com/edesy-ai/voice-agent-go"
)

ws, err := client.WebSocket(ctx, "agent_123")
if err != nil {
    log.Fatal(err)
}
defer ws.Close()

// Handle events
go func() {
    for event := range ws.Events() {
        switch e := event.(type) {
        case *edesy.TranscriptEvent:
            fmt.Printf("%s: %s\n", e.Role, e.Text)
        case *edesy.AudioEvent:
            playAudio(e.Audio)
        case *edesy.ErrorEvent:
            log.Printf("Error: %s", e.Message)
        }
    }
}()

// Send audio
err = ws.SendAudio(audioBuffer)

// Wait for completion
<-ws.Done()

Error Handling

import "errors"

call, err := client.Calls.Create(ctx, req)
if err != nil {
    var apiErr *edesy.APIError
    if errors.As(err, &apiErr) {
        switch apiErr.Code {
        case "authentication_error":
            log.Fatal("Invalid API key")
        case "rate_limit_exceeded":
            log.Printf("Rate limited. Retry after %d seconds", apiErr.RetryAfter)
        default:
            log.Printf("API error: %s", apiErr.Message)
        }
    }
    log.Fatal(err)
}

Webhooks

Webhook Signature Verification

JavaScript

import { verifyWebhookSignature } from '@edesy/voice-agent';

app.post('/webhook', (req, res) => {
  const signature = req.headers['x-edesy-signature'];
  const isValid = verifyWebhookSignature(
    req.body,
    signature,
    process.env.WEBHOOK_SECRET
  );

  if (!isValid) {
    return res.status(401).send('Invalid signature');
  }

  // Process webhook
  const event = req.body;
  console.log(`Received event: ${event.event}`);

  res.status(200).send('OK');
});

Python

from edesy import verify_webhook_signature

@app.post("/webhook")
def handle_webhook(request):
    signature = request.headers.get("X-Edesy-Signature")
    is_valid = verify_webhook_signature(
        request.data,
        signature,
        os.environ["WEBHOOK_SECRET"],
    )

    if not is_valid:
        return "Invalid signature", 401

    event = request.json
    print(f"Received event: {event['event']}")

    return "OK", 200

Go

import "github.com/edesy-ai/voice-agent-go/webhook"

func handleWebhook(w http.ResponseWriter, r *http.Request) {
    body, _ := io.ReadAll(r.Body)
    signature := r.Header.Get("X-Edesy-Signature")

    isValid := webhook.VerifySignature(body, signature, os.Getenv("WEBHOOK_SECRET"))
    if !isValid {
        http.Error(w, "Invalid signature", http.StatusUnauthorized)
        return
    }

    var event webhook.Event
    json.Unmarshal(body, &event)
    fmt.Printf("Received event: %s\n", event.Event)

    w.WriteHeader(http.StatusOK)
}

Best Practices

1. Use Environment Variables

// Never hardcode API keys
const client = new EdesyClient({
  apiKey: process.env.EDESY_API_KEY,
});

2. Handle Rate Limits

import { RateLimitError } from '@edesy/voice-agent';

async function createCallWithRetry(params, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await client.calls.create(params);
    } catch (error) {
      if (error instanceof RateLimitError) {
        await sleep(error.retryAfter * 1000);
        continue;
      }
      throw error;
    }
  }
}

3. Use Async/Await

// Good
const call = await client.calls.create(params);

// Avoid callback hell
client.calls.create(params).then(call => {
  client.calls.get(call.id).then(details => {
    // ...
  });
});

Next Steps