AbsoluteJS

Voice Tester

AI-driven automated tester for voice services. It simulates a caller end-to-end with TTS, STT, LLM decisions, transport adapters, scenarios, and JSON reports.

#CLI

@absolutejs/voice-tester can test a deployed receptionist or voice bot without a human caller. The default path opens a WebSocket directly to a Twilio Media Streams-compatible /stream endpoint, sends connected/start envelopes, streams 20 ms μ-law frames generated from Deepgram Aura TTS, decodes the service audio back to PCM, transcribes it with Deepgram STT, and asks an LLM what the simulated caller should do next.

BASH
bun x @absolutejs/voice-tester \
	--target wss://example.com/v1/voice/phone/stream \
	--scenario adversarial \
	--duration 90 \
	--from +15555550100 \
	--to +15555550199 \
	--session phone:+15555550100:$(date +%s)

#API

TS
import { runTwilioScenario } from "@absolutejs/voice-tester";
import { adversarialScenario } from "@absolutejs/voice-tester/scenarios";

const report = await runTwilioScenario({
	wsUrl: "wss://example.com/v1/voice/phone/stream",
	tts: { apiKey: process.env.DEEPGRAM_API_KEY! },
	stt: { apiKey: process.env.DEEPGRAM_API_KEY! },
	scenario: adversarialScenario({
		llm: { model: "claude-haiku-4-5-20251001" }
	}),
	customParameters: {
		sessionId: `phone:+15555550100:${Date.now()}`
	},
	from: "+15555550100",
	to: "+15555550199"
});

if (report.endedReason === "error") {
	throw new Error(report.error?.message ?? "scenario failed");
}

#Modes

ModePurpose
twilio-wsDefault mode. Opens a WebSocket directly to a Twilio Media Streams-compatible /stream endpoint and simulates the caller side without a real phone call.
discordJoins a Discord voice channel as a separate tester bot, sends Aura TTS as Opus, receives the bot-under-test audio, and transcribes it through STT.
twilio-outboundOriginates a real outbound Twilio call through a temporary public webhook server so the test includes the carrier audio path.

#Environment

DEEPGRAM_API_KEY is required for Aura TTS and Deepgram STT.
ANTHROPIC_API_KEY is used by @absolutejs/ai when built-in scenarios ask an LLM to choose the next caller action.
DISCORD_TESTER_TOKEN is required for Discord mode.
TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN are required for twilio-outbound mode.
Discord mode keeps discord.js, @discordjs/voice, and prism-media as optional peer dependencies so Twilio users do not install them by default.

#Scenario Report

Scenario reports include scenario id, transport id, transcript, caller turn count, service turn count, durationMs, endedReason, and optional error message.
endedReason is scenario_hangup, timeout, transport_closed, or error.
The CLI exits non-zero when endedReason is error so it can be used in CI or release checks.
Every run logs caller speech, service transcript finals, media activity, mark/clear events, STT lifecycle, and the final JSON report.

Continue toward an outcome

These playbooks show where this package fits, how to verify the combined system, and what changes before production.

Current package surface

What ships today

@absolutejs/voice-testerv0.0.4-beta.5 · betaVoice & MedianpmSource
4entry points42symbols

Import surface · click to copy

33 symbols
runScenarioexportPermalinkSource
TS
runScenario
Exported from @absolutejs/voice-tester
Use this API in an outcome:Build a voice agent

Outcomes

What you can build

Overview

AI-driven automated tester for voice services that speak the Twilio Media Streams protocol. Pairs with @absolutejs/voice — drives a regression scenario end-to-end against a deployed receptionist without a phone, a real Twilio call, or a human in the loop.

What it does

Opens a WebSocket directly to your voice service's /stream endpoint and acts as the caller side of a Twilio Media Stream:

Install

@absolutejs/ai is a peer dependency.

Hardening checklist

Production guidance

OverviewAI-driven automated tester for voice services that speak the Twilio Media Streams protocol. Pairs with @absolutejs/voice — drives a regression scenario end-to-end against a deployed receptionist without a phone, a real Twilio call, or a human in the loop.

Follow in order

Troubleshooting path

1
Quick start (CLI)
Exits non-zero if the scenario hit an error. Prints a JSON report: