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 => {
// ...
});
});