Skip to content

SDK

The @ph0ny/sdk package provides a typed TypeScript/JavaScript client for the ph0ny Voice API.

Installation

bash
pnpm add @ph0ny/sdk
# or
npm install @ph0ny/sdk

Quick Start

typescript
import { createVoiceClient } from '@ph0ny/sdk'

const client = createVoiceClient({
  apiKey: 'plabs_your_key_here',
})

Configuration

typescript
import { createVoiceClient } from '@ph0ny/sdk'

const client = createVoiceClient({
  apiKey: 'plabs_...',
  baseUrl: 'https://persona-labsvoice-api-production.up.railway.app/v1', // optional, defaults to production
  timeout: 30000,                       // request timeout in ms
  providerKeys: {                       // optional BYOK keys
    elevenlabs: 'sk_...',
    openai: 'sk-...',
    cartesia: 'sk_...',
  },
})

Client Namespaces

The VoiceClient organizes methods into sub-clients:

NamespaceDescription
client.agentsAgent CRUD, chat, speak, provision
client.ttsText-to-speech synthesis
client.sttSpeech-to-text transcription
client.ragCollection management and search
client.sessionsTwilio and WebSocket session creation
client.testsAgent test cases and self-play
client.conversationsConversation history
client.observabilitySession traces and quality metrics
client.recordingsCall recording retrieval
client.providerKeysClientStored provider key management
client.onboardingOnboarding interview flows
client.tasksOutbound call task dispatch

Agents

typescript
// Create
const agent = await client.agents.create({
  name: 'Support Agent',
  systemPrompt: 'You are a customer support agent for Acme Corp.',
  firstMessage: 'Hi, thanks for calling Acme. How can I help?',
  ttsProvider: 'cartesia',
  llmProvider: 'openai',
  llmModel: 'gpt-4.1',
  temperature: 0.7,
})

// List
const { data, nextCursor, hasMore } = await client.agents.list({ limit: 20 })

// Get
const agent = await client.agents.get('agent_abc123')

// Update
await client.agents.update('agent_abc123', {
  systemPrompt: 'Updated prompt...',
  temperature: 0.5,
})

// Delete
await client.agents.delete('agent_abc123')

// Chat
const reply = await client.agents.chat('agent_abc123', {
  message: 'What are your hours?',
  conversationId: 'conv_xyz', // optional, for multi-turn
})

// Speak (TTS with agent's voice)
const audioBuffer = await client.agents.speak('agent_abc123', {
  text: 'Welcome to Acme Corp!',
  format: 'mp3',
})

// Provision (agent + collection + initial content in one call)
const result = await client.agents.provision({
  name: 'Knowledge Agent',
  systemPrompt: 'Answer questions from the knowledge base.',
  collection: { name: 'FAQ' },
  initialContent: [
    { content: 'Our hours are 9am-5pm EST.', contentType: 'text' },
  ],
})

Text-to-Speech

typescript
// Synthesize
const result = await client.tts.synthesize({
  text: 'Hello world',
  voiceId: 'default',
  format: 'mp3',       // mp3 | wav | ogg
  speed: 1.0,
  provider: 'cartesia', // or elevenlabs, deepgram, fish-audio, etc.
})

// List voices
const voices = await client.tts.listVoices()

// Get voice details
const voice = await client.tts.getVoice('voice_id')

Speech-to-Text

typescript
// Transcribe from file
const result = await client.stt.transcribe(audioBlob, {
  language: 'en',
  mode: 'accurate',   // accurate | fast
  diarize: true,
  timestamps: 'segment',
})

// Transcribe from URL
const result = await client.stt.transcribe('https://example.com/audio.mp3')

// Async transcription
const job = await client.stt.transcribeAsync(audioBlob)
const result = await client.stt.waitForJob(job.id, {
  pollInterval: 1000,
  timeout: 300000,
})

RAG (Collections)

typescript
// Create collection
const collection = await client.rag.create({
  name: 'Product Docs',
  description: 'Product documentation for support agents',
})

// Ingest content
await client.rag.ingest(collection.id, {
  content: 'Our return policy allows returns within 30 days...',
  contentType: 'text',
  chunkSize: 1000,
  chunkOverlap: 200,
})

// Search
const results = await client.rag.search(collection.id, {
  query: 'return policy',
  limit: 5,
  threshold: 0.7,
})

// List collections
const { data } = await client.rag.list()

// Delete collection
await client.rag.delete(collection.id)

Sessions

typescript
// Create Twilio session
const session = await client.sessions.createTwilio({
  agentId: 'agent_abc123',
  from: '+18005551234',
  to: '+19005551234',
})

// Connect WebSocket session
const ws = await client.sessions.connectAgent('agent_abc123', {
  // WebSocket options
})

Observability

typescript
// List session traces
const sessions = await client.observability.listSessions({
  agentId: 'agent_abc123',
  limit: 20,
})

// Get session detail
const detail = await client.observability.getSession('session_id')

// Get root cause analysis
const analysis = await client.observability.getSessionRootCause('session_id')

Tasks (Outbound Calls)

typescript
// Dispatch an outbound call
const task = await client.tasks.dispatch('agent_abc123', {
  phoneNumber: '+19005551234',
  taskPrompt: 'Call the customer and confirm their appointment for tomorrow.',
})

// List tasks
const { data } = await client.tasks.list('agent_abc123')

Error Handling

All API errors throw VoiceApiException:

typescript
import { VoiceApiException } from '@ph0ny/sdk'

try {
  await client.agents.get('nonexistent')
} catch (err) {
  if (err instanceof VoiceApiException) {
    console.error(err.code)    // 'NOT_FOUND'
    console.error(err.message) // 'Agent not found'
    console.error(err.status)  // 404
  }
}

Provider Constants

The SDK re-exports canonical provider arrays:

typescript
import {
  TTS_PROVIDERS,    // ['cartesia', 'elevenlabs', 'deepgram', ...]
  STT_PROVIDERS,    // ['whisper', 'deepgram', 'elevenlabs', ...]
  LLM_PROVIDERS,    // ['openai', 'anthropic', 'groq']
  VOICE_BACKENDS,   // all voice backend types
  BYOK_PROVIDERS,   // providers supporting BYOK
} from '@ph0ny/sdk'

Built by Persona Labs.