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

# Versioning Components, Agents & Ensembles

> Version every piece independently. No more bumping the entire app to v2.0.0 because you changed one prompt.

## The Problem with Traditional Versioning

Traditional approach:

```
v1.0.0: App + Prompt A (v1) + Config B (v1) + Query C (v1)
v1.0.1: App + Prompt A (v2) + Config B (v1) + Query C (v1)
v2.0.0: App + Prompt A (v2) + Config B (v2) + Query C (v1)
```

**Problem:** Can't mix Prompt A v1 with Config B v2. Everything is locked to the app version.

**Edgit approach:**

```
Prompt A: v1.0.0, v1.1.0, v2.0.0 (independent)
Config B: v1.0.0, v2.0.0, v3.0.0 (independent)
Query C: v1.0.0, v1.5.0 (independent)
Ensemble D: v1.0.0, v1.1.0 (independent)
```

**Power:** Mix any combination. Prompt A v1 + Config B v3 + Query C v1.5 + Ensemble D v1.1. Infinite possibilities.

## Thin Git Wrapper Philosophy

**Edgit creates Git tags. That's it.**

* No custom databases
* No version registries
* No deployment state files
* Just standard Git tags

Your CI/CD (GitHub Actions, etc.) handles the actual deployment. Edgit gives you the primitives to version and reference everything.

## Git Tag Format (4 Levels)

Edgit uses a **4-level tag format**:

```
{prefix}/{type}/{name}/{slot}
```

**Levels:**

1. **prefix**: `components` or `logic` (inferred from file path)
2. **type**: `prompts`, `agents`, `ensembles`, etc.
3. **name**: Component name
4. **slot**: Version (v1.0.0) or environment (staging, production)

**Examples:**

```bash theme={null}
# Components (hot-swappable)
components/prompts/extraction/v1.0.0
components/prompts/extraction/staging
components/configs/api-settings/v2.1.0
components/queries/analytics/production

# Logic (requires Worker rebuild)
logic/agents/scraper/v1.0.0
logic/agents/classifier/v2.0.0
logic/agents/classifier/staging
logic/ensembles/pipeline/v1.5.0
logic/ensembles/pipeline/production
```

**Prefix determines deployment behavior:**

* **components**: Hot-swappable (prompts, configs, queries, schemas). Push to KV, live immediately.
* **logic**: Requires Worker rebuild (agents, ensembles). Bundle into code, redeploy Worker.

No `--type` flags needed. Edgit infers prefix from file location.

## Version Tags vs Environment Tags

### Version Tags (Immutable)

Version tags are immutable snapshots:

```bash theme={null}
edgit tag create prompts/extraction v1.0.0
edgit push --tags

edgit tag create agents/classifier v2.0.0
edgit push --tags
```

**Characteristics:**

* Semantic versioning: v1.0.0, v1.1.0, v2.0.0
* Immutable by convention (no --force needed)
* Create once, reference forever
* Safe for production

### Environment Tags (Mutable)

Environment tags are pointers to versions:

```bash theme={null}
# Point staging to a version
edgit tag set prompts/extraction staging v1.0.0
edgit push --tags --force

# Update production pointer
edgit tag set prompts/extraction production v2.0.0
edgit push --tags --force
```

**Characteristics:**

* Common names: staging, production, dev, canary
* Mutable (--force required to update)
* Point to version tags
* Easy deployment workflow

**Why mutable tags require --force:**

* Git protects against accidental overwrites
* Forces explicit intent when moving environment pointers
* Prevents race conditions in CI/CD

## Component Versioning

### What Gets Versioned

**Components** are versioned artifacts that agents use:

* **Prompts** (`.md`) - AI instructions
* **Configs** (`.json`, `.yaml`) - Settings
* **Queries** (`.sql`) - Database queries
* **Scripts** (`.js`, `.ts`) - Functions
* **Schemas** (`.json`) - Validation rules
* **Templates** (`.html`, `.md`) - Output templates

Each gets its own version history via Git tags.

### Create Component Versions

```bash theme={null}
# Create version tag
edgit tag create prompts/extraction v1.0.0
edgit push --tags

# Iterate
edgit tag create prompts/extraction v1.1.0
edgit push --tags

# Set environment pointer
edgit tag set prompts/extraction staging v1.1.0
edgit push --tags --force
```

**No registration needed.** Just create tags. The 4-level format is self-describing.

### Full Workflow Example

```bash theme={null}
# 1. Create version tags
edgit tag create prompts/extraction v1.0.0
edgit tag create prompts/validation v2.1.0
edgit push --tags

# 2. Deploy to staging
edgit tag set prompts/extraction staging v1.0.0
edgit tag set prompts/validation staging v2.1.0
edgit push --tags --force

# 3. Test in staging
# ... run tests ...

# 4. Promote to production
edgit tag set prompts/extraction production v1.0.0
edgit tag set prompts/validation production v2.1.0
edgit push --tags --force
```

**GitHub Actions sees tags and deploys them.** Edgit just creates the tags.

### Semantic Versioning

Follow semver: `v{major}.{minor}.{patch}`

**Major (v2.0.0):** Breaking changes

```bash theme={null}
# Changed prompt output format from JSON to CSV
edgit tag create prompts/extraction v2.0.0
```

**Minor (v1.1.0):** New features, backward compatible

```bash theme={null}
# Added extraction of new fields
edgit tag create prompts/extraction v1.1.0
```

**Patch (v1.0.1):** Bug fixes

```bash theme={null}
# Fixed typo in prompt instructions
edgit tag create prompts/extraction v1.0.1
```

### Reference Versions in Ensembles

Lock to specific versions:

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    import { versionedAgent, createEnsemble, step } from '@ensemble-edge/conductor'

    // Use versionedAgent for version-pinned agent references
    const analyzer = versionedAgent('analyzer', '1.0.0', {
      config: { model: 'claude-sonnet-4' }
    })
    const scorer = versionedAgent('scorer', '2.1.0')

    // Convert to flow steps in your ensemble
    const companyIntel = createEnsemble('company-intel')
      .addStep(step('analyze').agent(analyzer.path).config(analyzer.agentConfig || {}))
      .addStep(step('score').agent(scorer.path))
      .build()

    export default companyIntel
    ```
  </Tab>

  <Tab title="YAML">
    ```yaml theme={null}
    ensemble: company-intel

    agents:
      - name: analyzer
        operation: think
        component: extraction-prompt@v1.0.0  # Locked to v1.0.0
        config:
          model: claude-sonnet-4

      - name: scorer
        operation: think
        component: validation-prompt@v2.1.0  # Different version
    ```
  </Tab>
</Tabs>

**Benefits:**

* Predictable behavior (won't break on updates)
* Can A/B test different versions
* Easy rollback (just change the version)

<Note>
  For TypeScript ensembles, see the [Version Primitives documentation](/conductor/reference/ts-schema#version-primitives-edgit-integration) for complete API reference including `versionedAgent()`, `versionedEnsemble()`, and `deploymentRef()`.
</Note>

## Agent Versioning

### What Are Agents?

**Agents** are workers that execute tasks. They live in `logic/` because they require Worker rebuilds:

* **Pre-built agents** (scraper, validator, RAG, HITL)
* **Custom agent implementations**

### Version Agent Implementations

```bash theme={null}
# Create version tags
edgit tag create agents/scraper v1.0.0
edgit tag create agents/scraper v1.5.0
edgit push --tags

# Set environment
edgit tag set agents/scraper staging v1.5.0
edgit push --tags --force
```

**Tag format:**

```
logic/agents/scraper/v1.0.0
logic/agents/scraper/v1.5.0
logic/agents/scraper/staging
logic/agents/scraper/production
```

### Reference Agent Versions

```yaml theme={null}
ensemble: web-scraping-pipeline

agents:
  # Use specific agent version
  - name: scraper
    agent: scraper@v1.5.0  # Locked to v1.5.0
    config:
      url: https://example.com
      extract:
        title: "h1"
        description: "meta[name=description]"

  # Use different version for comparison
  - name: scraper-new
    agent: scraper@v2.0.0  # Testing v2.0.0
    config:
      url: https://example.com
      extract:
        title: "h1"
        description: "meta[name=description]"
```

## Ensemble Versioning

### What Are Ensembles?

**Ensembles** are workflow definitions that orchestrate agents. They live in `logic/`:

* **YAML ensembles** (`.yaml`, `.yml`) - Declarative workflow definitions
* **TypeScript ensembles** (`.ts`) - Programmatic workflow definitions with full type safety

### Version Ensemble Definitions

<Tabs>
  <Tab title="TypeScript">
    ```bash theme={null}
    # Create version tags
    edgit tag create ensembles/data-pipeline v1.0.0
    edgit tag create ensembles/data-pipeline v1.1.0
    edgit push --tags

    # Set environment
    edgit tag set ensembles/data-pipeline staging v1.1.0
    edgit push --tags --force
    ```
  </Tab>

  <Tab title="YAML">
    ```bash theme={null}
    # Create version tags
    edgit tag create ensembles/scraping-workflow v1.0.0
    edgit tag create ensembles/scraping-workflow v1.5.0
    edgit push --tags

    # Set environment
    edgit tag set ensembles/scraping-workflow production v1.5.0
    edgit push --tags --force
    ```
  </Tab>
</Tabs>

**Tag format:**

```
logic/ensembles/data-pipeline/v1.0.0
logic/ensembles/data-pipeline/v1.1.0
logic/ensembles/data-pipeline/staging
logic/ensembles/data-pipeline/production
```

### TypeScript vs YAML Ensembles

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    // ensembles/data-pipeline.ts
    import { createEnsemble, step, parallel, branch } from '@ensemble-edge/conductor'

    export default createEnsemble('data-pipeline')
      .addStep(
        step('extract')
          .operation('http')
          .config({ url: '${input.url}' })
      )
      .addStep(
        branch('route')
          .when('${extract.output.type === "json"}')
            .then(step('parse-json').operation('code').config({ script: 'scripts/parse-json' }))
          .when('${extract.output.type === "xml"}')
            .then(step('parse-xml').operation('code').config({ script: 'scripts/parse-xml' }))
          .otherwise(
            step('parse-text').operation('code').config({ script: 'scripts/parse-text' })
          )
      )
      .build()
    ```
  </Tab>

  <Tab title="YAML">
    ```yaml theme={null}
    ensemble: data-pipeline

    agents:
      - name: extract
        operation: http
        config:
          url: ${input.url}

      - name: parse-json
        condition: ${extract.output.type === 'json'}
        operation: code
        config:
          script: scripts/parse-json

      - name: parse-xml
        condition: ${extract.output.type === 'xml'}
        operation: code
        config:
          script: scripts/parse-xml

      - name: parse-text
        condition: ${!extract.output.type}
        operation: code
        config:
          script: scripts/parse-text
    ```
  </Tab>
</Tabs>

**When to use TypeScript:**

* Complex flow control (nested branches, loops)
* Type safety requirements
* IDE autocomplete and validation
* Reusable ensemble patterns

**When to use YAML:**

* Simple linear workflows
* Non-developers editing ensembles
* Quick prototyping
* Configuration-driven deployments

## The Versioning Multiverse

The real power: **version components, agents, AND ensembles independently, then mix them.**

### Example: Testing Matrix

You have:

* 2 agent versions (analyzer v1.0.0, v2.0.0)
* 3 prompt versions (prompt v1.0.0, v1.5.0, v2.0.0)
* 2 config versions (config v1.0.0, v2.0.0)

**That's 12 possible combinations!**

```yaml theme={null}
ensemble: multiverse-test

agents:
  # Combination 1: All stable
  - name: variant-1
    agent: analyzer@v1.0.0
    component: prompt@v1.0.0
    config: config@v1.0.0

  # Combination 2: New agent, old prompt
  - name: variant-2
    agent: analyzer@v2.0.0
    component: prompt@v1.0.0
    config: config@v1.0.0

  # Combination 3: Old agent, new prompt
  - name: variant-3
    agent: analyzer@v1.0.0
    component: prompt@v2.0.0
    config: config@v1.0.0

  # ... 9 more combinations to test

output:
  results:
    - variant: variant-1
      output: ${variant-1.output}
      quality: ${variant-1.score}
    - variant: variant-2
      output: ${variant-2.output}
      quality: ${variant-2.score}
    # Compare all variants
```

### Real-World Use Case: Progressive Testing

```bash theme={null}
# Week 1: Test new prompt with stable agent
edgit tag create prompts/analysis v2.0.0
edgit tag set prompts/analysis staging v2.0.0
edgit push --tags --force
# Deploy: analyzer@v1.0.0 + analysis-prompt@v2.0.0

# Week 2: New prompt works! Now test new agent with old prompt
edgit tag create agents/analyzer v2.0.0
edgit tag set agents/analyzer staging v2.0.0
edgit push --tags --force
# Deploy: analyzer@v2.0.0 + analysis-prompt@v1.0.0

# Week 3: Both work individually. Test together
# Deploy: analyzer@v2.0.0 + analysis-prompt@v2.0.0

# Week 4: All good! Promote to production
edgit tag set agents/analyzer production v2.0.0
edgit tag set prompts/analysis production v2.0.0
edgit push --tags --force
```

**You de-risked the rollout by testing each change independently.**

## Version Strategies

### Strategy 1: Lock Everything (Maximum Stability)

```yaml theme={null}
agents:
  - name: analyzer
    agent: analyzer@v1.0.0        # Locked
    component: prompt@v1.0.0      # Locked
    config: config@v1.0.0         # Locked
```

**When:** Production systems that can't break
**Trade-off:** Miss out on improvements

### Strategy 2: Latest Everything (Maximum Innovation)

```yaml theme={null}
agents:
  - name: analyzer
    agent: analyzer@latest         # Always use latest
    component: prompt@latest       # Always use latest
    config: config@latest          # Always use latest
```

**When:** Development/staging environments
**Trade-off:** Might break unexpectedly

### Strategy 3: Mixed (Balanced)

```yaml theme={null}
agents:
  - name: analyzer
    agent: analyzer@v1.0.0         # Stable agent
    component: prompt@v2.1.0       # Latest prompt (safe to iterate)
    config: config@v1.0.0          # Stable config
```

**When:** Most production systems
**Trade-off:** Balance between stability and improvement

### Strategy 4: Canary (Gradual Rollout)

```yaml theme={null}
agents:
  # 90% get stable
  - name: analyzer-stable
    agent: analyzer@v1.0.0
    component: prompt@v1.0.0
    condition: ${Math.random() < 0.9}

  # 10% get new version
  - name: analyzer-canary
    agent: analyzer@v2.0.0
    component: prompt@v2.0.0
    condition: ${Math.random() >= 0.9}
```

**When:** Rolling out risky changes
**Trade-off:** More complex setup

## Version Lifecycle

### Development Flow

```bash theme={null}
# 1. Create feature branch
git checkout -b feature/better-extraction

# 2. Modify component
vim components/prompts/extraction.md

# 3. Test locally (no version yet)
ensemble conductor dev

# 4. Merge to main
git checkout main
git merge feature/better-extraction

# 5. Version after merge (via CI or manually)
edgit tag create prompts/extraction v1.1.0
edgit push --tags

# 6. Deploy to staging
edgit tag set prompts/extraction staging v1.1.0
edgit push --tags --force

# 7. Test in staging
curl https://staging.example.com/test

# 8. Promote to production
edgit tag set prompts/extraction production v1.1.0
edgit push --tags --force
```

### When to Create Versions

**Do version:**

* After merging to main
* After successful tests in staging
* When deploying to any environment
* When you want to lock a working state

**Don't version:**

* Every commit during development
* WIP (work in progress) changes
* Before testing
* In feature branches

**Philosophy:** Versions are milestones, not checkpoints.

## Version Discovery

### List All Versions

```bash theme={null}
# List all tags for a component
git tag | grep "components/prompts/extraction"
# Output:
# components/prompts/extraction/v1.0.0
# components/prompts/extraction/v1.0.1
# components/prompts/extraction/v1.1.0
# components/prompts/extraction/staging
# components/prompts/extraction/production

# List all logic tags
git tag | grep "logic/agents"
```

### View Version Changes

```bash theme={null}
# See what changed in a version
git show components/prompts/extraction/v1.1.0

# Compare two versions
git diff components/prompts/extraction/v1.0.0 components/prompts/extraction/v1.1.0

# View commit message
git show components/prompts/extraction/v1.1.0 --format=%B --no-patch
```

## Best Practices

### 1. Version After Testing

```bash theme={null}
# Don't
edgit tag create prompts/my-prompt v1.0.0  # Before testing

# Do
ensemble conductor dev  # Test locally first
edgit tag create prompts/my-prompt v1.0.0  # Version after confirming it works
```

### 2. Use Semantic Versioning Correctly

```bash theme={null}
# Don't
edgit tag create prompts/my-prompt v1.0.1  # Major change labeled as patch

# Do
edgit tag create prompts/my-prompt v2.0.0  # Breaking change = major bump
```

### 3. Document Breaking Changes

```bash theme={null}
# Don't
edgit tag create prompts/my-prompt v2.0.0 -m "Update prompt"

# Do
edgit tag create prompts/my-prompt v2.0.0 -m "BREAKING: Changed output format from JSON to CSV"
```

### 4. Keep Old Versions

```bash theme={null}
# Don't
git tag -d components/prompts/my-prompt/v1.0.0  # Delete old versions

# Do
# Keep all versions - you might need to rollback
```

### 5. Test Version Combinations

```bash theme={null}
# Don't
# Only test new agent with new prompt

# Do
# Test all combinations:
# - New agent + Old prompt
# - Old agent + New prompt
# - New agent + New prompt
```

## Troubleshooting

### Version Not Found

```bash theme={null}
# Error: components/prompts/my-prompt/v1.0.0 not found

# Check if tag exists
git tag | grep "components/prompts/my-prompt"

# Check prefix (components vs logic)
git tag | grep "my-prompt"
```

### Version Conflicts

```bash theme={null}
# Error: Tag already exists

# Check existing tag
git show components/prompts/my-prompt/v1.0.0

# Use force to overwrite (careful!)
edgit tag create prompts/my-prompt v1.0.0 --force
edgit push --tags --force
```

### Can't Push Environment Tags

```bash theme={null}
# Error: Updates were rejected

# Environment tags are mutable, need --force
edgit push --tags --force
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Deployment Strategies" icon="rocket" href="/edgit/guides/deployment-strategies">
    Progressive rollouts, canaries, A/B testing
  </Card>

  <Card title="Rollback & Time Travel" icon="clock-rotate-left" href="/edgit/guides/rollback-time-travel">
    Emergency rollbacks and debugging
  </Card>

  <Card title="A/B Testing" icon="flask" href="/edgit/guides/ab-testing-multivariate">
    Multivariate testing with version combinations
  </Card>

  <Card title="CLI Reference" icon="terminal" href="/edgit/reference/cli-commands">
    Complete command documentation
  </Card>
</CardGroup>
