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

# Per-channel configuration

> Make one agent behave differently on phone, web, email, text, and SMS.

One agent can run across phone, web chat, email, text, and SMS. Per-channel configuration lets you tune how that agent thinks and how its replies are rendered on each channel, without forking the agent. Both maps are optional and additive: when a channel has no entry it inherits the base agent config, so voice and web behaviour is unaffected.

There are two independent maps, keyed by channel (`telephone`, `webrtc`, `sms`, `email`, `text`):

| Map                  | Group                    | What it controls                                                                                      |
| -------------------- | ------------------------ | ----------------------------------------------------------------------------------------------------- |
| `channel_overrides`  | LLM steering             | How the agent *thinks and responds* — instructions, greeting, tool budget.                            |
| `channel_properties` | Transport / presentation | How the reply is *rendered and sent* — body template, subject, signature, SMS segments, enabled flag. |

<Note>
  `channel_overrides` and `channel_properties` live on a `static_prompt` agent config. They are consumed by the async messaging engine (SMS, email, text). Voice and WebRTC ignore `channel_properties` transport mechanics and fall back to the base config.
</Note>

## channel\_overrides

Each entry steers inference for one channel. Fields are merged with the base config at resolution time.

| Field               | Type                  | Default  | Description                                                                              |
| ------------------- | --------------------- | -------- | ---------------------------------------------------------------------------------------- |
| `instructions`      | string                | none     | Extra prompt text for this channel.                                                      |
| `instructions_mode` | `append` \| `replace` | `append` | `append` joins this text after the base instructions; `replace` swaps them out entirely. |
| `starting_message`  | starting message      | none     | Per-channel greeting. When set, it replaces the base greeting on this channel.           |
| `max_tool_steps`    | integer (≥ 1)         | none     | Per-channel tool-call budget per turn. When set, it overrides the base `max_tool_steps`. |

When `instructions_mode` is `append`, the resolver concatenates base and override instructions separated by a blank line. If the base instructions are empty, the override is used as-is regardless of mode.

## channel\_properties

Each entry is a channel-exclusive block, discriminated by its `channel` field. Every block shares `enabled` (default `true`) and `body_template` (default `{{agent_response}}`), then adds channel-specific fields.

### EmailProperties (`channel: "email"`)

| Field                        | Type                                 | Default              | Description                                                                                 |
| ---------------------------- | ------------------------------------ | -------------------- | ------------------------------------------------------------------------------------------- |
| `enabled`                    | boolean                              | `true`               | Whether the agent responds on this channel.                                                 |
| `body_template`              | string                               | `{{agent_response}}` | Template for the reply body.                                                                |
| `body_format`                | `multipart` \| `html` \| `plaintext` | `multipart`          | How the email body is rendered.                                                             |
| `subject_template`           | string                               | `Re: {{subject}}`    | Template for the reply subject line.                                                        |
| `default_subject`            | string                               | none                 | Subject used when no inbound subject is available.                                          |
| `from_display_name`          | string                               | none                 | Display name shown on the `From` header.                                                    |
| `signature`                  | string                               | none                 | Signature appended to the body.                                                             |
| `template_wrapper`           | string                               | none                 | Outer wrapper template applied around the body.                                             |
| `include_unsubscribe_footer` | boolean                              | `true`               | Append an unsubscribe footer.                                                               |
| `quote_history`              | boolean                              | `false`              | Quote the prior message thread under the reply.                                             |
| `cc_reply_policy`            | `conditional` \| `never` \| `always` | `conditional`        | Whether to keep `Cc` recipients on replies. `conditional` keeps them only when appropriate. |
| `require_dmarc_pass`         | boolean                              | `false`              | Require inbound mail to pass DMARC before the agent replies.                                |
| `auto_close_on_conclusion`   | boolean                              | `true`               | Close the conversation when the exchange concludes.                                         |

For the full email-agent reference (domains, routing, and the fields above in context), see [Configuring an email agent](/email/configuring-an-email-agent).

### SmsProperties (`channel: "sms"`)

| Field                   | Type                  | Default              | Description                                                                          |
| ----------------------- | --------------------- | -------------------- | ------------------------------------------------------------------------------------ |
| `enabled`               | boolean               | `true`               | Whether the agent responds on this channel.                                          |
| `body_template`         | string                | `{{agent_response}}` | Template for the message body.                                                       |
| `max_segments`          | integer (≥ 1)         | `3`                  | Maximum SMS segments per message.                                                    |
| `on_overflow`           | `truncate` \| `split` | `truncate`           | When the body exceeds `max_segments`, either cut it off or split it across messages. |
| `strip_markdown`        | boolean               | `true`               | Remove markdown formatting before sending.                                           |
| `allow_unicode`         | boolean               | `true`               | Permit non-GSM Unicode characters.                                                   |
| `append_opt_out_footer` | boolean               | `false`              | Append an opt-out footer to outbound messages.                                       |

### TextProperties (`channel: "text"`)

The first-party API text channel has no transport mechanics, so it carries only the shared fields.

| Field           | Type    | Default              | Description                                 |
| --------------- | ------- | -------------------- | ------------------------------------------- |
| `enabled`       | boolean | `true`               | Whether the agent responds on this channel. |
| `body_template` | string  | `{{agent_response}}` | Template for the response body.             |

## How resolution works

When a message arrives on a channel, `resolve_channel_config` folds the base agent config with that channel's override and property blocks into a single effective config:

```text theme={null}
base config ──┐
              ├── instructions  = base, base+"\n\n"+override (append), or override (replace)
override  ────┤── starting_message = override if set, else base
              ├── max_tool_steps = override if set, else base, else 3 (default)
properties ───┴── enabled / body_template = from channel_properties, else defaults
                  properties = the matching email/sms/text block (or none)
```

The resolved values:

| Resolved field     | Source order                                                  |
| ------------------ | ------------------------------------------------------------- |
| `instructions`     | base, or base + override (append), or override (replace)      |
| `starting_message` | channel override, else base                                   |
| `max_tool_steps`   | channel override, else base, else `3`                         |
| `enabled`          | `channel_properties.enabled`, else `true`                     |
| `body_template`    | `channel_properties.body_template`, else `{{agent_response}}` |
| `properties`       | the matching channel-properties block, else none              |

<Info>
  If a channel has no override and no properties entry, the base config is returned unchanged. This keeps voice and WebRTC untouched when you add async-channel tuning.
</Info>

## Next steps

<CardGroup cols={2}>
  <Card title="Configuring an email agent" icon="envelope" href="/email/configuring-an-email-agent">
    Full reference for email-specific fields, routing, and domains.
  </Card>

  <Card title="Channels" icon="layer-group" href="/getting-started/channels">
    How an agent connects to phone, web, email, text, and SMS.
  </Card>
</CardGroup>
