Skip to content

Documentation / Guides / Port an existing voicebot

Port an existing voicebot

Port behavior first and mechanics second. The goal is a smaller consumer that still owns every product decision while VAANI replaces duplicated runtime work.

This approach is based on the proven standalone Product Catalog consumer and the approved prod-v4.2 Vertex migration at 05a5c42b.

Map files by responsibility

Existing voicebot area Consumer destination VAANI replacement
root/persona instructions prompts.py none
call-flow prompt builders feature modules beside prompts.py none
tools and domain providers tools.py and domain/ RuntimeTool admission/execution
product/reference data packaged consumer data none
language/model/voice config reviewed consumer config typed profiles and bindings
accepted-call/session plumbing vaani_setup.py VoiceRuntime and adapters
LiveKit entrypoint thin deployment adapter LiveKitCallHandoff
frontend choices existing frontend validated CallSetup
logging/GCS/Postgres result consumers immutable result and optional adapters/publisher

Port one vertical slice

Start with one representative call flow:

  1. Freeze an expected prompt, participant utterance, business tool request, business result, reply, and terminal outcome.
  2. Move the prompt builder without changing its wording.
  3. Wrap one existing domain function in a RuntimeTool. Keep its underlying data and state in the consumer.
  4. Build one LanguageBinding and CallSetup.
  5. Script STT → LLM → tool → TTS offline.
  6. Assert transcript, tool evidence, one Closure, and no resources.
  7. Only then assemble live adapters and a non-connecting credential preflight.

The Vertex Product Catalog example shows this slice in repository form.

For a greenfield shell around migrated prompts and tools, the companion Starter CLI generates a consumer-owned LiveKit bridge, backend, and browser console. Treat it as scaffolding: move existing behavior into the generated consumer modules and repeat the same offline proof before considering live traffic.

Adapt tools deliberately

Do not expose arbitrary Python callables directly. Give each tool a stable model-facing name, closed JSON schemas, a declared effect, and a handler that uses only approved consumer state.

During a broad port, classify tools:

  • get_, check_, lookup_: often READ_ONLY;
  • durable upserts with idempotency keys: potentially IDEMPOTENT;
  • transfers, notifications, payments, or unkeyed writes: usually NON_IDEMPOTENT.

Confirm each classification with the domain owner.

Preserve deployment choices

The reference Vertex bot retains Deepgram STT, Vertex reasoning, Google speech, Google STT and AI Studio fallbacks, language-specific prompts/voices, named transfer routes, and frontend persona composition. Those values belong in the consumer setup. VAANI does not choose a "better" route during migration.

Keep the entrypoint thin

The final entrypoint should:

  1. validate deployment/caller data;
  2. construct TelephonyIdentity and the LiveKit handoff;
  3. build consumer state and CallSetup;
  4. call the runtime;
  5. send the terminal result to post-Closure consumers.

It should not reimplement silence timers, provider retries, teardown races, or mutable result assembly.

Roll out by composition

Deploy the VAANI entrypoint behind a consumer-owned feature flag. Keep the previous entrypoint deployable. New calls take the selected composition; already-running calls remain pinned to the runtime/adapters they started with. Rollback routes only new calls back to the previous entrypoint and drains running calls.

Next: prove the port offline and prepare production.