> ## Documentation Index
> Fetch the complete documentation index at: https://app.miyon.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Set up a voice agent

> Create a voice agent, then shape how it talks and sounds with recipes for the common settings.

This guide takes you from a new voice agent to one that greets callers, follows
your instructions and sounds the way you want. Create the agent with one request,
then adjust it through the settings endpoints.

## Create the agent

`POST /api/v1/voice_agents` needs only a `name`. Set the instructions, the
greeting and the language in the same request so the agent is usable right away:

```bash theme={null}
curl -X POST https://app.miyon.ai/api/v1/voice_agents \
  -H "Authorization: Bearer <your-api-token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Booking agent",
    "prompt": {
      "user_prompt": "You are the receptionist of Example Dental. Book, move and cancel appointments...",
      "initial_response": "Hello, this is the booking line of Example Dental. How can I help?",
      "transcription_locale": "en"
    },
    "voice_config": {
      "voice_config.tts_voice": "elevenlabs_Dm2pqleCzqJpMQgIh5nm"
    }
  }'
```

The `voice_config` block is optional and takes the same keys and values as the
settings below. Every value is validated as if you had set it with the settings
endpoints; if one is rejected, nothing is created and the API returns `422`. Keep
the returned `id` - all settings and tools use it.

Afterwards:

* Add tools with `POST /api/v2/tools`, using the agent's `id` as `agent_id`. See
  [Tools](/docs/en/tools).
* Connect a phone number in the dashboard. See [AI numbers](/docs/en/ai-numbers).

## What you configure where

A voice agent has three settings groups. Each has a read, an update and a schema
endpoint under `/api/v1/voice_agents/{id}/concerns/<group>`.

| Group | What it controls | Typical changes |
| - | - | - |
| `prompts` | **What the agent says and does** | Instructions, greeting, language, global behavior rules |
| `voice_config` | **How the agent sounds, and how the call runs** | Voice, language model, conversation type, response time, timeouts, recording |
| `knowledge_base` | **What the agent may look up** | Which knowledge sources it uses |

If you only want an agent that answers calls with your instructions, you need the
`prompts` group. The defaults in `voice_config` work without changes.

## How a change works

1. **Read the schema** - `GET .../concerns/<group>/schema`. It lists every setting
   (`fields[].key`), its type (`value_type`), its limits (`validation`) and, for
   selection fields, the accepted values (`option_sets[field.options_ref]`).
2. **Write one setting** - `PATCH .../concerns/<group>` with
   `{ "key": "<fields[].key>", "value": <value> }`. One setting per request.
3. **Check `effects`** - the response lists every related setting the server
   changed along with yours, with the old and the new value. `values` is the
   resulting configuration.

Read the schema again after changing a field marked `affects_schema: true`
(conversation type, language model, speech model, voice): the options of related
fields change with it.

> [!TIP]
>
> Labels and option descriptions in the schema are localized. Add `?locale=en`
> (or `de`, `es`) to choose the language; the response states it in the
> `Content-Language` header. Always send an option's `value`, never its `label`.

## Recipes

Each recipe changes one setting of an existing agent. Agent `789` in the
examples; responses are shortened.

### Set the greeting

The greeting is the first sentence the agent says when it picks up, up to 1000
characters. `%%caller_number%%`, `%%called_number%%` and
`%%forwarded_from_number%%` are replaced with the live call's numbers.

```bash theme={null}
curl -X PATCH https://app.miyon.ai/api/v1/voice_agents/789/concerns/prompts \
  -H "Authorization: Bearer <your-api-token>" \
  -H "Content-Type: application/json" \
  -d '{ "key": "prompts.initial_response", "value": "Hello, this is the booking line of Example Dental. How can I help?" }'
```

### Change the instructions and the language

`prompts.user_prompt` holds the instructions: the agent's role, what it should
find out and how it should answer. The [prompting guide](/docs/en/ai-prompts) explains
how to write them.

```bash theme={null}
curl -X PATCH https://app.miyon.ai/api/v1/voice_agents/789/concerns/prompts \
  -H "Authorization: Bearer <your-api-token>" \
  -H "Content-Type: application/json" \
  -d '{ "key": "prompts.user_prompt", "value": "You are the receptionist of Example Dental. Book, move and cancel appointments..." }'
```

`prompts.transcription_locale` is the language the agent listens in: `de`, `en`,
`fr` and so on, or `xx` when callers may speak different languages. The full list
is in `option_sets["prompts.transcription_locales"]`.

```bash theme={null}
curl -X PATCH https://app.miyon.ai/api/v1/voice_agents/789/concerns/prompts \
  -H "Authorization: Bearer <your-api-token>" \
  -H "Content-Type: application/json" \
  -d '{ "key": "prompts.transcription_locale", "value": "en" }'
```

### Pick a voice

Voices are listed in `option_sets["voice_config.tts_voices"]`, each with a
`label`, `provider`, `gender` and a short `description`:

```bash theme={null}
curl "https://app.miyon.ai/api/v1/voice_agents/789/concerns/voice_config/schema?locale=en" \
  -H "Authorization: Bearer <your-api-token>"
```

```json theme={null}
{
  "option_sets": {
    "voice_config.tts_voices": [
      { "value": "elevenlabs_v3V1d2rk6528UrLKRuy8", "label": "Susi", "provider": "elevenlabs", "gender": "female", "description": "Effortless and confident" },
      { "value": "elevenlabs_Dm2pqleCzqJpMQgIh5nm", "label": "Alex", "provider": "elevenlabs", "gender": "male", "description": "Upbeat, energetic and clear" },
      { "value": "Nina", "label": "Nina", "provider": "soniox", "gender": "female", "description": "Bright, expressive and friendly" }
    ]
  }
}
```

Send the `value` exactly as listed:

```bash theme={null}
curl -X PATCH https://app.miyon.ai/api/v1/voice_agents/789/concerns/voice_config \
  -H "Authorization: Bearer <your-api-token>" \
  -H "Content-Type: application/json" \
  -d '{ "key": "voice_config.tts_voice", "value": "elevenlabs_Dm2pqleCzqJpMQgIh5nm" }'
```

The speech model follows the voice: a voice from another provider also switches
`voice_config.tts` to that provider's model, and `effects` shows it. To use a
different model of the **same** provider (for example ElevenLabs Flash instead of
v3 Conversational), set `voice_config.tts` afterwards; the voice is kept.
Choosing a model of another provider resets the voice to that provider's default.

### Choose the language model

The language model writes the agent's answers. Pick a `value` from
`option_sets["voice_config.llm_models"]`:

```bash theme={null}
curl -X PATCH https://app.miyon.ai/api/v1/voice_agents/789/concerns/voice_config \
  -H "Authorization: Bearer <your-api-token>" \
  -H "Content-Type: application/json" \
  -d '{ "key": "voice_config.llm", "value": "openai/gpt-4.1" }'
```

`voice_config.response_style` (0 to 1) controls how varied the answers are: lower
is more predictable, higher is more creative.

### Switch the conversation type

`voice_config.model_mode` decides how the agent processes speech:

| Value | How it works | Choose it when |
| - | - | - |
| `pipeline` | Standard. Speech is transcribed, the language model answers in text, a separate voice speaks the answer. | You want the full choice of language models and voices, key terms for speech recognition, and the most predictable behavior. |
| `realtime` | One realtime model listens and speaks directly, with its own built-in voices. | Low latency and natural turn-taking matter more than the choice of voice. |

```bash theme={null}
curl -X PATCH https://app.miyon.ai/api/v1/voice_agents/789/concerns/voice_config \
  -H "Authorization: Bearer <your-api-token>" \
  -H "Content-Type: application/json" \
  -d '{ "key": "voice_config.model_mode", "value": "realtime" }'
```

> [!WARNING]
>
> Switching the conversation type resets the language model, speech models, voice
> and response time to the defaults of the new type, and replaces the global
> behavior rules (`prompts.system_prompt`) with that type's default. Switch first,
> then read the schema again and apply your own choices.

### Tune response time and call limits

`voice_config.response_time_ms` is how long the agent waits after the caller
stops speaking before it answers. The field's `presets` are `0` (fast), `700`
(balanced) and `1200` (patient).

```bash theme={null}
curl -X PATCH https://app.miyon.ai/api/v1/voice_agents/789/concerns/voice_config \
  -H "Authorization: Bearer <your-api-token>" \
  -H "Content-Type: application/json" \
  -d '{ "key": "voice_config.response_time_ms", "value": 1200 }'
```

The timeouts and the maximum call duration take seconds, with `-1` for "off"
(the field's `validation.disabled_value`). Any other value must be at least
`validation.min`. To end calls after ten minutes:

```bash theme={null}
curl -X PATCH https://app.miyon.ai/api/v1/voice_agents/789/concerns/voice_config \
  -H "Authorization: Bearer <your-api-token>" \
  -H "Content-Type: application/json" \
  -d '{ "key": "voice_config.max_call_duration_seconds", "value": 600 }'
```

## Settings reference

The schema decides what an agent accepts right now. These tables explain what
each setting does.

### Prompt settings (`prompts`)

| Key | What it does |
| - | - |
| `prompts.name`, `prompts.description` | Name and description, as shown in the dashboard. |
| `prompts.user_prompt` | Instructions: the agent's role, task and how it answers. |
| `prompts.initial_response` | Greeting, spoken first. Up to 1000 characters. |
| `prompts.system_prompt` | Global behavior rules applied on top of the instructions, for example the current date and time. Each conversation type has its own default, and switching the type or ElevenLabs text normalization replaces it. |
| `prompts.transcription_locale` | Language the agent listens in. `xx` is multilingual. |
| `prompts.mute_user_while_assistant_speaks` | `true`: the caller cannot interrupt the agent while it speaks. |
| `prompts.response_style` | Chat agents only. Voice agents use `voice_config.response_style`. |

`option_sets["prompts.variable_suggestions"]` lists the variables, such as
`%%caller_number%%`, you can use in the instructions.

### Voice settings (`voice_config`)

| Key | What it does |
| - | - |
| `voice_config.model_mode` | Conversation type: `pipeline` or `realtime`. |
| `voice_config.llm` | Language model that writes the answers. |
| `voice_config.response_style` | 0 to 1. Lower is more predictable, higher more creative. |
| `voice_config.stt` | Speech recognition model. Not writable through the API yet. |
| `voice_config.tts` | Speech model that speaks the answers (`pipeline` only). |
| `voice_config.tts_voice` | Voice. |
| `voice_config.elevenlabs.text_normalization` | ElevenLabs speaks numbers, dates and currencies naturally. Turning it on or off also replaces the global behavior rules. |
| `voice_config.elevenlabs.speed`, `.style`, `.stability` | ElevenLabs voice tuning. `stability` is locked while text normalization is on. |
| `voice_config.soniox.speed` | Speaking speed of Soniox voices. |
| `voice_config.speech_recognition_terms` | Words the recognizer should expect: product names, street names, jargon. |
| `voice_config.speech_recognition_context` | A short text about the calls' topic that helps recognition. |
| `voice_config.response_time_ms` | Pause after the caller stops speaking before the agent answers. |
| `voice_config.turn_detector` | `livekit` detects the end of the caller's turn from what they say, not only from silence. `null` uses silence. |
| `voice_config.noise_suppression` | 0 to 100. Filters background noise. |
| `voice_config.background_audio.mode`, `.volume` | Ambient sound under the call (office, city, ...). |
| `voice_config.tool_sound.mode`, `.volume` | Sound played while a tool runs, such as keyboard typing. |
| `voice_config.inactivity_timeout_seconds` | Seconds of caller silence before the agent asks whether they are still there. `-1` is off. |
| `voice_config.followup_timeout_seconds` | Seconds after that question before the agent ends the call. `-1` waits indefinitely. Needs the inactivity timeout. |
| `voice_config.max_call_duration_seconds` | Hard limit for a call. `-1` is off. |
| `voice_config.wait_for_user_response` | Outbound calls: the agent waits for the callee to speak before greeting. |
| `voice_config.recording_enabled` | Records call audio. |
| `voice_config.transcript_retention` | How long transcripts are kept: `full`, `delete_after_ttl` (with a `ttl` from the field's `ttl_options`), `zero`, or `zero_after_postprocessing`. |
| `voice_config.actions.license_plate_pronunciation` | Improves how the agent pronounces vehicle license plates. |

### Fields you cannot write

A field whose `capabilities.writable` is `false` is rejected on write.
`capabilities.reason` says why:

| Reason | Meaning |
| - | - |
| `not_yet_available` | Not available through the API yet. |
| `locked_by_text_normalization` | Turn off `voice_config.elevenlabs.text_normalization` first. |
| `field_requires_elevenlabs_provider`, `field_requires_soniox_provider` | Applies only to that provider's voices. |
| `requires_background_audio_enabled`, `requires_tool_sound_enabled` | Choose a sound first. |
| `requires_inactivity_timeout_enabled` | Set the inactivity timeout first. |
| `requires_outgoing_calls_enabled` | Outbound calling is not enabled for your account. |
| `realtime_uses_native_stt`, `realtime_uses_native_voice`, `unavailable_in_realtime_mode` | Not used by the `realtime` conversation type. |
| `retention_disables_recording` | Recording is off because transcripts are not kept. |
| `subprompt_inherits_initial_prompt` | Set on the agent's main prompt; follow-up prompts inherit it. |

## Concurrent edits: `If-Match`

Every read and write returns a `revision`. Send it as the `If-Match` header on a
`PATCH`. If the configuration changed since that read, for example in the
dashboard, nothing is saved and the API returns `409` with the current
`revision` and `values`. `If-Match` is optional; without it the write always
applies.

## Rejected values

A value the schema does not allow returns `422`, with `errors` keyed by field.
`values` and `revision` show the unchanged state:

```json theme={null}
{
  "concern": "prompts",
  "schema_version": "prompts.v4",
  "revision": "prompt:987:prompts:sha256:9c2e4f0a...",
  "values": { "prompts.mute_user_while_assistant_speaks": false },
  "effects": [],
  "errors": { "prompts.mute_user_while_assistant_speaks": ["must be a boolean"] },
  "affected_concerns": []
}
```

When a selection value is rejected, read the schema again: the options usually
changed because of an earlier change.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.