MeetStream — MIA API Reference

View as Markdown

MIA (MeetStream Infrastructure Agent) configurations define how an AI agent behaves when deployed into a meeting. Use these endpoints to create, retrieve, update, and delete agent configurations programmatically — no dashboard required.

Base URL: https://api.meetstream.ai Authentication: Authorization: Token <YOUR_API_KEY> Content-Type: application/json

Applies to: Google Meet, Zoom, Microsoft Teams Support: docs.meetstream.ai · API: api.meetstream.ai

Before you start: Agent configurations require that you have configured the relevant provider API keys in MeetStream. Add keys via the MeetStream dashboard → Integrations page (or the Integrations API) before creating an agent that references those providers.


Endpoints

MethodPathDescription
POST/api/v1/miaCreate a new agent configuration
GET/api/v1/miaRetrieve one or all agent configurations
PUT/api/v1/miaUpdate an existing agent configuration
DELETE/api/v1/miaDelete an agent configuration

POST /api/v1/mia

Create a new agent configuration.

Request Body

FieldTypeRequiredDescription
agent_namestringYesDisplay name for this agent configuration
modestringYes"pipeline" or "realtime" — see Operating Modes
modelobjectYesLLM or realtime model configuration (see below)
voiceobjectPipeline onlyTTS voice configuration (see below)
transcriberobjectPipeline onlySTT transcription configuration (see below)
agentobjectNoAgent behavior: turn detection, VAD, interruptions, MCP servers, custom functions. Auto-filled with defaults if omitted (pipeline mode).
audioobjectNoAudio processing configuration. Defaults to { "sample_rate": 24000, "num_channels": 1 } if omitted.
wake_wordobjectNoWake word gating — pipeline mode only. words is required when enabled=true.
avatarobjectNoAvatar configuration (Anam provider)

Nested: model (Pipeline Mode)

FieldTypeRequiredDefaultDescription
providerstringYesLLM provider: "openai", "anthropic", "xai", or "google"
modelstringYesModel name — e.g. "gpt-4.1", "gpt-4.1-mini", "grok-3"
system_promptstringYesSystem prompt defining agent personality and behavior. Supports {{variable}} template placeholders — see Template Variables.
temperaturenumberNo0.8LLM temperature (0–2)
max_tokensintegerNo(none — model default)Maximum response tokens
first_messagestringNo""Pipeline greeting spoken when the bot joins. Supports {{variable}} placeholders.
top_pnumberNo(provider default)Nucleus-sampling control where supported
frequency_penaltynumberNo(provider default)Penalizes repeated token frequency where supported
presence_penaltynumberNo(provider default)Penalizes already-used tokens where supported

Nested: model (Realtime Mode)

FieldTypeRequiredDefaultDescription
providerstringYesRealtime provider: "openai", "xai", or "google"
modelstringNoper-providerModel name — auto-filled if omitted (see provider table below). xAI model is implicit (hardcoded server-side).
system_promptstringYesSystem prompt defining agent personality and behavior. Supports {{variable}} template placeholders — see Template Variables.
voicestringNoper-providerVoice name — auto-filled if omitted (see provider table below)
temperaturenumberNo0.8Temperature (0–2)
max_response_output_tokensintegerNo(model default)Max output tokens — OpenAI only, must be positive
thinking_configobjectNoGoogle Gemini thinking: { "include_thoughts": bool, "thinking_budget": int }
modalitiesarray[string]No["text", "audio"]Realtime output modalities. Use ["text"] for text-only output.
top_pnumberNo(provider default)Nucleus-sampling control where supported
enable_affective_dialogbooleanNofalseGoogle native-audio expressive responses
proactivitybooleanNofalseGoogle native-audio model may choose not to respond to irrelevant input
disable_automatic_activity_detectionbooleanNofalseDisable Gemini’s built-in VAD. Configure an external STT model when using this option.

Realtime providers — model and voice values

ProvidermodelDefault modelvoice optionsDefault voice
openai"gpt-realtime-mini", "gpt-realtime-1.5", "gpt-4o-realtime-preview", "gpt-4o-mini-realtime-preview"gpt-realtime-minialloy, ash, ballad, cedar, coral, echo, fable, marin, nova, onyx, sage, shimmer, versecoral
xaiNot needed (hardcoded internally)Ara, Eve, Leo, Rex, SalAra
google"gemini-2.5-flash-native-audio-preview-12-2025"gemini-2.5-flash-native-audio-preview-12-2025Puck, Charon, Kore, Fenrir, Aoede, Leda, Orus, ZephyrPuck

Nested: voice (Pipeline Mode)

FieldTypeRequiredDefaultDescription
providerstringYesTTS provider: "openai", "elevenlabs", or "xai"
voice_idstringYesVoice identifier for the chosen provider (see table below)
modelstringNoper-providerTTS model name — auto-filled based on provider if omitted (see table below)
speednumberNo1.0Playback speed multiplier (provider-dependent support)

Voice model defaults by provider

If you omit voice.model, the API fills it automatically:

ProviderDefault modelExample voice_id values
openaitts-1alloy, ash, coral, echo, fable, nova, onyx, sage, shimmer, verse
elevenlabseleven_turbo_v2_5Your ElevenLabs voice ID (e.g. cjVigY5qzO86Huf0OWal) — browse at elevenlabs.io. Other models: eleven_flash_v2_5, eleven_multilingual_v2
xaitts-1ara, eve, leo, rex

Important: ElevenLabs voice IDs are provider-specific UUIDs — do not use OpenAI voice names like "alloy" with provider: "elevenlabs". This will cause a 403 error from ElevenLabs.

Nested: transcriber (Pipeline Mode)

FieldTypeRequiredDefaultDescription
providerstringYesSTT provider: "openai", "deepgram", "assemblyai", or "xai"
modelstringNoper-providerSTT model name — auto-filled based on provider if omitted (see table below)
languagestringNo"en"Language code — e.g. "en", "es"
boostwordsarray[string]No[]Words to boost recognition accuracy. Also accepted as boost_words (normalised automatically). Wake word phrases are auto-merged into this list.

Transcriber model defaults by provider

If you omit transcriber.model, the API fills it automatically:

ProviderDefault modelOther valid models
deepgramnova-2nova-3, nova-2-conversationalai, nova-2-phonecall, flux-general
openaiwhisper-1
assemblyaiu3-rt-prouniversal-streaming, universal-streaming-multilingual
xaistt-1

Nested: agent

The agent block is optional. If omitted entirely on a pipeline-mode create, the API fills it with sensible defaults so you don’t need to specify every field.

FieldTypeRequiredDefaultDescription
response_modalitystringNo"audio""audio" for spoken output, "chat" for meeting-chat output, or "action" for silent tool execution. Legacy aliases such as "voice" are accepted.
turn_detectionstringNo"vad"Turn-detection strategy: "vad", "stt", "multilingual", or "manual"
endpointing_modestringNo"fixed""fixed" (constant delay) or "dynamic" (adapts to conversation rhythm)
interruption_modestringNo"vad""vad" (silence-based) or "adaptive" (LiveKit Cloud ML barge-in detection, pipeline mode)
enable_interruptionsbooleanNotrueWhether users can interrupt agent speech
user_away_timeoutnumberNo15Seconds of silence before the agent considers the user away
preemptive_generationbooleanNofalseStart LLM generation before the user finishes speaking
false_interruption_timeoutnumberNo2.0Seconds to wait before confirming a false interruption
resume_false_interruptionbooleanNotrueResume agent speech after a false interruption
interruptionsobjectNomode-specificInterruption thresholds: min_duration_seconds, word_threshold, and optional energy_threshold
vad_typestringNo"server_vad"Realtime VAD strategy. OpenAI also supports "semantic_vad".
vad_eagernessstringNo"medium"Semantic VAD eagerness: "auto", "low", "medium", or "high"
vad_deactivation_thresholdnumberNo(model default)Optional pipeline VAD deactivation threshold
min_endpointing_delaynumberNo0.5Minimum silence (seconds) before treating speech as complete
max_endpointing_delaynumberNo3.0Maximum silence (seconds) before forcing endpointing
vad_activation_thresholdnumberNo0.5VAD sensitivity (0–1, higher = less sensitive)
vad_min_silence_duration_msintegerNo550Milliseconds of silence needed to trigger endpointing
vad_min_speech_duration_msintegerNo50Minimum speech duration (ms) to start processing
vad_prefix_padding_duration_msintegerNo300Audio padding (ms) prepended to captured speech
toolsarray[string]No[]Built-in tool names to enable, currently current_time and weather_now
mcp_serversarray[object] or objectNo[]MCP server configurations. Arrays and named-object maps are accepted.
mcp_fail_openbooleanNotrueIf MCP startup fails, retry the agent session without MCP tools
custom_functionsarray[object]No[]User-defined HTTP endpoints registered as agent tools — see Custom Functions. Max 20 per agent.
tool_results_to_chatbooleanNofalseIn audio mode, also send compact tool-result details to meeting chat
speaker_aware_responsesbooleanNofalseWhen true, every user utterance is prefixed with the active speaker’s name (e.g. [Rahul]: ...) before reaching the LLM, so the agent can distinguish who is speaking on multi-participant calls. Pipeline mode only. See Speaker-Aware Responses.
speaker_aware_promptstringNoMeetStream defaultOptional instruction text appended to your model.system_prompt when speaker_aware_responses=true. Lets you customise how the LLM should interpret the bracketed [Speaker Name]: prefix (address people by name, summarise per-speaker at the end, ignore the names entirely, etc.). Max 2000 characters. If omitted, MeetStream supplies a sensible default. Has no effect when speaker_aware_responses=false. See Speaker-Aware Responses.

Nested: agent.mcp_servers[]

FieldTypeRequiredDescription
urlstringYesStreamable HTTP MCP endpoint (must be HTTPS)
headersobjectNoAuthentication headers — e.g. { "Authorization": "Bearer <token>" }. Environment expansion requires the entire value to be env:VAR_NAME.
allowed_toolsarray[string]NoWhitelist of tool names. Omit to allow all tools from this server
timeoutnumberNoPer-call timeout in seconds (default: 10)

Nested: agent.custom_functions[]

Each entry registers a single HTTPS endpoint as an LLM-callable tool. Authentication is handled by you — put a narrowly scoped bearer token or API key in headers. See the Custom Functions Guide for end-to-end setup and response-variable examples.

FieldTypeRequiredDescription
namestringYesSnake-case identifier matching ^[a-z][a-z0-9_]*$, max 64 chars. Unique per agent. Must not collide with built-ins (current_time, weather_now) or reserved prefixes (meetstream_, mia_, lk_).
descriptionstringYesShort natural-language description. Shown to the LLM so it knows when to call the function.
methodstringNoHTTP method: GET, POST, PATCH, PUT, or DELETE. Defaults to POST.
urlstringYesFully-qualified HTTPS URL. Hostname must resolve to a public IP (private/RFC-1918 targets are rejected for SSRF protection).
headersobjectNoExtra HTTP headers. {{variable}} placeholders are resolved from dynamic vars. Environment expansion requires the whole value to be env:VAR_NAME and a variable provisioned in the managed runtime. MeetStream always adds X-Bot-ID unless supplied; X-Agent-ID is optional and must not be required by your endpoint.
query_paramsobjectNoFlat key/value map appended as query string.
parametersobjectNoJSON Schema describing the arguments the LLM must supply. Must be {"type": "object", "properties": {...}, "required": [...]}. If omitted, the tool accepts no arguments.
payload_args_onlybooleanNoWhen true, the request body is the raw args object. When false (default), the body is {"name", "bot", "args"}.
timeout_snumberNoTotal request timeout in seconds. Range 1–120, default 30.
retriesintegerNoNumber of retries on 5xx / network errors (exponential backoff). Range 0–5, default 2.
response_cap_charsintegerNoMaximum characters of the response body passed back to the LLM. Range 1000–50000, default 15000. Longer responses are truncated with a trailing notice.
speak_during_executionbooleanNoWhen true, the agent emits a filler utterance while the HTTP call is in flight. Default false.
speak_during_promptstringNoFiller text to speak during execution (e.g. "Let me check that for you."). Only used when speak_during_execution=true. Max 500 chars. If omitted, a default filler (“One moment please.”) is used.
speak_after_executionbooleanNoDefault true. When false, the agent’s turn ends silently after the tool completes — useful for pure side-effect calls (e.g. create-ticket, update-CRM).
response_variablesarray[object]NoExtract values from a successful JSON response into in-memory session variables. They resolve in later custom-function templates and stored-prompt rebuilds. Max 20 entries per function.

By default, POST, PUT, and PATCH requests use the body {"name", "bot", "args"}. The bot object always contains bot_id; agent_id is optional. Its dynamic_vars contains values extracted from earlier custom-function responses, not the bot’s initial agent_config_params. GET and DELETE send no body unless payload_args_only=true.

Nested: agent.custom_functions[].response_variables[]

FieldTypeRequiredDescription
namestringYesVariable name matching ^[a-zA-Z_][a-zA-Z0-9_]*$, max 64 chars, unique within the function.
pathstringYesDot-notation path into the JSON response — e.g. "data.user.city". Brackets and $. prefixes are not allowed. Missing paths are skipped silently.

Nested: wake_word (Pipeline Mode Only)

FieldTypeRequiredDefaultDescription
enabledbooleanNotrue at pipeline runtimeWhether wake word gating is active. Set explicitly to false for always-on listening.
wordsarray[string] or stringYes when explicitly creating an enabled block["hey assistant", "hello bot"] at runtimeTrigger phrases. Comma-separated string or array. An explicit enabled=true block returns 400 if words is empty or missing.
timeoutnumberNo30Seconds the agent stays active after the wake word is heard. Each new utterance during this window rolls the timer forward.
bypass_below_participantsintegerNo0 (off)Auto-disable the wake-word gate when the meeting has at most this many human participants. The bot is not counted — set to 1 for 1:1 calls (you + bot = bypass active). 0 keeps the gate on regardless of meeting size. Range: 050. Reacts live to mid-call joins/leaves.
max_listening_windowintegerNo0 (off)Hard cap, in seconds, on a single listening session even if the user keeps talking. 0 disables the cap and preserves the rolling-extend behaviour. When set, the listening window cannot extend past wake-word-detected-at + max_listening_window — once it expires the user must say the wake word again. Range: 07200.

Runtime default: A pipeline agent with no stored wake_word block starts with gating enabled, the phrases ["hey assistant", "hello bot"], and a 30-second timeout. Set wake_word.enabled=false explicitly when the agent should listen to every utterance.

Tip — picking values: Leave both adaptive fields at 0 for shared meetings where the wake word is the privacy contract. Set bypass_below_participants: 1 for direct 1:1 calls. Combine max_listening_window: 600 with the default timeout: 30 for a hard ten-minute listening ceiling.

Speaker-Aware Responses

Pipeline mode only. When agent.speaker_aware_responses: true, every transcribed user utterance is prefixed with the active speaker’s display name before it reaches the LLM. The agent’s chat history then carries who-said-what context, which is critical for multi-participant calls (sales calls, panels, group standups) where the agent should address people by name and reason about turn-taking.

What the agent sees

Without speaker_aware_responses (default):

User: Can you summarise the action items so far?
User: I disagree with the budget number, can we revisit it?

With speaker_aware_responses: true:

User: [Rahul]: Can you summarise the action items so far?
User: [Priya]: I disagree with the budget number, can we revisit it?

The system prompt is automatically extended with a short instruction telling the LLM to use the names but not echo the bracketed prefix back in its replies.

Customising the instruction (speaker_aware_prompt)

The default instruction MeetStream appends is generic — “use the name to keep track of who said what, address participants by name when appropriate, do not include the bracketed prefix in your own replies”. For most agents this is all you need.

When you want different behaviour — e.g. only address the most senior participant, summarise per-speaker at the end of the call, or treat the names purely as metadata that the agent should never mention out loud — provide your own agent.speaker_aware_prompt. It’s appended to your model.system_prompt verbatim (with a leading blank line) whenever speaker_aware_responses=true. Limits:

  • Max 2000 characters.
  • Must be a string. null, empty string, or omitted field → MeetStream uses its default.
  • Has no effect when speaker_aware_responses is false (it’s still accepted by the API so configs round-trip cleanly).

The bracketing mechanism ([Rahul]: ...) is unconditional once speaker_aware_responses=truespeaker_aware_prompt only governs how the LLM interprets the prefix, not whether it appears.

Example custom prompts:

Each user message is prefixed with [Speaker Name]:. Track each participant's
viewpoint separately. When asked to summarise, group your summary by speaker.
Never repeat the bracketed prefix in your own replies and never address the
person by name unless they directly addressed you.
Each user message starts with [Speaker Name]:. Treat the speaker label as
internal metadata only — do not address anyone by name in your replies and
do not mention the bracketed prefix. Use the speaker information only to
decide whose follow-up question you are answering.
Messages are prefixed with [Speaker Name]:. The host is always [Rahul]; treat
their instructions as authoritative. Other participants are guests — answer
their questions briefly and defer back to the host. Strip the prefix from your
own replies.

Speaker accuracy by platform

PlatformHow the speaker is identifiedAccuracy
ZoomPer-user raw-audio callbacks tagged with SDK node_idStrongest source attribution
Google MeetMixed audio labelled from the current active-speaker state; per-track CSRC audio is best effortApproximate
Microsoft TeamsPer-participant tracks when available; otherwise mixed audio with dominant-speaker stateExact at source in isolated-track mode; approximate on fallback

The transcript prefix uses the latest speaker state when an utterance completes; it is not bound to a speaker-specific transcript span. Treat names as helpful conversational context, not forensic diarization. Rapid hand-offs, overlapping speech, and fallback mixed-audio paths can be misattributed.

Compatibility

  • STT providers: Works with any provider you configure in transcriber. No diarization flags or special setup required — the speaker label comes from the bot itself, not the STT provider.
  • Wake word: Compatible. Wake-word detection tokenises the transcript and ignores punctuation, so the bracketed prefix does not block matching.
  • Realtime mode: Not part of the documented speaker-prefix contract. Realtime providers ingest raw audio directly; do not rely on this field for speaker attribution.
  • Custom functions / MCP tools: Compatible. Tool calls are unaffected.

Example — enable speaker-aware responses

1{
2 "mode": "pipeline",
3 "agent_name": "Sales Coach",
4 "agent": {
5 "speaker_aware_responses": true,
6 "speaker_aware_prompt": "Each user message is prefixed with [Speaker Name]:. Track each participant's viewpoint separately and group your summaries by speaker. Never repeat the bracketed prefix in your own replies."
7 },
8 "model": {
9 "provider": "openai",
10 "model": "gpt-4o-mini",
11 "system_prompt": "You are a sales coach. Address participants by name.",
12 "first_message": "Hi everyone, I'll listen in and help summarise."
13 },
14 "transcriber": { "provider": "deepgram", "model": "nova-2" },
15 "voice": { "provider": "elevenlabs", "voice_id": "..." }
16}

Nested: avatar

Renders a video avatar on the bot’s participant tile. Requires an Anam API key configured via the Integrations API (config_type=avatar, provider=anam). See Virtual Avatars for capability details.

FieldTypeRequiredDescription
enabledbooleanNoWhether the avatar is active. Default: false
providerstringNoAvatar provider — currently "anam" only. Default: "anam"
avatar_idstringRequired when enabled=true and provider is "anam"Anam avatar identifier. Fetch valid ids via GET https://api.anam.ai/v1/avatars. Must be an avatar_id, not a persona_id — both are UUIDs and this is a common source of errors
avatar_modelstringNoOptional Anam avatarModel override passed through to the persona config
namestringNoOptional persona display name

Example Request — Pipeline Mode

$curl -X POST https://api.meetstream.ai/api/v1/mia \
> -H "Authorization: Token <YOUR_API_KEY>" \
> -H "Content-Type: application/json" \
> -d '{
> "agent_name": "Meeting Assistant",
> "mode": "pipeline",
> "model": {
> "provider": "openai",
> "model": "gpt-4.1",
> "system_prompt": "You are a helpful meeting assistant. Summarize key decisions and track action items.",
> "first_message": "Hello! I am your meeting assistant. How can I help today?"
> },
> "voice": {
> "provider": "openai",
> "voice_id": "nova"
> },
> "transcriber": {
> "provider": "deepgram",
> "model": "nova-3",
> "language": "en"
> },
> "agent": {
> "response_modality": "audio"
> }
> }'

Example Request — Realtime Mode

$curl -X POST https://api.meetstream.ai/api/v1/mia \
> -H "Authorization: Token <YOUR_API_KEY>" \
> -H "Content-Type: application/json" \
> -d '{
> "agent_name": "Fast Voice Agent",
> "mode": "realtime",
> "model": {
> "provider": "openai",
> "model": "gpt-4o-realtime-preview",
> "system_prompt": "You are a concise, helpful assistant.",
> "voice": "alloy"
> }
> }'

Example Request — Realtime Mode (xAI Grok)

$curl -X POST https://api.meetstream.ai/api/v1/mia \
> -H "Authorization: Token <YOUR_API_KEY>" \
> -H "Content-Type: application/json" \
> -d '{
> "agent_name": "Grok Agent",
> "mode": "realtime",
> "model": {
> "provider": "xai",
> "system_prompt": "You are a witty and helpful meeting assistant.",
> "voice": "Ara"
> }
> }'

Example Request — Realtime Mode (Google Gemini)

$curl -X POST https://api.meetstream.ai/api/v1/mia \
> -H "Authorization: Token <YOUR_API_KEY>" \
> -H "Content-Type: application/json" \
> -d '{
> "agent_name": "Gemini Agent",
> "mode": "realtime",
> "model": {
> "provider": "google",
> "system_prompt": "You are a thoughtful meeting assistant.",
> "voice": "Puck",
> "thinking_config": {
> "include_thoughts": true,
> "thinking_budget": 1024
> }
> }
> }'

Example Request — Pipeline Mode with Wake Words

$curl -X POST https://api.meetstream.ai/api/v1/mia \
> -H "Authorization: Token <YOUR_API_KEY>" \
> -H "Content-Type: application/json" \
> -d '{
> "agent_name": "Wake Word Agent",
> "mode": "pipeline",
> "model": {
> "provider": "openai",
> "model": "gpt-4.1",
> "system_prompt": "You are a helpful meeting assistant. Only respond when addressed."
> },
> "voice": {
> "provider": "elevenlabs",
> "voice_id": "21m00Tcm4TlvDq8ikWAM",
> "model": "eleven_turbo_v2_5"
> },
> "transcriber": {
> "provider": "deepgram",
> "model": "nova-3"
> },
> "wake_word": {
> "enabled": true,
> "words": ["hey assistant", "hello bot"],
> "timeout": 30,
> "bypass_below_participants": 1,
> "max_listening_window": 600
> }
> }'

The bypass_below_participants: 1 above tells the bot to skip wake-word gating when only one human is in the meeting (you + bot). The moment a second human joins, gating resumes automatically.

Example Request — Pipeline Mode with MCP Tools

$curl -X POST https://api.meetstream.ai/api/v1/mia \
> -H "Authorization: Token <YOUR_API_KEY>" \
> -H "Content-Type: application/json" \
> -d '{
> "agent_name": "Action Agent",
> "mode": "pipeline",
> "model": {
> "provider": "openai",
> "model": "gpt-4.1",
> "system_prompt": "Listen for action items. When someone says to create a ticket, use the Linear tool to create it. Do not speak unless asked."
> },
> "voice": {
> "provider": "elevenlabs",
> "voice_id": "21m00Tcm4TlvDq8ikWAM",
> "model": "eleven_turbo_v2_5"
> },
> "transcriber": {
> "provider": "deepgram",
> "model": "nova-3"
> },
> "agent": {
> "response_modality": "action",
> "mcp_servers": [
> {
> "url": "https://your-mcp-gateway.example.com/mcp",
> "headers": { "Authorization": "Bearer <MCP_TOKEN>" },
> "allowed_tools": ["create_issue", "list_issues"]
> }
> ]
> }
> }'

Example Request — Pipeline Mode with Custom Functions

Register two HTTPS endpoints as agent tools. The LLM sees them in the function-calling schema and can call them when the conversation warrants. The response body from lookup_order is captured into the session’s dynamic vars so later prompt updates can reference {{latest_order_status}}.

$curl -X POST https://api.meetstream.ai/api/v1/mia \
> -H "Authorization: Token <YOUR_API_KEY>" \
> -H "Content-Type: application/json" \
> -d '{
> "agent_name": "Support Agent",
> "mode": "pipeline",
> "model": {
> "provider": "openai",
> "model": "gpt-4.1",
> "system_prompt": "You are a support agent. When the caller asks about an order, call lookup_order. When they ask to open a ticket, call create_ticket.",
> "first_message": "Hi, I am your support assistant. How can I help today?"
> },
> "voice": { "provider": "openai", "voice_id": "nova" },
> "transcriber": { "provider": "deepgram", "model": "nova-3" },
> "agent": {
> "custom_functions": [
> {
> "name": "lookup_order",
> "description": "Look up the status of a customer order by order id.",
> "method": "POST",
> "url": "https://api.example.com/orders/lookup",
> "headers": {
> "Authorization": "Bearer <CUSTOM_FUNCTION_TOKEN>"
> },
> "parameters": {
> "type": "object",
> "required": ["order_id"],
> "properties": {
> "order_id": { "type": "string", "description": "Order id, e.g. ORD-1234" }
> }
> },
> "timeout_s": 20,
> "retries": 2,
> "response_cap_chars": 4000,
> "speak_during_execution": true,
> "speak_during_prompt": "One moment while I pull that up.",
> "response_variables": [
> { "name": "latest_order_status", "path": "data.order.status" }
> ]
> },
> {
> "name": "create_ticket",
> "description": "Create a support ticket. Call this when the caller explicitly asks to open a ticket.",
> "method": "POST",
> "url": "https://api.example.com/tickets",
> "parameters": {
> "type": "object",
> "required": ["subject", "body"],
> "properties": {
> "subject": { "type": "string" },
> "body": { "type": "string" },
> "priority": { "type": "string", "enum": ["low", "normal", "high"] }
> }
> },
> "speak_after_execution": false
> }
> ]
> }
> }'

Example Request — Realtime Mode with Anam Avatar

Renders a video avatar on the bot’s tile that lip-syncs to the agent’s voice. Requires an Anam API key stored via the Integrations API (config_type=avatar, provider=anam). Use GET https://api.anam.ai/v1/avatars to list your available avatar ids.

$curl -X POST https://api.meetstream.ai/api/v1/mia \
> -H "Authorization: Token <YOUR_API_KEY>" \
> -H "Content-Type: application/json" \
> -d '{
> "agent_name": "Avatar Agent",
> "mode": "realtime",
> "model": {
> "provider": "openai",
> "model": "gpt-realtime",
> "system_prompt": "You are a friendly customer success agent. Greet participants warmly and help them get started."
> },
> "voice": {
> "provider": "openai",
> "voice_id": "alloy"
> },
> "avatar": {
> "enabled": true,
> "provider": "anam",
> "avatar_id": "f0e7a8c4-1234-4abc-9def-0123456789ab"
> }
> }'

Response — 200 OK

1{
2 "message": "Agent configuration created successfully.",
3 "agent_config_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
4 "agent_config": {
5 "AgentConfigID": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
6 "UserID": "usr_xxxx",
7 "AgentName": "Meeting Assistant",
8 "Mode": "pipeline",
9 "Model": {
10 "provider": "openai",
11 "model": "gpt-4.1",
12 "system_prompt": "You are a helpful meeting assistant."
13 },
14 "Voice": { "provider": "openai", "voice_id": "nova" },
15 "Transcriber": { "provider": "deepgram", "model": "nova-3", "language": "en" },
16 "CreatedAt": "2026-04-22T10:00:00Z",
17 "UpdatedAt": "2026-04-22T10:00:00Z"
18 }
19}

GET /api/v1/mia

Retrieve a specific agent configuration by ID, or list all configurations for your account.

Query Parameters

ParameterTypeRequiredDescription
agent_config_idstringNoRetrieve a specific configuration by ID

If agent_config_id is omitted, all configurations for your account are returned.

Example — List All Configurations

$curl -X GET https://api.meetstream.ai/api/v1/mia \
> -H "Authorization: Token <YOUR_API_KEY>"

200 OK

1{
2 "agent_configs": [
3 {
4 "AgentConfigID": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
5 "UserID": "usr_xxxx",
6 "AgentName": "Meeting Assistant",
7 "Mode": "pipeline",
8 "Model": { "provider": "openai", "model": "gpt-4.1", "system_prompt": "..." },
9 "Voice": { "provider": "openai", "voice_id": "nova" },
10 "Transcriber": { "provider": "deepgram", "model": "nova-3" },
11 "CreatedAt": "2026-04-22T10:00:00Z",
12 "UpdatedAt": "2026-04-22T10:00:00Z"
13 }
14 ],
15 "count": 1
16}

Example — Get a Specific Configuration

$curl -X GET "https://api.meetstream.ai/api/v1/mia?agent_config_id=a1b2c3d4-e5f6-7890-abcd-ef1234567890" \
> -H "Authorization: Token <YOUR_API_KEY>"

200 OK

1{
2 "agent_config": {
3 "AgentConfigID": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
4 "UserID": "usr_xxxx",
5 "AgentName": "Meeting Assistant",
6 "Mode": "pipeline",
7 "Model": { "provider": "openai", "model": "gpt-4.1", "system_prompt": "..." },
8 "Voice": { "provider": "openai", "voice_id": "nova" },
9 "Transcriber": { "provider": "deepgram", "model": "nova-3" },
10 "Agent": { "response_modality": "audio" },
11 "CreatedAt": "2026-04-22T10:00:00Z",
12 "UpdatedAt": "2026-04-22T10:00:00Z"
13 }
14}

PUT /api/v1/mia

Update an existing agent configuration. Only fields present in the request body are updated — omitted fields are left unchanged.

Request Body

FieldTypeRequiredDescription
agent_config_idstringYesID of the configuration to update
agent_namestringNoNew display name
modestringNoChange mode: "pipeline" or "realtime". Triggers full re-validation of all mode-specific fields.
modelobjectNoReplace the model configuration
voiceobjectNoReplace the voice configuration (pipeline mode)
transcriberobjectNoReplace the transcription configuration (pipeline mode)
agentobjectNoReplace agent behavior settings
wake_wordobjectNoReplace wake word configuration
audioobjectNoReplace audio configuration
avatarobjectNoReplace avatar configuration

Note: Changing mode triggers full re-validation. Updating individual sections like model, voice, or transcriber validates that you have the required provider API keys but does not re-validate the full config structure.

Example — Update the System Prompt

$curl -X PUT https://api.meetstream.ai/api/v1/mia \
> -H "Authorization: Token <YOUR_API_KEY>" \
> -H "Content-Type: application/json" \
> -d '{
> "agent_config_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
> "model": {
> "provider": "openai",
> "model": "gpt-4.1-mini",
> "system_prompt": "You are a concise meeting assistant. Keep answers brief."
> }
> }'

Example — Update Agent Name and Wake Word

$curl -X PUT https://api.meetstream.ai/api/v1/mia \
> -H "Authorization: Token <YOUR_API_KEY>" \
> -H "Content-Type: application/json" \
> -d '{
> "agent_config_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
> "agent_name": "Scrum Bot",
> "wake_word": {
> "enabled": true,
> "words": ["hey scrum bot"],
> "timeout": 45
> }
> }'

Example — Switch from Pipeline to Realtime Mode

$curl -X PUT https://api.meetstream.ai/api/v1/mia \
> -H "Authorization: Token <YOUR_API_KEY>" \
> -H "Content-Type: application/json" \
> -d '{
> "agent_config_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
> "mode": "realtime",
> "model": {
> "provider": "openai",
> "model": "gpt-4o-realtime-preview",
> "system_prompt": "You are a concise meeting assistant.",
> "voice": "alloy"
> }
> }'

Response — 200 OK

1{
2 "message": "Agent configuration updated successfully.",
3 "agent_config": {
4 "AgentConfigID": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
5 "UserID": "usr_xxxx",
6 "AgentName": "Scrum Bot",
7 "Mode": "pipeline",
8 "Model": { "provider": "openai", "model": "gpt-4.1-mini", "system_prompt": "..." },
9 "Voice": { "provider": "openai", "voice_id": "nova" },
10 "Transcriber": { "provider": "deepgram", "model": "nova-3" },
11 "WakeWord": { "enabled": true, "words": ["hey scrum bot"], "timeout": 45 },
12 "UpdatedAt": "2026-04-22T11:00:00Z"
13 }
14}

DELETE /api/v1/mia

Permanently delete an agent configuration. This action cannot be undone.

Query Parameters

ParameterTypeRequiredDescription
agent_config_idstringYesID of the configuration to delete

Example

$curl -X DELETE "https://api.meetstream.ai/api/v1/mia?agent_config_id=a1b2c3d4-e5f6-7890-abcd-ef1234567890" \
> -H "Authorization: Token <YOUR_API_KEY>"

200 OK

1{
2 "message": "Agent configuration deleted successfully."
3}

Error Codes

HTTP StatusWhen it occurs
400Missing required field, invalid value, unsupported provider, or provider API key not configured
403You do not own this agent configuration
404Agent configuration or user not found
405HTTP method not allowed on this path
500Internal server error

Common Error Responses

Missing provider API key

1{
2 "message": "API key not configured for: model.provider=openai (missing OpenAIAPIKey). Add it via the Integrations API first."
3}

Missing required field

1{
2 "message": "Missing agent_name."
3}

Invalid mode

1{
2 "message": "Invalid mode: batch. Must be 'pipeline' or 'realtime'."
3}

Unsupported provider

1{
2 "message": "Unsupported model provider: cohere. Supported: ['openai', 'anthropic', 'xai', 'google']"
3}

Invalid realtime voice

1{
2 "message": "Invalid OpenAI realtime voice: 'shimmy'. Supported: ['alloy', 'ash', 'ballad', 'cedar', 'coral', 'echo', 'fable', 'marin', 'nova', 'onyx', 'sage', 'shimmer', 'verse']"
3}

Invalid xAI voice

1{
2 "message": "Invalid xAI voice: 'Bob'. Supported: ['Ara', 'Eve', 'Leo', 'Rex', 'Sal']"
3}

Invalid Gemini voice

1{
2 "message": "Invalid Gemini voice: 'Zeus'. Supported: ['Aoede', 'Charon', 'Fenrir', 'Kore', 'Leda', 'Orus', 'Puck', 'Zephyr']"
3}

Access denied

1{
2 "message": "Access denied to this agent configuration."
3}

Server-Side Defaults (Pipeline Mode)

When creating a pipeline agent, the API automatically fills missing optional fields so the stored config matches what the internal dashboard produces. You can override any default by including the field explicitly.

SectionFieldDefaultNotes
modeltemperature0.8
modelfirst_message""
voicemodelper-provider (see voice defaults)openaitts-1, elevenlabseleven_turbo_v2_5, xaitts-1
voicespeed1.0
transcriberlanguage"en"
audiosample_rate24000Must be 24000 for OpenAI realtime compatibility
audionum_channels1
agent(entire block)see agent defaultsturn_detection=vad, endpointing_mode=fixed, user_away_timeout=15, etc.

Field-name normalization: model.max_token is auto-corrected to model.max_tokens. transcriber.boost_words is auto-corrected to transcriber.boostwords.


Supported Providers

For the full list of supported realtime and pipeline providers, voices, models, and capabilities (wake words, interruption, VAD, MCP, echo cancellation, etc.), see the MeetStream MIA Reference.


Template Variables

Agent config prompts support Mustache-style {{variable}} placeholders in model.system_prompt and model.first_message. This lets you create a reusable agent config once and customize it per-bot at creation time by passing different variable values.

How It Works

  1. Define placeholders in your agent config prompt using {{variable_name}} syntax.
  2. Pass values via the agent_config_params field when creating a bot.
  3. Placeholders are resolved before the agent session starts — the LLM receives the fully substituted prompt.

Variable names can contain letters, digits, and underscores (\w+). Unresolved placeholders (no matching key in agent_config_params) are left as-is in the prompt.

Example — Reusable Sales Agent

Step 1: Create an agent config with template variables

$curl -X POST https://api.meetstream.ai/api/v1/mia \
> -H "Authorization: Token <YOUR_API_KEY>" \
> -H "Content-Type: application/json" \
> -d '{
> "agent_name": "Sales Agent Template",
> "mode": "pipeline",
> "model": {
> "provider": "openai",
> "model": "gpt-4.1",
> "system_prompt": "You are a sales assistant for {{company_name}}. You are speaking with {{customer_name}}. Focus on {{product_line}}. {{extra_instructions}}",
> "first_message": "Hi {{customer_name}}, thanks for joining! I am here to help you with {{product_line}}."
> },
> "voice": {
> "provider": "openai",
> "voice_id": "nova"
> },
> "transcriber": {
> "provider": "deepgram",
> "model": "nova-3",
> "language": "en"
> }
> }'

Step 2: Create bots with different variable values

$curl -X POST https://api.meetstream.ai/api/v1/bots/create_bot \
> -H "Authorization: Token <YOUR_API_KEY>" \
> -H "Content-Type: application/json" \
> -d '{
> "meeting_link": "https://meet.google.com/abc-defg-hij",
> "agent_config_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
> "agent_config_params": {
> "company_name": "Acme Corp",
> "customer_name": "Sarah",
> "product_line": "enterprise analytics",
> "extra_instructions": "Mention the Q2 discount if asked about pricing."
> }
> }'

The agent receives this resolved prompt:

You are a sales assistant for Acme Corp. You are speaking with Sarah. Focus on enterprise analytics. Mention the Q2 discount if asked about pricing.

And the first message spoken to the meeting:

Hi Sarah, thanks for joining! I am here to help you with enterprise analytics.

Example — Fully Dynamic Prompt

You can use a single {{prompt}} placeholder to make the entire system prompt dynamic:

$# Agent config with: "system_prompt": "{{prompt}}"
$
$curl -X POST https://api.meetstream.ai/api/v1/bots/create_bot \
> -H "Authorization: Token <YOUR_API_KEY>" \
> -H "Content-Type: application/json" \
> -d '{
> "meeting_link": "https://meet.google.com/abc-defg-hij",
> "agent_config_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
> "agent_config_params": {
> "prompt": "You are a strict meeting moderator. Enforce a 2-minute speaking limit per person. Warn participants when they are approaching the limit."
> }
> }'

agent_config_params Reference

FieldTypeDescription
agent_config_paramsobjectKey-value map of template variable values. Keys must be strings matching {{key}} placeholders in the prompt. Values are coerced to strings.

Custom Functions

Custom functions let your agent call any HTTPS endpoint you host as a tool. Pair them with, or use them instead of, MCP: use MCP when you already run a multi-tool MCP server; use custom functions when you want to register a single endpoint without standing up MCP.

What you get per function

  • JSON Schema arguments (the LLM generates correctly-typed args).
  • Custom headers with {{variable}} substitution, plus automatic X-Bot-ID and X-Agent-ID context headers.
  • Automatic retries on 5xx / network errors with exponential backoff.
  • Configurable response cap so long payloads don’t overwhelm the model.
  • Optional filler utterance while the HTTP call runs (speak_during_execution) and optional silent return once it finishes (speak_after_execution=false).
  • Optional response variables — values pulled from successful JSON responses via dot-notation paths. They are immediately available to later custom-function templates and to stored-prompt template rebuilds triggered by update_mia.

See agent.custom_functions[] for the full field table and the Custom Functions Guide for an end-to-end example.


Mid-Call Updates (update_mia)

Request an asynchronous update to the agent’s prompt, template variables, or wake-word state while the bot is live in a meeting. A successful HTTP response confirms that the command was accepted and forwarded; it does not wait for an application acknowledgement from the active agent session.

Endpoint

POST https://api.meetstream.ai/api/v1/bots/{bot_id}/update_mia
ParameterLocationRequiredDescription
bot_idPathYesThe bot ID returned from create_bot
AuthorizationHeaderYesToken <YOUR_API_KEY>

Request Body

FieldTypeRequiredDescription
agent_config_paramsobjectAt least oneNew template variable values to merge into existing params. Maximum 50 keys; values must be strings, numbers, or booleans.
system_promptstringAt least oneA literal system prompt that replaces the agent’s current instructions entirely (no template resolution). Max 32,000 characters.
wake_word_enabledbooleanAt least oneToggle wake-word gating on or off live. Once set, this supersedes the automatic bypass_below_participants behaviour for the rest of the call — the user-supplied state wins regardless of meeting size. See Live wake-word control.
wake_wordsarray[string]At least oneReplace the wake-word phrase list live. Max 10 phrases, each up to 64 characters after trim. Empty array is rejected — use wake_word_enabled: false to disable the gate.

Note: At least one of agent_config_params, system_prompt, wake_word_enabled, or wake_words is required. If both agent_config_params and system_prompt are provided, system_prompt takes precedence. A supplied system_prompt is literal and is not template-resolved. The wake-word fields are applied first.

Merge Behavior for agent_config_params

New params are merged into the bot’s existing AgentConfigParams in DynamoDB — they do not replace them. For example, if the bot was created with:

1{ "company_name": "Acme Corp", "customer_name": "Sarah", "product_line": "analytics" }

And you send:

1{ "agent_config_params": { "customer_name": "John", "extra_instructions": "Offer a demo" } }

The merged result used for template resolution is:

1{ "company_name": "Acme Corp", "customer_name": "John", "product_line": "analytics", "extra_instructions": "Offer a demo" }

The original template from the agent config is re-resolved against the merged params.

Example — Update Template Variables Mid-Call

$curl -X POST "https://api.meetstream.ai/api/v1/bots/{bot_id}/update_mia" \
> -H "Authorization: Token <YOUR_API_KEY>" \
> -H "Content-Type: application/json" \
> -d '{
> "agent_config_params": {
> "customer_name": "John",
> "extra_instructions": "The customer just asked about pricing — mention the Q2 discount."
> }
> }'

Example — Replace the System Prompt Entirely

$curl -X POST "https://api.meetstream.ai/api/v1/bots/{bot_id}/update_mia" \
> -H "Authorization: Token <YOUR_API_KEY>" \
> -H "Content-Type: application/json" \
> -d '{
> "system_prompt": "You are now in wrap-up mode. Summarize the key decisions from the meeting and list action items."
> }'

Live wake-word control

wake_word_enabled and wake_words give you runtime control over the wake-word system without needing to update the agent config or restart the bot.

Behaviour

  • wake_word_enabled: true forces the gate on: the agent stays gated even if the meeting drops below bypass_below_participants (e.g. a 1:1 call where the gate would normally auto-bypass). The agent waits for a wake phrase before responding.
  • wake_word_enabled: false forces the gate off: the agent listens to every utterance regardless of meeting size. Useful for “always-on” modes, push-to-talk dashboards, or debugging.
  • wake_words: [...] replaces the entire phrase list. Subsequent utterances are matched against the new list (whole-token, case-insensitive, punctuation-insensitive). Phrases configured at agent-config creation time are no longer matched.
  • Either field is sticky for the rest of the session — it overrides the agent-config defaults and the participant-count bypass until the bot leaves the meeting (or you call update_mia again with a different value).
  • Both fields are accepted in a single call. Phrases are applied first, then the on/off override, then any prompt update.

Override semantics — important

wake_word_enabled supersedes the automatic bypass_below_participants logic configured on the agent. Once you call update_mia with wake_word_enabled, the platform-side participant-count bypass is no longer consulted for that bot — your explicit setting is authoritative until the bot leaves. This lets you take full control from a dashboard or runtime workflow without fighting the platform.

Examples

Disable the gate for the rest of the call (always-on listening):

$curl -X POST "https://api.meetstream.ai/api/v1/bots/{bot_id}/update_mia" \
> -H "Authorization: Token <YOUR_API_KEY>" \
> -H "Content-Type: application/json" \
> -d '{ "wake_word_enabled": false }'

Re-enable the gate (e.g. when guests join the call):

$curl -X POST "https://api.meetstream.ai/api/v1/bots/{bot_id}/update_mia" \
> -H "Authorization: Token <YOUR_API_KEY>" \
> -H "Content-Type: application/json" \
> -d '{ "wake_word_enabled": true }'

Switch wake phrases mid-call (e.g. swap to a meeting-specific code phrase):

$curl -X POST "https://api.meetstream.ai/api/v1/bots/{bot_id}/update_mia" \
> -H "Authorization: Token <YOUR_API_KEY>" \
> -H "Content-Type: application/json" \
> -d '{ "wake_words": ["hey ada", "ok ada", "ada listen"] }'

Combined update — switch into always-on, replace wake phrases, and pivot the prompt in one call:

$curl -X POST "https://api.meetstream.ai/api/v1/bots/{bot_id}/update_mia" \
> -H "Authorization: Token <YOUR_API_KEY>" \
> -H "Content-Type: application/json" \
> -d '{
> "wake_word_enabled": false,
> "wake_words": ["hey ada"],
> "system_prompt": "You are now in active assistant mode. Respond to every utterance."
> }'

Validation errors (400)

ErrorCause
wake_word_enabled must be a boolean (true or false)Non-bool value supplied.
wake_words must be an array of stringsWrong type (string, object, etc.).
wake_words cannot be empty — use 'wake_word_enabled': false to disable the gateEmpty list.
wake_words exceeds 10 phrase limitMore than 10 entries.
wake_words[N] cannot be empty after trimWhitespace-only entry.
wake_words[N] exceeds 64 character limitSingle phrase too long.

Persistence: live overrides are held in-memory on the agentic task. If the agentic task is replaced (rolling deploy), the bot reverts to the wake-word settings configured on its agent. To make a setting permanent, also update the agent config via the standard PUT /api/v1/mia endpoint.

Response (200)

This response means accepted for asynchronous delivery, not confirmed application:

1{
2 "status": "accepted",
3 "bot_id": "83acdd72-3257-4b06-a2e9-0d879dc571ff",
4 "command": "update_mia"
5}

Conditions

  • The bot must have an active MIA agent session (created with agent_config_id).
  • The bot must be in the meeting (Joining or InMeeting status).
  • Rate limit: 30 bot-command requests per minute per bot, shared with other commands on this endpoint.
  • Works on all platforms: Google Meet, Zoom, Microsoft Teams.

Error Responses

StatusMeaning
400Missing both agent_config_params and system_prompt, or invalid field types.
401Missing or invalid API key.
403Bot does not belong to your account.
404Bot not found.
409Bot is not currently in a meeting.
429Rate limit exceeded (30/min per bot).
503Bot is unreachable or has no active MIA session.

Using an Agent Config with a Bot

Pass agent_config_id when creating a bot to attach the agent to a meeting session. The agent becomes active as soon as the bot joins. WebSocket URLs for socket_connection_url and live_audio_required are auto-populated when agent_config_id is present — you do not need to provide them.

$curl -X POST https://api.meetstream.ai/api/v1/bots/create_bot \
> -H "Authorization: Token <YOUR_API_KEY>" \
> -H "Content-Type: application/json" \
> -d '{
> "meeting_link": "https://meet.google.com/abc-defg-hij",
> "agent_config_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
> }'

To customize the prompt per-bot, add agent_config_params (see Template Variables):

$curl -X POST https://api.meetstream.ai/api/v1/bots/create_bot \
> -H "Authorization: Token <YOUR_API_KEY>" \
> -H "Content-Type: application/json" \
> -d '{
> "meeting_link": "https://meet.google.com/abc-defg-hij",
> "agent_config_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
> "agent_config_params": {
> "name": "John",
> "command": "welcome to the meeting"
> }
> }'

See the Create Bot Payload Reference for all available bot creation options.