# Version Sets & Promotion

Version sets define which agent, state machine, and model preferences a service uses. They enable safe iteration like Git branches while keeping production stable.

* Purpose: Pin exact versions for a service run (agent, state machine, LLM model preferences).
* Analogy: Treat version sets like Git branches for your service configuration.
* Two special sets exist on every service:
  * `edge`: Always points to the latest agent and state machine with no model preferences. Locked from updates; cannot be deleted.
  * `release`: The default version set used when clients don’t specify one. Cannot be deleted; can be updated to promote changes.

{% hint style="warning" %}
Guardrails

* `edge` cannot be updated or deleted.
* `release` cannot be deleted and is the default when no version set is specified.
* Custom version sets cannot be deleted if referenced by simulation unit tests.
  {% endhint %}

## What Each Special Set Means

* `edge` (locked default settings)
  * Always latest agent/state machine; no explicit LLM preferences.
  * Cannot be updated via the upsert API and cannot be deleted.
  * Use for quick local validation or smoke checks; not for stable user exposure.
* `release` (default exposed to users)
  * Used by conversations and real-time APIs when `service_version_set_name` is not provided.
  * Cannot be deleted, but can be updated to promote a tested configuration to production.

## Creating and Updating Version Sets

* Create/Update: Use the Service Version Set upsert API to create named sets (e.g., `personal-alex`, `test`, `preview`). All sets except `edge` are updatable.
* Delete: Allowed for custom sets, but not for `edge` or `release`. Deletion is blocked if a set is referenced by any simulation unit tests.
* Permissions:
  * Create: `Service:CreateVersionSet`
  * Update: `Service:UpdateVersionSet`
  * Delete: `Service:DeleteVersionSet`

## How Version Sets Are Used at Runtime

* Conversation APIs default to `release` if `service_version_set_name` is omitted.
* Simulation unit tests and test runs must explicitly specify the target version set.
* Services are created with both `edge` and `release` by default; `release` will equal `edge` unless specified otherwise at creation time.

## Recommended Workflow (Git-Branch Style)

1. Personal branch

* Create a personal version set (e.g., `personal-yourname`), pin agent/state machine versions and set LLM preferences.
* Iterate locally; validate via small focused simulation unit tests.

2. Merge into `test`

* Upsert the shared `test` version set with your candidate configuration.
* Run your simulation unit test set on `test`. Fix regressions here.

3. Promote to `preview`

* Copy the `test` configuration into `preview` (another named version set).
* Run the full simulation suite on `preview` and conduct stakeholder UAT.

4. Release

* If `preview` passes full sims and UAT, promote by updating `release` with the same configuration (i.e., upsert `release` to match `preview`).
* Do not delete `release` or `edge`. Use them as stable anchors.

### Promotion Flow

{% @mermaid/diagram content="---
config:
gitGraph:
mainBranchName: 'release'
showCommitLabel: true
rotateCommitLabel: true
-----------------------

gitGraph
commit id: "Initial" tag: "v1.0.0"

```
%% First development cycle
branch personal-dev
commit id: "Agent v2"
commit id: "LLM: standard"
commit id: "State: v3"

checkout release
branch test
checkout personal-dev
commit id: "Agent v2"
checkout test
commit id: "Test passed ✓"

checkout release
branch preview
checkout test
commit id: "Test passed ✓"
checkout preview
commit id: "UAT ✓" type: HIGHLIGHT

checkout release
merge preview id: "Promote" tag: "v1.1.0" type: HIGHLIGHT

%% Second development cycle
checkout release
commit id: "Stable"
branch personal-dev-2
commit id: "Agent v3"

checkout release
branch edge
commit id: "Auto-latest" type: REVERSE tag: "🔒 Locked"" %}
```

## CLI Commands (`forge version-set`)

Agent Forge provides CLI commands to manage version sets directly from the terminal:

### List Version Sets

```bash
forge version-set list MyService -e production

# JSON output for scripting
forge version-set list MyService -e production --json
```

Shows all version sets for a service with their pinned versions and LLM preferences.

### Create/Update a Version Set

```bash
# Create with unpinned versions (dev only)
forge version-set upsert personal-alex -s MyService -e dogfood --apply

# Create with pinned versions (resolves current latest)
forge version-set upsert personal-alex -s MyService -e dogfood --latest --apply

# Create by copying from another version set
forge version-set upsert preview -s MyService -e production --copy-from test --apply

# Pin specific versions
forge version-set upsert preview -s MyService -e production -a 5 -g 3 --apply
```

{% hint style="info" %}
**Dry-run by default**: All mutating commands show what would change without `--apply`. Add `--apply` to execute.
{% endhint %}

#### Version Existence Validation

When pinning to specific versions using `-a` (agent) or `-g` (context graph) flags, the CLI validates that those versions actually exist before applying the change:

```bash
$ forge version-set upsert preview -s MyService -e production -a 999 -g 888 --apply

Error: Agent version 999 does not exist. Use 'forge asset agent version-list' to see available versions.
Error: Context graph version 888 does not exist. Use 'forge asset context-graph version-list' to see available versions.
```

For advanced users who need to bypass this validation (e.g., in automation scripts where versions may be created in parallel), use the `--skip-version-check` flag:

```bash
forge version-set upsert preview -s MyService -e production -a 5 -g 3 --skip-version-check --apply
```

{% hint style="warning" %}
Use `--skip-version-check` with caution. Pinning non-existent versions will cause runtime failures when the service is invoked.
{% endhint %}

### Compare Version Sets

```bash
forge version-set diff preview release -s MyService -e production

# JSON output for scripting
forge version-set diff preview release -s MyService -e production --json
```

Shows a side-by-side comparison of two version sets, highlighting differences.

### Promote Version Sets

```bash
# Promote to release (auto-backup creates release-previous for easy rollback)
forge version-set promote preview release -s MyService -e production --apply

# Skip auto-backup if needed
forge version-set promote preview release -s MyService -e production --no-backup --apply
```

{% hint style="info" %}
**Auto-backup**: When promoting to `release`, a backup is automatically created as `release-previous`. Use `--no-backup` to skip this safety measure.
{% endhint %}

### Rollback Version Sets

If a release causes issues, quickly revert to the previous configuration:

```bash
# Preview what would be rolled back (dry-run)
forge version-set rollback -s MyService -e production

# Execute the rollback
forge version-set rollback -s MyService -e production --apply
```

This is equivalent to `forge version-set promote release-previous release` but provides a clearer intent and shows a comparison of the configurations:

```
Rollback 'release' to 'release-previous'
  Service: MyService (686d598b1234567890abcdef)
                         Configuration Comparison
┏━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┓
┃ Field                 ┃ Previous (release-previous) ┃ Current (release) ┃
┡━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━┩
│ agent_version         │ 27                          │ 28                │
│ context_graph_version │ 3                           │ 4                 │
│ llm_preferences       │ 2 configured                │ 2 configured      │
└───────────────────────┴─────────────────────────────┴───────────────────┘

Dry-run mode. Use --apply to execute.
```

{% hint style="warning" %}
The `release-previous` version set is created automatically when promoting to `release`. If you've never promoted to release, or used `--no-backup`, the rollback command will fail with an error.
{% endhint %}

### Show Version Set Details

```bash
# Human-readable format
forge version-set show preview -s MyService -e production

# JSON output (for scripting)
forge version-set show preview -s MyService -e production --json
```

### Delete a Version Set

```bash
forge version-set delete test-old -s MyService -e dogfood --apply
```

{% hint style="warning" %}
Cannot delete `edge` or `release`. Cannot delete version sets referenced by simulation unit tests.
{% endhint %}

## Discovering Services (`forge service`)

Before working with version sets, you may need to discover what services exist and their current configuration. Use `forge service` commands to list and inspect services.

### List Services

```bash
# List all services in an environment
forge service list -e production

# Filter by tag (e.g., production, phone, voice)
forge service list -e production --tag phone

# JSON output for scripting
forge service list -e production --json
```

Output shows services with their tags and version set counts:

```
Services in production
Filtered by tag: phone

┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┓
┃ Name                      ┃ ID          ┃ Tags                ┃ Version Sets ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━┩
│ Customer Support          │ 686d598b... │ phone, voice        │            3 │
│ Sales Assistant           │ 68bb4c7f... │ phone, production   │            2 │
└───────────────────────────┴─────────────┴─────────────────────┴──────────────┘
```

### Show Service Details

```bash
# Show full service configuration
forge service show "Customer Support" -e production

# JSON output for scripting
forge service show "Customer Support" -e production --json
```

Output includes linked assets and version set configuration:

```
Service: Customer Support
  ID: 686d598b1234567890abcdef
  Description: Voice support agent
  Active: Yes

Tags:
  - phone
  - voice

Linked Assets:
  Agent: support_agent (66e0d996f5a09fb3cf18ea73)
  Context Graph: support_context_graph (66e0d575f5a09fb3cf18ea5e)

Version Sets:
  Name       Agent Ver    CG Ver    LLM Config
  edge          latest    latest    defaults
  preview           28         4    2 set
  release           28         4    2 set

Related commands:
  forge version-set list Customer Support -e production
  forge asset agent version-list support_agent -e production
```

### Check Service Health Status

Monitor the health of services across your organization to identify configuration issues:

```bash
# Check status of active services only (default behavior)
forge service status -e production

# Include inactive/disabled services in the analysis
forge service status -e production --include-inactive

# Focus on production-tagged services only
forge service status -e production --production

# Show only services with issues
forge service status -e production --issues

# Filter by tag
forge service status -e production --tag phone

# JSON output for monitoring/alerting
forge service status -e production --json
```

**Detected Issues:**

* **Version set drift**: Preview and release configurations differ
* **Missing version sets**: Production services missing preview or release
* **Unpinned versions**: Production services with non-edge version sets using `latest`

**Example Output:**

```
Service Status in production

Summary:
  Total services: 8  # Only showing active services by default
  Production services: 3
  Services with issues: 2
    - With preview/release drift: 2

Services Needing Attention:

Name           ID          Active  Prod   Preview  Release  Issues
MyService      507f1f7...  Yes     Yes    Yes      Yes      preview/release drift
OtherService   508f2a8...  Yes     Yes    No       Yes      missing preview
```

{% hint style="info" %}
**Discovery workflow**: Use `forge service list` to find services, `forge service status` to check health, then `forge service show` to inspect configuration before making changes with `forge version-set` commands.
{% endhint %}

## Discovering Asset Versions (`forge asset`)

Before pinning specific versions in a version set, you need to know what versions exist. Use `forge asset` commands to discover agent and context graph versions.

### List Agent Versions

```bash
# List versions for an agent by name
forge asset agent version-list MyAgent -e production

# List by agent ID
forge asset agent version-list 507f1f77bcf86cd799439011 -e production

# Show newest versions first
forge asset agent version-list MyAgent -e production --newest-first

# Get 50 most recent versions (pagination fetches multiple API pages automatically)
forge asset agent version-list MyAgent -e production --newest-first --limit 50
```

Output shows version numbers with creation timestamps:

```
Versions for Agent: MyAgent (507f1f77bcf86cd799439011)

┏━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┓
┃ Version ┃ Created          ┃ Description ┃
┡━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━┩
│       1 │ 2024-04-11 23:52 │ -           │
│       2 │ 2025-01-30 19:38 │ -           │
│       3 │ 2025-01-30 19:51 │ -           │
└─────────┴──────────────────┴─────────────┘
```

{% hint style="info" %}
**Sorting & Pagination**: The `--newest-first` / `-d` flag sorts versions descending. When `--limit` exceeds the API's 10-per-page maximum, the CLI automatically paginates using `continuation_token` to fetch all requested results. Available on all `version-list` commands (agent, context-graph, behavior).
{% endhint %}

### List Context Graph Versions

```bash
forge asset context-graph version-list MyGraph -e production

# Newest first with limit
forge asset context-graph version-list MyGraph -e production -d --limit 20
```

Output includes state count for each version:

```
Versions for Context Graph: MyGraph (66997b4d40fe08f84ba0d1d1)

┏━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┓
┃ Version ┃ Created          ┃ States ┃ Description          ┃
┡━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━┩
│       1 │ 2024-07-18 20:45 │     21 │ Initial version      │
│       2 │ 2024-08-07 17:06 │     22 │ Added new state      │
│       3 │ 2025-02-10 20:14 │     22 │ Bug fixes            │
└─────────┴──────────────────┴────────┴──────────────────────┘
```

### Show Version Details

```bash
# Agent version details
forge asset agent version-show MyAgent 3 -e production

# Context graph version details (shows state breakdown)
forge asset context-graph version-show MyGraph 2 -e production

# JSON output for scripting
forge asset agent version-show MyAgent 3 -e production --json
```

### Check Behavior Invocations

```bash
# See when/where a behavior was triggered
forge asset behavior invocations "Emergency Response Protocol" -e production

# JSON output for detailed analysis
forge asset behavior invocations "Emergency Response Protocol" -e production --json
```

### Workflow: Pin Discovered Versions

```bash
# 1. Discover latest agent version
forge asset agent version-list MyAgent -e production

# 2. Discover latest context graph version
forge asset context-graph version-list MyGraph -e production

# 3. Pin specific versions in a version set
forge version-set upsert preview -s MyService -e production -a 3 -g 2 --apply
```

{% hint style="info" %}
**Tip**: Use `forge version-set upsert --latest` to automatically resolve and pin the current latest versions without manually looking them up.
{% endhint %}

## CLI Validation

All mutating version-set commands (`upsert`, `promote`, `delete`) run pre-flight validation before applying changes. Configurations are validated before reaching the remote API.

### Validation Rules

| Rule                                   | Scope               | Behavior                                                  |
| -------------------------------------- | ------------------- | --------------------------------------------------------- |
| Version existence check                | All upsert commands | Error if pinned agent/context graph version doesn't exist |
| Pinned versions required               | Production services | Error if agent/context graph version is `null`            |
| Cannot delete preview/release          | Production services | Error blocks deletion                                     |
| Preview required for release promotion | Production services | Error if preview doesn't exist                            |
| Voice-optimized LLMs only              | Voice channels      | Error if using non-voice-optimized models                 |
| Empty LLM prefs warning                | Voice channels      | Warning (non-blocking)                                    |
| Cost tier constraints                  | Economy presets     | Error if using premium LLMs                               |

{% hint style="info" %}
**Bypass validation**: Use `--skip-version-check` to bypass version existence validation for advanced use cases.
{% endhint %}

### Example: Blocked Mutation

```bash
$ forge version-set upsert preview -s "Voice Service" -e production --apply

Error: Version set 'preview' uses a non-voice-optimized LLM.
Voice preset 'voice' requires voice-optimized LLMs for low latency.
Use 'forge channel llm-info --channel phone' to see valid models.

Validation failed. Fix errors before proceeding.
```

### Example: Warning (Non-blocking)

Warnings are displayed but don't block the operation:

```bash
$ forge version-set upsert test -s "Voice Service" -e dogfood --apply

Warning: Version set 'test' has empty llm_model_preferences. System defaults may
include non-voice-optimized LLMs. For voice preset 'voice', configure LLM preferences
explicitly using voice-optimized LLMs.

Create version set 'test'
  Service: Voice Service (66e0da39f5a09fb3cf18ea75)
  Agent version: latest
  Context Graph version: latest

Dry-run mode. Use --apply to execute.
```

{% hint style="info" %}
**Channel and preset tags** determine which validation rules apply. See [Channel Tagging](https://docs.amigo.ai/developer-guide/operations/devops/channel-tagging) for details on configuring service tags.
{% endhint %}

## Practical Tips

### Naming Conventions

* Use lowercase letters, digits, `-` or `_` only.
* Don’t use `/`, `.`, or names starting with `$`.
* Examples: `personal-alex`, `test`, `preview`, `release`.
* Drift control: Treat `release` as immutable except during deliberate promotion. Keep a changelog of which version set was promoted, when, and by whom.
* Safety checks: Block deletion of sets referenced by simulations. Prefer deprecation and migration over deletion when many artifacts depend on a set.
* Fast rollback: Use `forge version-set rollback` to quickly revert to the previous release configuration. The `release-previous` backup is created automatically when promoting to `release`.
* Observability: Compare simulation metrics between `test`, `preview`, and `release` to quantify impact before promotion.

## API Touchpoints (Operational Behavior)

### API References

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/service/" method="post" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/service/{service\_id}/version\_sets/{version\_set\_name}/" method="put" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/service/{service\_id}/version\_sets/{version\_set\_name}/" method="delete" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

\- Service creation initializes \`edge\` and \`release\`. - Upsert version set API cannot update \`edge\` but can update \`release\` and custom sets. - Delete version set API forbids deleting \`edge\` and \`release\`, and blocks deletion if a set is used in simulation unit tests. - Conversation and real-time endpoints default to \`release\` when a version set isn’t specified by the client.
