Client libraries for integrating voice agents into your applications. Python, Go, Node and React SDKs are available; ask us for access. They are not published on npm or PyPI.
Available SDKs#
| Language | Package name used in the examples |
|---|---|
| JavaScript/TypeScript (Node, React) | @edesy/voice-agent |
| Python | edesy-voice-agent |
| Go | github.com/edesy-ai/voice-agent-go |
Access is on request: contact us.
JavaScript/TypeScript SDK#
Installation#
Python, Go, Node and React SDKs are available; ask us for access. You will get the package and install instructions with access.
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#
Python, Go, Node and React SDKs are available; ask us for access. You will get the package and install instructions with access.
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#
Python, Go, Node and React SDKs are available; ask us for access. You will get the package and install instructions with access.
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#
Webhook subscription deliveries carry X-Webhook-Signature: t=<unix seconds>,v1=<hex>, where v1 is an HMAC-SHA256 keyed with your whsec_... secret over "{t}.{raw request body}". Verify against the raw body, before JSON parsing, and reject timestamps older than 5 minutes.
Node.js#
const crypto = require('crypto');
function verifyWebhook(rawBody, header, secret) {
const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));
const ts = Number(parts.t);
if (!ts || Date.now() / 1000 - ts > 300) return false;
const expected = crypto
.createHmac('sha256', secret)
.update(`${parts.t}.${rawBody}`)
.digest('hex');
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1 || ''));
}
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const ok = verifyWebhook(req.body.toString(), req.headers['x-webhook-signature'] || '', process.env.WEBHOOK_SECRET);
if (!ok) return res.status(401).send('Invalid signature');
const event = JSON.parse(req.body.toString());
console.log(`Received event: ${event.type}`);
res.status(200).send('OK');
});
For Python and Go verification code, see Webhook Subscriptions.
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 => {
// ...
});
});