Case studies

TraceBox: Real WebRTC Voice-Agent Testing

I built a tool that tests voice agents in a real browser, with an eight-state agent, live audio capture and saved run evidence.

1–100
bots per run
supported batch size
120s
max listen window
RMS silence detection
8
LangGraph states
explicit lifecycle
1
worker concurrency
Cloud Run execution
Approach
[01]Control plane[02]Isolated browser execution[03]Real WebRTC conversations[04]Persistent evidence

[1] Control plane

Control plane, execution plane & ownership

How runs are created, dispatched, executed, observed, and persisted.

System overview

A signed-in control plane sends each run to one of two execution modes.

Fig. 1 · Runs dispatch to an isolated worker or fall back in-process.

Control plane ↔ execution plane

In worker mode, run control and long browser sessions stay separate. Without WORKER_URL, runs execute in-process.

Fig. 2 · The 8-state agent runs inside headless Chromium.

I own the eight-state LangGraph agent, browser and WebRTC control, isolated workers, live inspection, persistence and session evidence. I built the voice-agent testing workflow end to end.

Ownership ledger

AreaDetailOwnership
Browser testing workflowBrowser-based voice-agent testingBuilt
WebRTC capture + injectionReal live browser conversationsBuilt
Isolated worker executionCloud Run concurrency 1Built
Realtime live inspectionStatus + transcript + screencastBuilt
Eight-state LangGraph agentNavigate → finalize lifecycleDesigned + built
RMS voice activity detection120-second max listen windowEngineered
Local execution fallbackIn-process spawnBots pathBuilt
Persistent session evidenceScreenshots · recording · trace · logsBuilt

The story: a control and execution split, isolated headless browser workers, the LangGraph lifecycle, real WebRTC media, live observability, evidence capture, deployment and known limits.

[2] Agent

LangGraph agent & runtime guardrails

An eight-state lifecycle with retries, time limits, recovery and finalization.

Eight-state bot lifecycle

The main path is shown first, with the retry and exit routes listed below.

Fig. 3 · The main path through one voice session.

Retry and exit routes

FromConditionGoes to
act, speakContinue listeninglisten
setupPage not readynavigate
actBrowser error or inactivenavigate
setupSetup timeout or unrecoverable errorfinalize, then end
reasonSession end or timeoutfinalize, then end

Runtime guardrails

GuardrailValueBehavior
Session deadlinemax_session_durationChecked in setup, listen, and reason
Setup cap50 turnsSetup stops after the configured cap
Silent session20 turnsReasoning stops without system transcript
Stuck recovery3 bot turnsFresh screenshot before selecting next action
Listen window120 secondsRMS-based silence / voice activity detection
Stop behaviorWorkspace + botsMarks non-terminal bots stopped; listen checks status

[3] WebRTC

Real-time WebRTC voice loop

It captures live speech, reasons over the conversation and page, then plays synthesized audio back into the browser session.

Real WebRTC media loop

Target audio becomes conversation state, and the agent either acts in the browser or speaks.

Fig. 4 · Reasoning branches to a browser action or injected speech.

WebRTC media bridge

StageMechanismDetail
Incoming audioMediaRecorderRemote audio track → speech capture
ListeningRMS silence detection120-second maximum listening window
Outgoing audioElevenLabs pcm_1600016 kHz PCM speech generation
Media injectionreplaceTrack()Replaces the outbound WebRTC media track

Screenshot-assisted reasoning

Latest page contextA screenshot is taken after every navigation and browser action. It's uploaded for later review and kept as the latest PNG in graph state, so the model sees the current page.

[4] Observability

Realtime observability & session evidence

Watch a run live without polling, then review recordings, screenshots, transcripts, timings, logs and errors afterwards.

Live observability without polling

Database state and short-lived session data take separate Supabase Realtime paths to the viewer.

Fig. 5 · Postgres Changes for state; Broadcast for transcript and frames.

Screen recording & live frame pipeline

CDP screencast frames split into sampled live frames and the saved screen recording.

Fig. 6 · One frame stream, a live feed and a stored recording.

Evidence per bot

EvidenceFormatDetail
RecordingWebM / audioRecording URL and path
TraceLangGraph timingsPer-node execution durations
TranscriptJSON + normalizedSpeaker + text + elapsed timestamp
LogsPer-bot server logsExecution-side evidence
ScreenshotsStorage URLsCaptured after navigation / actions
ErrorsError detailsTerminal failure context

[5] Deployment

Deployment, technical facts & limitations

What the implementation confirms, and what this write-up deliberately doesn't claim.

Two-service Cloud Run path

deploy.sh deploys the worker first, takes its URL, then deploys the frontend with WORKER_URL.

Fig. 7 · Worker first, then frontend with WORKER_URL.

deploy.sh defaults to asia-south1. GCP, Supabase and provider settings are set up separately. cloudbuild.yaml is an alternate combined-image path.

Confirmed technical facts

FactConfirmed valueFraming
Bots per run1–100Supported batch size
LangGraph lifecycle8 statesNamed lifecycle
Production worker modelConcurrency 1Worker concurrency 1
Listening window120 secondsMax VAD window

Known limitations & boundary

Security limitationPublic-readable media bucketsBuilt as an experimental project; production use would require private media storage with signed access and automated security testing.
Testing limitationNo automated test suiteNo unit, integration, E2E, or load-test files.
Recording fallbackPreserve available evidenceMuxed → screen-only → audio-only.
Claim boundaryNo unsupported performance claimsNo uptime, benchmark, SLA, or load claims.

Note on scope

High-level architecture and confirmed configuration only. No claims about users, revenue, uptime, benchmarks, reliability, privacy or load.

Want to talk about any of this?

Happy to go deeper on the WebRTC audio loop, the LangGraph lifecycle, or live observability.

© 2026 Tharun Pranav SakthivelHome