# Channel Tagging System

Configure services for deployment channels (voice, text, async) with validation and optimized LLM presets.

## Overview

Different deployment channels have distinct requirements:

* **Voice** channels need ultra-low latency and restricted state types
* **Text** channels support full features with moderate latency
* **Async** channels (email, API) have relaxed latency requirements

The channel tagging system helps you configure services appropriately and validates configurations before sync.

## Channels

| Channel        | Type  | Typical Use Case                        |
| -------------- | ----- | --------------------------------------- |
| `phone`        | voice | Telephony (PSTN / VoIP - Voice over IP) |
| `web_voice`    | voice | Browser WebRTC                          |
| `mobile_voice` | voice | Mobile app voice                        |
| `sms`          | text  | SMS messaging                           |
| `whatsapp`     | text  | WhatsApp                                |
| `web_chat`     | text  | Web chat widget                         |
| `mobile_chat`  | text  | Mobile app chat                         |
| `email`        | async | Email                                   |
| `api`          | async | Direct API integration                  |

## Channel Profiles

Each channel type has a profile defining its constraints:

### Voice Channels

* **Max states**: 5
* **Allowed state types**: action, annotation, tool-call
* **Memory retrieval**: Disabled
* **Dynamic behaviors**: Not supported
* **Recommendation**: Configure `keyterms` for transcription accuracy

### Text Channels

* **Max states**: Unlimited
* **Allowed state types**: All
* **Memory retrieval**: Supported
* **Dynamic behaviors**: Supported

### Async Channels

* **Max states**: Unlimited
* **Allowed state types**: All
* **Memory retrieval**: Supported
* **Dynamic behaviors**: Supported
* **Maximum capabilities** with relaxed latency requirements

## Version Set Presets

Presets configure LLM models optimized for each channel type:

| Tier              | Voice                     | Text           | Async           |
| ----------------- | ------------------------- | -------------- | --------------- |
| Standard          | `voice`                   | `text`         | `async`         |
| Premium           | `voice_premium`           | `text_premium` | `async_premium` |
| Economy           | `voice_economy`           | `text_economy` | `async_economy` |
| Ultra-Low         | `voice_ultra_low`         | -              | -               |
| Ultra-Low Premium | `voice_ultra_low_premium` | -              | -               |

### Regional Availability

Some presets use LLMs that are not available in all regions. See [LLM Regional Availability](https://docs.amigo.ai/developer-guide/getting-started/regions-and-endpoints#llm-regional-availability) for the full availability matrix.

{% hint style="warning" %}
**Premium Model Regional Restriction**

The following presets use premium-tier models that are only available in **US** and **EU** regions:

* `text_premium`
* `async`
* `async_premium`

These presets **cannot be deployed** to CA or AU regions. Use economy or standard presets for those regions instead.
{% endhint %}

### Ultra-Low Latency Presets

The `voice_ultra_low` and `voice_ultra_low_premium` presets require **single-state context graphs**:

{% hint style="warning" %}
**Single-State Requirements**

To use ultra-low latency presets:

* All action states must have exactly 1 action
* All action states must have 0 exit conditions
* Set `skip_active_memory_retrieval: true`

This triggers the backend fast path that **skips the `select_next_action` LLM call**, saving 100-500ms latency per turn.
{% endhint %}

## Tag Format

Services support two tag formats in local JSON/YAML files:

### Simple String Format (Recommended)

```json
{
  "tags": ["phone", "voice_premium"]
}
```

Or in YAML:

```yaml
tags:
  - phone
  - voice_premium
```

### Object Format (Legacy)

```json
{
  "tags": [
    {"key": "phone", "value": null},
    {"key": "voice_premium", "value": null}
  ]
}
```

{% hint style="success" %}
**Use the simple string format** for easier editing. Both formats are automatically converted to the API format during sync.
{% endhint %}

Tags encode:

1. **Channel** (e.g., `phone`, `web_chat`) - which deployment channel
2. **Preset** (e.g., `voice_premium`, `text`) - which LLM configuration

## Service Environment Tags

Services can be tagged with `dev` or `production` to enforce different validation rules for version set pinning.

### Environment Tag Options

| Tag          | Description                  | Validation Rules                                                                              |
| ------------ | ---------------------------- | --------------------------------------------------------------------------------------------- |
| `dev`        | Development/sandbox services | No version pinning required. Can push directly to `release`.                                  |
| `production` | Production services          | Must have `preview` defined. `release` must match `preview`. All version sets must be pinned. |

### Adding Environment Tags

Add an environment tag alongside your channel tags:

```yaml
tags:
  - phone
  - voice_premium
  - production  # or 'dev'
```

{% hint style="info" %}
**No environment tag?** Services without an environment tag skip environment-specific validation entirely.
{% endhint %}

### Production Service Requirements

When a service is tagged `production`, the following rules are enforced during `forge sync-to-remote`:

1. **Preview version set required**: A `preview` version set must be defined
2. **Release matches preview**: The `release` configuration must exactly match `preview` (agent version, context graph version, LLM preferences)
3. **Versions pinned**: All version sets (except `edge`) must have explicit pinned version numbers - no `latest`

**Example validation error:**

```
Service: My Production Service
  ! Production service missing required 'preview' version set.
  ! Release version set does not match preview configuration.
  ! Version set 'release' must have pinned agent version for production services.
```

### Dev Service Flexibility

Services tagged `dev` have no version set restrictions:

* Can use unpinned versions (`latest`) in any version set
* No `preview` requirement
* Can push directly to `release` without promotion workflow

{% hint style="warning" %}
**Use `dev` only for sandbox/development environments.** Production services should always use the `production` tag to enforce proper promotion workflows.
{% endhint %}

## LLM Validation

Service tags control LLM validation at the version set layer. LLM preferences then match channel and cost requirements.

### Voice-Optimized LLMs

Voice channels require low Time-To-First-Token (TTFT) for real-time conversation. Only a subset of available LLMs meet the latency requirements for voice. Use `forge channel llm-info --channel phone` to see the current list of voice-optimized models.

{% hint style="danger" %}
**Non-voice-optimized LLMs will cause validation errors** for services with voice channel or voice preset tags. Premium-tier and high-capability models generally have higher latency and are not suitable for voice.
{% endhint %}

### Cost Tier Classifications

LLMs are classified into cost tiers for validation against preset expectations:

| Tier     | Description                                      | Price Range (per 1M input) |
| -------- | ------------------------------------------------ | -------------------------- |
| Economy  | Lightweight, low-cost models optimized for speed | $0.05-$0.40                |
| Standard | Balanced cost and capability                     | $0.25-$2                   |
| Premium  | Highest capability models                        | $1.25-$15                  |

Use `forge channel llm-info` to see the current model-to-tier mapping.

### Validation Rules

| Tag                                                  | Validation                                 | Severity |
| ---------------------------------------------------- | ------------------------------------------ | -------- |
| Voice channel (`phone`, `web_voice`, `mobile_voice`) | Non-voice-optimized LLMs                   | ERROR    |
| Voice preset (`voice`, `voice_premium`, etc.)        | Non-voice-optimized LLMs                   | ERROR    |
| Economy preset (`*_economy`)                         | Premium-tier LLMs                          | ERROR    |
| Premium preset (`*_premium`)                         | Only economy-tier LLMs                     | ERROR    |
| Production environment                               | `release` LLM prefs != `preview`           | ERROR    |
| Empty `llm_model_preferences` (voice)                | System defaults may not be voice-optimized | WARNING  |
| No channel/preset tags                               | LLM preferences cannot be validated        | WARNING  |

### Example Validation Output

```
!! CHANNEL VALIDATION ERRORS !!

  Entity: Cardi (68bb4c7fb3c5a689980b217f)
    ✗ ERROR: Version set 'release' uses non-voice-optimized LLM
      for 'backend.chat_agent_engage_user'.
      Voice preset 'voice' requires voice-optimized LLMs for low latency.

~~ CHANNEL VALIDATION WARNINGS ~~

  Entity: SDK Test Service (689b81e7afdaf934f4b48f81)
    ⚠ WARNING: Version set 'edge' has empty llm_model_preferences.
      System defaults may include non-voice-optimized LLMs.
```

### System Defaults vs Preset Defaults

{% hint style="warning" %}
**Important:** Empty `llm_model_preferences` does NOT use preset defaults. It uses **system defaults** which may not match your channel/preset requirements.

For voice services, always explicitly configure LLM preferences to ensure voice-optimized models are used.
{% endhint %}

## Validation

Services with channel tags are validated against channel constraints:

* **Preset compatibility**: Voice presets only work with voice channels
* **Regional LLM availability**: Presets are validated against the target region's LLM availability
* **LLM preferences**: Voice channels require voice-optimized LLMs; cost tiers must match preset expectations
* **Channel constraints**: Context graphs are checked against channel profile limits
* **Keyterms warning**: Voice services without `keyterms` trigger a warning
* **Untagged LLM preferences**: Services with LLM preferences but no tags trigger a warning
* **Errors block sync**, warnings prompt for confirmation

### Standalone Validation

Use `forge validate` to check services locally before syncing:

```bash
# Validate all services
forge validate --entity-type service --env production

# Validate all entity types
forge validate --all --env production

# Also check references against remote
forge validate --entity-type service --env production --check-references

# Validate service dependencies against channel constraints
forge validate --entity-type service --env production --check-dependencies
```

This catches issues early without making any changes to the remote.

### Dependency Validation (`--check-dependencies`)

The `--check-dependencies` flag validates that a service's linked assets are compatible with its channel constraints. This is essential for voice services which have strict latency requirements.

**What gets validated:**

| Check                                | Voice Channels | Severity |
| ------------------------------------ | -------------- | -------- |
| Context graph state count ≤ 5        | ✓              | Warning  |
| No decision/reflection/recall states | ✓              | Error    |
| No active memory retrieval           | ✓              | Warning  |
| No dynamic behaviors applied         | ✓              | Error    |
| Single-state for ultra-low presets   | ✓              | Error    |

**Example output:**

```
── Validating service dependencies ──
  Loaded 12 context graphs
  Loaded 148 dynamic behaviors

  Service: Cardi
    Context graph: Cardi POC Check In
    ! Context graph 'Cardi POC Check In' contains state types not allowed
      for phone channel: decision (1), reflection (1).
    ~ Context graph 'Cardi POC Check In' has 10 states, exceeds recommended
      max of 5 for phone channel.

  Service: Reactive Support
    Dynamic behaviors applied: 145
    ! Voice channel 'phone' does not support dynamic behaviors.

============================================================
Validation complete: 3 error(s), 28 warning(s)
```

{% hint style="warning" %}
**Voice Services with Dynamic Behaviors**

Voice channels do not support dynamic behaviors due to latency requirements. If you have dynamic behaviors applied to a voice service, you must either:

1. Remove the dynamic behaviors from the service
2. Change the service to a text or async channel
   {% endhint %}

### Validation Flow

{% @mermaid/diagram content="%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#D4E2E7", "primaryTextColor": "#100F0F", "primaryBorderColor": "#083241", "lineColor": "#575452", "textColor": "#100F0F", "clusterBkg": "#F1EAE7", "clusterBorder": "#D7D2D0"}}}%%
flowchart TB
Sync\[forge sync-to-remote] --> Check{Has channel tags?}
Check -->|No| LLMWarn{Has LLM prefs?}
LLMWarn -->|Yes| WarnNoTag\[Warning: LLM prefs without tags]
LLMWarn -->|No| Proceed\[Sync proceeds]
WarnNoTag --> Proceed
Check -->|Yes| Validate\[Validate service]

```
Validate --> Preset{Preset matches channel?}
Preset -->|No| Error[Error: blocks sync]
Preset -->|Yes| Region{LLMs available in region?}

Region -->|No| Error
Region -->|Yes| LLMValid{LLM prefs valid?}

LLMValid -->|No| Error
LLMValid -->|Yes| Graph{Context graph valid?}

Graph -->|No| Error
Graph -->|Yes| Keyterms{Voice + no keyterms?}

Keyterms -->|Yes| Warn[Warning: prompts confirmation]
Keyterms -->|No| Proceed

Warn --> Confirm{User confirms?}
Confirm -->|Yes| Proceed
Confirm -->|No| Abort[Sync aborted]" %}
```

## CLI Commands

Use `forge channel` commands to explore and validate configurations:

### List Channels

```bash
forge channel list-channels
```

Shows all supported channels with their profiles.

### List Presets

```bash
# All presets
forge channel list-presets

# Filter by type
forge channel list-presets --type voice

# Show LLM configurations
forge channel list-presets --verbose
```

### Show Channel Profile

```bash
forge channel show-profile phone
```

Displays constraints and recommendations for a specific channel.

### Show Tags

```bash
# Default preset
forge channel show-tags phone

# Specific preset
forge channel show-tags phone --preset voice_premium
```

Outputs the JSON tags to add to your service.

### Validate Preset

```bash
# Validate preset for channel
forge channel validate-preset voice_premium phone

# Validate preset for channel AND region
forge channel validate-preset text_premium web_chat --region ca
```

Checks if a preset is compatible with a channel and optionally validates regional LLM availability.

### Validate Context Graph

```bash
# Basic validation
forge channel validate-context-graph phone \
  --state-type action \
  --state-type annotation \
  --state-count 3

# Validate for ultra-low latency
forge channel validate-context-graph phone \
  --state-type action \
  --state-count 1 \
  --single-state-eligible \
  --preset voice_ultra_low
```

Validates context graph characteristics against channel constraints.

### LLM Info

```bash
# All models
forge channel llm-info

# Voice-optimized models
forge channel llm-info --channel phone
```

Shows the LLM catalog with voice-optimized recommendations.

## Best Practices

{% hint style="success" %}
**Voice Channel Optimization**

1. **Use keyterms**: Configure domain-specific vocabulary for better transcription
2. **Minimize states**: Keep context graphs under 5 states for voice
3. **Consider ultra-low presets**: If your workflow is single-state, use `voice_ultra_low` to save 100-500ms
4. **Avoid memory retrieval**: Set `skip_active_memory_retrieval: true` for voice
   {% endhint %}

{% hint style="info" %}
**Preset Selection Guide**
{% endhint %}

| Scenario                            | Recommended Preset |
| ----------------------------------- | ------------------ |
| Production voice with quality focus | `voice_premium`    |
| High-volume voice, cost-sensitive   | `voice_economy`    |
| Single-state voice flows            | `voice_ultra_low`  |
| Standard text chat                  | `text`             |
| Complex reasoning (email, API)      | `async_premium`    |

## Example: Configuring a Voice Service

1. **Check channel constraints**:

   ```bash
   forge channel show-profile phone
   ```
2. **Get tags for your preset**:

   ```bash
   forge channel show-tags phone --preset voice_premium
   ```
3. **Add tags to your service** in `local/<env>/entity_data/service/<service>.yaml`:

   ```yaml
   tags:
     - phone
     - voice_premium
   ```
4. **Validate locally** (catches issues without touching remote):

   ```bash
   forge validate --entity-type service --env production
   ```
5. **Validate dependencies** (ensures context graph is compatible):

   ```bash
   forge validate --entity-type service --env production --check-dependencies
   ```
6. **Preview sync changes**:

   ```bash
   forge sync-to-remote --entity-type service --env production
   ```
7. **Apply changes**:

   ```bash
   forge sync-to-remote --entity-type service --env production --apply
   ```

## Related Documentation

{% content-ref url="version-sets-best-practices" %}
[version-sets-best-practices](https://docs.amigo.ai/developer-guide/operations/devops/version-sets-best-practices)
{% endcontent-ref %}
