Expand description
Vapi bidirectional WebSocket voice-agent adapter for rvoip.
This crate lets rvoip retain ownership of a SIP or WebRTC caller leg while Vapi owns ASR, dialog, synthesis, and interruption handling on a raw-audio WebSocket call transport.
§rvoip-vapi
Developer-preview Vapi integration for rvoip. rvoip owns the caller-facing SIP or WebRTC leg; Vapi owns the full ASR, model, synthesis, and interruption pipeline through its bidirectional raw-audio WebSocket transport.
The primary API attaches an agent to a caller connection that is already bound to an active rvoip session:
use std::sync::Arc;
use rvoip_core::{ConnectionId, Orchestrator};
use rvoip_vapi::{
VapiAdapter, VapiApiKey, VapiAssistant, VapiCallOptions, VapiConfig,
};
async fn attach(
orchestrator: Arc<Orchestrator>,
caller: ConnectionId,
) -> Result<(), Box<dyn std::error::Error>> {
let key = VapiApiKey::new(std::env::var("VAPI_API_KEY")?)?;
let adapter = VapiAdapter::new(VapiConfig::new(key))?;
let options =
VapiCallOptions::new(VapiAssistant::saved(std::env::var("VAPI_ASSISTANT_ID")?));
// Registers this adapter when no Vapi adapter is registered, originates
// the remote agent, bridges both audio directions, and supervises teardown.
let mut call = adapter.attach_agent(&orchestrator, caller, options).await?;
call.say("One moment while I look that up.", false, true).await?;
let _outcome = call.wait().await;
Ok(())
}For a complete high-level server that accepts either SIP or WebRTC with one
transport flag, see
examples/14-vapi-agent.
VapiAudioFormat::MuLaw8Khz is the default and gives SIP/PCMU a pass-through
path. VapiAudioFormat::PcmS16Le16Khz selects raw mono PCM and relies on
rvoip’s media graph for conversion to the caller codec.
The low-level path is also available: register VapiAdapter as a
ConnectionAdapter, originate Transport::Vapi with a typed
VapiCallOptions context, then bridge the resulting connection yourself.
Call events are available through VapiAgentCall::subscribe_events and
VapiAdapter::subscribe_vapi_events. Unknown event types are preserved rather
than closing the audio session. The first per-call subscriber also receives
events buffered during activation. DTMF and transfer remain owned by the rvoip
caller leg; Vapi’s WebSocket transport does not define an RTP/DTMF input.
Production configuration requires HTTPS and WSS. API keys, returned socket URLs, assistant definitions, transcripts, audio, and tool payloads are omitted from adapter diagnostics.
The adapter emits content-free counters for setup failures, remote disconnects, bounded-queue overflow, audio-frame flow, unknown or malformed events, dropped RTP DTMF frames, and terminated sessions. Metric labels use only fixed stage, direction, and outcome values.
The live smoke test is ignored by default. Run it explicitly with
VAPI_API_KEY and either VAPI_ASSISTANT_ID or
VAPI_TRANSIENT_ASSISTANT_JSON:
cargo test -p rvoip-vapi --test live_smoke -- --ignoredRe-exports§
pub use adapter::VapiAdapter;pub use adapter::VapiTransportHandle;pub use adapter::ADAPTER_EVENT_CAPACITY;pub use adapter::VAPI_CALL_REFERENCE_KIND;pub use agent::VapiAgentCall;pub use agent::VapiAgentOutcome;pub use config::VapiApiKey;pub use config::VapiConfig;pub use error::Result;pub use error::VapiError;pub use events::VapiEvent;pub use events::VapiEventEnvelope;pub use types::VapiAssistant;pub use types::VapiAudioFormat;pub use types::VapiCallOptions;pub use types::VapiPeerFailurePolicy;
Modules§
- adapter
- Staged outbound
ConnectionAdapterimplementation for Vapi. - agent
- High-level caller-to-Vapi attachment and paired lifecycle supervision.
- config
- Static Vapi adapter configuration.
- error
- Error types for the Vapi adapter.
- events
- Typed, forward-compatible Vapi event surface.
- types
- Public call configuration and control-message types.