Speko Docs

Types

Shared request / response types exported from @spekoai/sdk.

All types below are exported from the package root:

import type {
  SpekoClientOptions,
  KeySource,
  OptimizeFor,
  RoutingIntent,
  PipelineConstraints,
  TranscribeOptions,
  TranscribeResult,
  TranscribeStreamEvent,
  SynthesizeOptions,
  SynthesizeResult,
  SynthesizeStreamResult,
  ChatMessage,
  ChatTool,
  ChatToolCall,
  ChatToolChoice,
  CompleteParams,
  CompleteResult,
  CompleteStreamEvent,
  UsageSummary,
  UsageByProvider,
  UsageQueryParams,
  OrganizationBalance,
  CreditLedgerEntry,
  CreditLedgerKind,
  CreditLedgerPage,
  CreditLedgerQueryParams,
  RealtimeProvider,
  RealtimeToolSpec,
  RealtimeConnectParams,
  RealtimeFrame,
  RealtimeEventHandler,
  RealtimeSessionHandle,
  VoiceDialParams,
  VoiceDialResult,
  PhoneNumberRow,
  PhoneNumberKybOverview,
  PhoneNumberKybSubmission,
  CallDetail,
  CallEvent,
  CallReport,
  CallTransfer,
  ScheduledCallback,
  AgentCallListPage,
  AgentRow,
  AgentCreateParams,
  AgentToolRow,
  KnowledgeBaseRow,
  KnowledgeBaseDocumentRow,
} from '@spekoai/sdk';

Routing primitives

OptimizeFor

type OptimizeFor = 'balanced' | 'accuracy' | 'latency' | 'cost';

Biases the weighted score the router uses to rank candidates. balanced is the default.

RoutingIntent

interface RoutingIntent {
  language: string; // BCP-47, e.g. "en" or "es-MX"
  region?: string; // e.g. "us-east4"; defaults to "global" server-side
  optimizeFor?: OptimizeFor;
}

Every proxy call takes one. TranscribeOptions and SynthesizeOptions extend it directly.

PipelineConstraints

interface PipelineConstraints {
  allowedProviders?: {
    stt?: string[];
    llm?: string[];
    tts?: string[];
  };
}

Optional allow-list layered on top of RoutingIntent. When set, the router still ranks by benchmark score but considers only candidates in the allow-list for that modality.

Transcribe

interface TranscribeOptions extends RoutingIntent {
  contentType?: string; // default "audio/wav"
  constraints?: PipelineConstraints;
  keywords?: readonly string[];
}

interface TranscribeResult {
  text: string;
  provider: string;
  model: string;
  confidence: number | null;
  failoverCount: number;
  scoresRunId: string | null;
}

Synthesize

interface SynthesizeOptions extends RoutingIntent {
  voice?: string;
  speed?: number;
  constraints?: PipelineConstraints;
}

interface SynthesizeResult {
  audio: Uint8Array;
  contentType: string; // e.g. "audio/pcm;rate=24000" or "audio/mpeg"
  provider: string;
  model: string;
  failoverCount: number;
  scoresRunId: string | null;
}

Complete

interface ChatMessage {
  role: 'system' | 'user' | 'assistant' | 'tool';
  content: string;
  toolCalls?: ChatToolCall[];
  toolCallId?: string;
  isError?: boolean;
}

interface ChatToolCall {
  id: string;
  name: string;
  args: string;
}

type ChatToolChoice =
  | 'auto'
  | 'none'
  | 'required'
  | { type: 'function'; function: { name: string } };

interface ChatTool {
  name: string;
  description: string;
  parameters: Record<string, unknown>;
  executionMode?: 'inline' | 'webhook' | 'builtin';
  source?:
    | { kind: 'inline' }
    | {
        kind: 'webhook';
        url: string;
        secretRef: string;
        headers?: Record<string, string>;
        timeoutMs?: number;
      }
    | { kind: 'builtin'; name: string; config?: unknown };
}

interface CompleteParams {
  messages: ChatMessage[];
  intent: RoutingIntent;
  systemPrompt?: string;
  temperature?: number;
  maxTokens?: number;
  reasoningEffort?: 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';
  constraints?: PipelineConstraints;
  tools?: ChatTool[];
  toolChoice?: ChatToolChoice;
  parallelToolCalls?: boolean;
  maxToolHops?: number;
}

interface CompleteResult {
  text: string;
  provider: string;
  model: string;
  usage: {
    promptTokens: number;
    completionTokens: number;
  };
  failoverCount: number;
  scoresRunId: string | null;
  toolCalls?: ChatToolCall[];
}

Usage

type KeySource = 'BYOK' | 'MANAGED';

interface UsageQueryParams {
  from?: string; // ISO-8601
  to?: string; // ISO-8601
}

interface UsageSummary {
  totalSessions: number;
  totalMinutes: number;
  totalCost: number;
  breakdown: UsageByProvider[];
  balanceUsd: number;
  currency: 'USD';
}

interface UsageByProvider {
  provider: string;
  type: 'stt' | 'llm' | 'tts';
  metric: string;
  keySource: KeySource;
  quantity: number;
  cost: number;
}

Credits

interface OrganizationBalance {
  balanceUsd: number;
  currency: 'USD';
  updatedAt: string;
}

type CreditLedgerKind = 'grant' | 'debit' | 'topup' | 'refund' | 'adjustment';

interface CreditLedgerEntry {
  id: string;
  kind: CreditLedgerKind;
  /** Signed. Positive for grants/topups/refunds, negative for debits. */
  amountMicroUsd: string;
  metric: string | null;
  provider: string | null;
  sessionId: string | null;
  createdAt: string;
}

interface CreditLedgerPage {
  entries: CreditLedgerEntry[];
  nextCursor: string | null;
}

interface CreditLedgerQueryParams {
  limit?: number;
  cursor?: string;
}

Realtime (S2S)

type RealtimeProvider = 'openai' | 'google' | 'xai' | 'inworld';

interface RealtimeToolSpec {
  name: string;
  description: string;
  parameters: Record<string, unknown>;
}

interface RealtimeConnectParams {
  provider: RealtimeProvider;
  model: string;
  voice?: string;
  systemPrompt?: string;
  temperature?: number;
  inputSampleRate?: 16000 | 24000;
  outputSampleRate?: 16000 | 24000;
  tools?: RealtimeToolSpec[];
  metadata?: Record<string, unknown>;
  /** Max session duration in seconds. Server-capped at 1800 (30 min). */
  ttlSeconds?: number;
}

type RealtimeFrame =
  | { type: 'ready'; inputSampleRate: 16000 | 24000; outputSampleRate: 16000 | 24000 }
  | { type: 'audio'; pcm: Uint8Array; sampleRate: number }
  | {
      type: 'transcript';
      role: 'user' | 'assistant';
      text: string;
      final: boolean;
    }
  | {
      type: 'tool_call';
      callId: string;
      name: string;
      arguments: string;
    }
  | {
      type: 'usage';
      inputAudioTokens: number;
      outputAudioTokens: number;
    }
  | { type: 'interruption'; at: 'user' | 'assistant' }
  | {
      type: 'server_tool_call';
      id: string;
      name: string;
      status: 'started' | 'completed' | 'failed';
    }
  | { type: 'error'; code: string; message: string }
  | { type: 'close'; code: number; reason: string };

type RealtimeEventHandler = (frame: RealtimeFrame) => void;

interface RealtimeSessionHandle {
  readonly sessionId: string;
  readonly expiresAt: string;
  readonly inputSampleRate: 16000 | 24000;
  readonly outputSampleRate: 16000 | 24000;

  sendAudio(pcm: Uint8Array): void;
  commit(): void;
  interrupt(): void;
  sendToolResult(callId: string, output: string): void;
  on(handler: RealtimeEventHandler): () => void;
  close(code?: number, reason?: string): void;
}

Voice, Phone Numbers, Agents, and Knowledge Bases

These resource types are also exported from the package root. The full shapes live in TypeScript and are intended to be consumed from your editor, but the high-level entry points are:

interface VoiceDialParams {
  to: string;
  from?: string;
  intent: RoutingIntent;
  constraints?: PipelineConstraints;
  voice?: string;
  systemPrompt?: string;
  llm?: { temperature?: number; maxTokens?: number };
  ttsOptions?: { sampleRate?: number; speed?: number };
  metadata?: Record<string, unknown>;
}

interface VoiceDialResult {
  sessionId: string;
  callControlId: string;
  roomName: string;
  status: 'dialing' | 'dialing-stub';
  to: string;
  from: string;
}

interface PhoneNumberRow {
  id: string;
  e164: string;
  direction: 'inbound' | 'outbound' | 'both';
  label: string | null;
  agentId: string | null;
  createdAt: string;
  updatedAt: string;
}

interface AgentRow {
  id: string;
  name: string;
  systemPrompt: string;
  voice: string | null;
  intent: { language: string; optimizeFor?: 'latency' | 'quality' | 'cost' };
  llmOptions: { temperature?: number; maxTokens?: number; model?: string } | null;
  stackPreferences: {
    allowedProviders?: { stt?: string[]; llm?: string[]; tts?: string[]; s2s?: string[] };
  } | null;
  sttOptions: { keywords?: string[] } | null;
  createdAt: string;
  updatedAt: string;
}

interface KnowledgeBaseRow {
  id: string;
  agentId: string;
  name: string;
  description: string | null;
  embeddingModel: string;
  documentCount: number;
  chunkCount: number;
  createdAt: string;
  updatedAt: string;
}

Client

interface SpekoClientOptions {
  apiKey: string;
  baseUrl?: string; // default "https://api.speko.dev"
  timeout?: number; // default 30000
}

On this page