Skip to main content

deepgram-rust-voice-agent

Use when implementing a Deepgram Voice Agent from the Rust SDK, including the agent() WebSocket client, Settings/Update messages, typed AgentResponse events, function calling, and saved agent configurations.

Informações da origem

Repositório
deepgram/deepgram-rust-sdk
Última atividade na origem
8 de outubro de 2026 às 12:56
Idioma detectado do SKILL.md
inglês
Estrelas
67
Forks
45

Opções de instalação

Por padrão, está selecionado o prompt que primeiro revisa a origem. Você pode mudar para um comando direto ou baixar uma cópia local.

Revise os arquivos de origem

Leia o SKILL.md e os arquivos complementares exibidos pelo SkillsMP antes de decidir se vai instalar.

Exibindo SKILL.md

SKILL.md
Instruções da origem · Visualização somente leitura
name
deepgram-rust-voice-agent
description
Use when implementing a Deepgram Voice Agent from the Rust SDK, including the agent() WebSocket client, Settings/Update messages, typed AgentResponse events, function calling, and saved agent configurations.
# Using Deepgram Voice Agent (Rust SDK) Use this skill when the user wants an end-to-end conversational voice agent — STT, LLM, and TTS orchestrated by Deepgram over one WebSocket. ## When to use this product - Building a full conversational agent (the server runs the turn loop, the LLM call, and speech synthesis). - Handling agent events: conversation text, function-call requests, latency reports, interruptions. - Changing a live session's model, prompt, or voice without reconnecting. Prefer conversational STT (`flux_request`) instead when the application only needs turn-based transcripts and drives its own LLM and TTS. ## Authentication The Voice Agent client is behind the `agent` feature (on by default). ```toml [dependencies] deepgram = { version = "0.12", default-features = false, features = ["agent"] } tokio = { version = "1", features = ["full"] } futures = "0.3" ``` `agent` is also part of the crate's default features, so a plain `cargo add deepgram` includes it. ```rust let dg = deepgram::Deepgram::new(std::env::var("DEEPGRAM_API_KEY")?)?; ``` The credential travels in the handshake's `Authorization` header. `start()` uses the SaaS endpoint; `start_at_url()` accepts a custom host but requires `wss://` (plain `ws://` is allowed only for loopback, so local mock servers work). Do not hand-roll a raw `tokio_tungstenite::connect_async` session: the SDK client also supplies the shared rustls connector (so `rustls-tls-native-roots` and `Deepgram::tls_config` apply), the correct `Host` authority for non-default ports, and `Debug` redaction of provider credentials. ## Quick start ```rust use deepgram::agent::{ audio::{AudioConfig, AudioInput, AudioInputEncoding}, listen::{AgentListenProvider, AgentListenSettings, DeepgramListenV2Provider}, settings::{AgentConfig, InlineAgentConfig, SettingsMessage}, speak::{DeepgramSpeakModel, DeepgramSpeakProvider, SpeakProvider, SpeakSettings}, think::{OpenAiModel, OpenAiThinkProvider, ThinkProvider, ThinkSettings}, AgentEvent, AgentResponse, }; use deepgram::{Deepgram, DeepgramError}; use futures::stream::StreamExt; #[tokio::main] async fn main() -> Result<(), DeepgramError> { let dg = Deepgram::new(std::env::var("DEEPGRAM_API_KEY").unwrap())?; let (mut handle, mut events) = dg.agent().start().await?; handle .send_settings(SettingsMessage::new( AudioConfig::new( Some(AudioInput::new(AudioInputEncoding::Linear16, 16_000)), None, ), AgentConfig::inline( InlineAgentConfig::from_parts( AgentListenSettings::new(AgentListenProvider::DeepgramV2( DeepgramListenV2Provider::new("flux-general-en"), )), ThinkSettings::new(ThinkProvider::OpenAi(OpenAiThinkProvider::new( OpenAiModel::Gpt4oMini, ))), SpeakSettings::new(SpeakProvider::Deepgram(DeepgramSpeakProvider::new( DeepgramSpeakModel::Aura2ThaliaEn, ))), ) .with_greeting("Hello! How can I help today?"), ), )) .await?; // Stream microphone audio with handle.send_data(pcm) from another task. while let Some(event) = events.next().await { match event? { AgentEvent::Json(AgentResponse::ConversationText(c)) => { println!("{:?}: {}", c.role, c.content) } AgentEvent::Json(AgentResponse::Error(e)) => { eprintln!("{}: {}", e.code, e.description); break; } AgentEvent::Json(AgentResponse::Unknown(value)) => println!("unmodeled: {value}"), AgentEvent::Audio(bytes) => println!("{} bytes of agent audio", bytes.len()), _ => {} // AgentEvent and AgentResponse are #[non_exhaustive] } } Ok(()) } ``` ## Key parameters - Entry points: `dg.agent().start()`, `dg.agent().start_at_url(url)`. Both return `(AgentHandle, AgentEventStream)`. - `AgentHandle` client messages: `send_settings`, `send_update_listen`, `send_update_speak`, `send_update_think`, `send_update_prompt`, `send_inject_user_message`, `send_inject_agent_message`, `send_function_call_response`, `send_data` (binary audio), `keep_alive`, `force_end_turn`, `close`, and `send_raw_json` as the escape hatch for messages the SDK has not typed yet. - `AgentEventStream` implements `futures::Stream<Item = Result<AgentEvent>>`; `AgentEvent` is `Json(AgentResponse)` or `Audio(Bytes)`, interleaved in protocol order. - Settings: `AgentConfig::inline(InlineAgentConfig…)` or `AgentConfig::saved(uuid)` for a saved configuration. Listen providers are Deepgram V1 (Nova) and V2 (Flux STT, with `language_hints`, `eot_threshold`, `eager_eot_threshold`, `eot_timeout_ms`, `keyterms`); Think providers are OpenAI, Anthropic, AWS Bedrock, Google, and Groq; Speak providers are Deepgram, ElevenLabs, Cartesia, OpenAI, and AWS Polly. - Request id: `handle.request_id()` / `events.request_id()` from the upgrade header, or `AgentResponse::Welcome`'s `request_id` when the header is absent. ## API reference (layered) 1. **In-repo** - `src/agent/websocket.rs` (client, handle, event stream) - `src/agent/settings.rs`, `src/agent/messages.rs`, `src/agent/response.rs` - `src/agent/{audio,listen,think,speak,history,endpoint,aws_credentials}.rs` - `examples/agent/websocket/simple_agent.rs`, `examples/agent/websocket/function_calling.rs` - `tests/agent_websocket_local.rs` 2. **OpenAPI** - Raw spec: `https://developers.deepgram.com/openapi.yaml` - Voice Agent reference page: `https://developers.deepgram.com/reference/voice-agent/voice-agent` 3. **AsyncAPI** - Raw spec: `https://developers.deepgram.com/asyncapi.yaml` - Voice Agent channel reference: `https://developers.deepgram.com/reference/voice-agent/voice-agent` 4. **Context7** - `/llmstxt/developers_deepgram_llms_txt` 5. **Product docs** - `https://developers.deepgram.com/docs/voice-agent` ## Gotchas 1. **Its own host.** Voice Agent runs on `agent.deepgram.com`, not `api.deepgram.com`. `Deepgram::with_base_url` does not redirect it; use `start_at_url` for a self-hosted deployment. 2. **`Settings` comes first.** Send it before any audio, and wait for `SettingsApplied` before assuming the configuration is live. `Update*` messages are confirmed by their own `ListenUpdated` / `SpeakUpdated` / `ThinkUpdated` / `PromptUpdated` events. 3. **KeepAlive while silent.** The server closes sessions that go quiet; send `keep_alive()` every 8 seconds during an idle period. It does not extend the 2-hour session cap. 4. **Drain the event stream.** The handle and the stream are bounded channels, so send audio and consume events from separate tasks rather than queueing audio without reading. 5. **Sends fail once the session ends.** After a peer close or a transport error, every `send_*` on a retained handle returns an error instead of silently dropping the message; `close()` on an ended session is a no-op. 6. **Unmodeled events are preserved; malformed known ones are not swallowed.** An event whose `type` the SDK does not model lands in `AgentResponse::Unknown(serde_json::Value)` rather than breaking the stream — including the production `{"type":"EndOfTurn","trigger":"model"|"timeout"}` message from Flux STT listen providers, which is not in the published spec yet. An event whose `type` *is* modeled but whose payload does not fit its schema arrives as an `Err` item naming the event type, so a malformed `Error` event is never mistaken for an ignorable `Unknown`. A modeled event carrying an *unmodeled value* is neither: a `role` the SDK does not name arrives as `ConversationRole::Unknown(String)` holding the wire string, and a `History` entry matching neither modeled shape as `HistoryMessage::Unknown(serde_json::Value)`, so a new server enum value never ends the session. 7. **`force_end_turn` needs Flux STT.** With any other listen provider the server answers `FORCE_END_TURN_UNSUPPORTED` as a `Warning` and the turn does not end. 8. **Do not answer `FunctionCallCancelled`.** It reports calls the server abandoned; only `FunctionCallRequest` expects a `send_function_call_response`. ## Example files in this repo - `examples/agent/websocket/simple_agent.rs` — connect, configure, print events, close. - `examples/agent/websocket/function_calling.rs` — client-side function execution and `FunctionCallResponse`. ## Central product skills For cross-language Deepgram product knowledge — the consolidated API reference, documentation finder, focused runnable recipes, third-party integration examples, and MCP setup — install the central skills: ```bash npx skills add deepgram/skills ``` This SDK ships language-idiomatic code skills; `deepgram/skills` ships cross-language product knowledge (see `api`, `docs`, `recipes`, `examples`, `starters`, `setup-mcp`).
Ver no GitHub