Skip to main content

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:
# 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:
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:
# 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

# 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

# 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
# Changed prompt output format from JSON to CSV
edgit tag create prompts/extraction v2.0.0
Minor (v1.1.0): New features, backward compatible
# Added extraction of new fields
edgit tag create prompts/extraction v1.1.0
Patch (v1.0.1): Bug fixes
# Fixed typo in prompt instructions
edgit tag create prompts/extraction v1.0.1

Reference Versions in Ensembles

Lock to specific versions:
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
Benefits:
  • Predictable behavior (won’t break on updates)
  • Can A/B test different versions
  • Easy rollback (just change the version)
For TypeScript ensembles, see the Version Primitives documentation for complete API reference including versionedAgent(), versionedEnsemble(), and deploymentRef().

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

# 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

ensemble: web-scraping-pipeline

agents:
  # Use specific agent version
  - name: scraper
    agent: [email protected]  # 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: [email protected]  # 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

# 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
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

// 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()
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!
ensemble: multiverse-test

agents:
  # Combination 1: All stable
  - name: variant-1
    agent: [email protected]
    component: [email protected]
    config: [email protected]

  # Combination 2: New agent, old prompt
  - name: variant-2
    agent: [email protected]
    component: [email protected]
    config: [email protected]

  # Combination 3: Old agent, new prompt
  - name: variant-3
    agent: [email protected]
    component: [email protected]
    config: [email protected]

  # ... 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

# 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: [email protected] + [email protected]

# 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: [email protected] + [email protected]

# Week 3: Both work individually. Test together
# Deploy: [email protected] + [email protected]

# 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)

agents:
  - name: analyzer
    agent: [email protected]        # Locked
    component: [email protected]      # Locked
    config: [email protected]         # Locked
When: Production systems that can’t break Trade-off: Miss out on improvements

Strategy 2: Latest Everything (Maximum Innovation)

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)

agents:
  - name: analyzer
    agent: [email protected]         # Stable agent
    component: [email protected]       # Latest prompt (safe to iterate)
    config: [email protected]          # Stable config
When: Most production systems Trade-off: Balance between stability and improvement

Strategy 4: Canary (Gradual Rollout)

agents:
  # 90% get stable
  - name: analyzer-stable
    agent: [email protected]
    component: [email protected]
    condition: ${Math.random() < 0.9}

  # 10% get new version
  - name: analyzer-canary
    agent: [email protected]
    component: [email protected]
    condition: ${Math.random() >= 0.9}
When: Rolling out risky changes Trade-off: More complex setup

Version Lifecycle

Development Flow

# 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

# 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

# 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

# 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

# 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

# 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

# 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

# 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

# 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

# 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

# Error: Updates were rejected

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

Next Steps