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.

Quellinformationen

Repository
deepgram/deepgram-rust-sdk
Letzte Quellaktivität
8. Oktober 2026 um 12:56
Erkannte Sprache von SKILL.md
Englisch
Sterne
67
Forks
45

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
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`).
Auf GitHub ansehen