# Workflow for Versioned Agent Updates and Skill Publishing

> Learn the workflow for versioned agent updates and skill publishing in the anthropics/cwc-workshops repository. Discover idempotent deployment for Claude Managed Agents.

- Repository: [Anthropic/cwc-workshops](https://github.com/anthropics/cwc-workshops)
- Tags: workflow
- Published: 2026-07-18

---

**The `anthropics/cwc-workshops` repository implements an idempotent deployment pipeline that versions skills under `.claude/skills/`, caches resource IDs in [`.stockpilot_ids.json`](https://github.com/anthropics/cwc-workshops/blob/main/.stockpilot_ids.json), and performs atomic versioned updates to Claude Managed Agents without recreating them.**

The repository provides a deterministic workflow for versioned agent updates and skill publishing through the Claude Managed Agents (CMA) helpers located in [`agents/cma.py`](https://github.com/anthropics/cwc-workshops/blob/main/agents/cma.py). This architecture allows developers to package skills as zip archives, publish new versions without changing skill identifiers, and update existing agent configurations while preserving their identity and state.

## Skill Packaging and Versioning

Skills reside in the `.claude/skills/` directory and are packaged into zip archives before upload. The `upload_skills` function in **[`agents/cma.py`](https://github.com/anthropics/cwc-workshops/blob/main/agents/cma.py)** (lines 97-126) handles the complete lifecycle:

- If a skill does not exist, it calls `c.beta.skills.create()` with the zipped archive.
- If the skill already exists, it invokes `c.beta.skills.versions.create()` to produce a new version while retaining the original skill ID.

This approach ensures that existing agent configurations referencing the skill remain valid while allowing iterative improvements to the skill logic.

```python

# From agents/cma.py - simplified upload logic

sid = c.beta.skills.create(
    display_title=title,
    files=[(f"{name}.zip", buf, "application/zip")],
)

# If skill exists, versions.create is called instead

```

## Environment and Agent Lifecycle Management

The workflow separates environment provisioning from agent updates to support repeatable deployments.

### Creating the Managed Environment

The `ensure_env` function in **[`agents/cma.py`](https://github.com/anthropics/cwc-workshops/blob/main/agents/cma.py)** (lines 30-38) verifies whether a "managed-agents" environment exists and creates one if absent. This provides the execution context for all agents in the deployment.

### Versioned Agent Updates

When updating an existing agent, the `ensure_agent` function in **[`agents/cma.py`](https://github.com/anthropics/cwc-workshops/blob/main/agents/cma.py)** (lines 40-55) implements a version-aware update strategy:

1. Retrieve the existing agent by deterministic name
2. Extract the current version number (defaulting to `1` if uninitialized)
3. Issue an update targeting that specific version

This prevents race conditions and ensures the configuration change applies to the correct revision.

```python

# From agents/cma.py - versioned update logic

current = c.beta.agents.retrieve(existing)
version = getattr(current, "version", None) or (
    getattr(current, "versions", [1]) or [1]
)[-1]
c.beta.agents.update(existing, version=version, **config)

```

## Configuration and Deployment

### Referencing Latest Skill Versions

The agent configuration specifies skill dependencies using the `"version": "latest"` pointer. In **[`agents/starter/agent.py`](https://github.com/anthropics/cwc-workshops/blob/main/agents/starter/agent.py)** (lines 100-126), the `build_config` function constructs a configuration that references uploaded skills:

```python
"skills": [
    {"type": "custom", "skill_id": skill_ids[n], "version": "latest"}
    for n in SKILLS if n in skill_ids
],

```

By using `"latest"`, the runtime automatically resolves to the most recent skill version uploaded during the deployment phase, eliminating the need to hardcode version strings.

### The Deployment Orchestration

The `deploy` function in **[`agents/cma.py`](https://github.com/anthropics/cwc-workshops/blob/main/agents/cma.py)** (lines 76-95) orchestrates the complete workflow:

1. Invokes `upload_skills` to package and version skills
2. Calls `ensure_env` to verify the execution environment
3. Executes `ensure_agent` to create or update the agent
4. Persists all generated IDs via `save_ids`

This single entry point ensures that running `deploy(slot, config_builder)` multiple times produces consistent results without creating duplicate resources.

## Idempotent Deployment with Persistent IDs

To support repeatable deployments for workshop attendees or CI/CD pipelines, the system caches all resource identifiers in **[`.stockpilot_ids.json`](https://github.com/anthropics/cwc-workshops/blob/main/.stockpilot_ids.json)**. The `load_ids` and `save_ids` functions in **[`agents/cma.py`](https://github.com/anthropics/cwc-workshops/blob/main/agents/cma.py)** (lines 56-62) manage this cache:

- On startup, the system reads existing IDs from the JSON file
- If resources exist, they are reused rather than recreated
- Newly created IDs are written back to the cache

This persistence layer ensures that subsequent deployments reference the same skills, environment, and agent instances, creating a truly idempotent workflow.

## Complete Deployment Example

The following example demonstrates deploying a "starter" agent with forecasting and reorder-policy skills:

```python
from agents.cma import client, upload_skills, ensure_agent, deploy

ALL_SKILLS = ["forecasting", "reorder-policy"]

def make_config(skill_ids):
    return {
        "name": "stockpilot-starter",
        "model": "claude-3-5-sonnet-20240620",
        "system": "You are StockPilot...",
        "tools": [{"type": "agent_toolset_20260401"}],
        "skills": [
            {"type": "custom", "skill_id": skill_ids[n], "version": "latest"}
            for n in ALL_SKILLS
        ],
    }

# Execute deployment

deployment_info = deploy("starter", make_config)
print("Agent deployed:", deployment_info["agents"]["starter"])

```

Running `uv run deploy starter` executes this workflow, uploading skill versions, ensuring the environment exists, updating the agent to the latest version, and caching all IDs for future runs.

## Summary

- **Skill versioning** occurs in `upload_skills` within [`agents/cma.py`](https://github.com/anthropics/cwc-workshops/blob/main/agents/cma.py), which creates new versions for existing skills without changing their IDs.
- **Versioned updates** use `ensure_agent` to retrieve the current agent version and issue targeted updates to that specific revision.
- **Latest version resolution** happens at runtime through the `"version": "latest"` pointer in skill configurations defined in [`agents/starter/agent.py`](https://github.com/anthropics/cwc-workshops/blob/main/agents/starter/agent.py).
- **Idempotency** is maintained by caching skill, environment, and agent IDs in [`.stockpilot_ids.json`](https://github.com/anthropics/cwc-workshops/blob/main/.stockpilot_ids.json) between deployments.
- **Orchestration** is handled by the `deploy` function, which sequences skill uploads, environment verification, and agent configuration.

## Frequently Asked Questions

### How does the workflow handle existing skills during deployment?

When `upload_skills` detects that a skill already exists, it calls `c.beta.skills.versions.create()` instead of `c.beta.skills.create()`. This generates a new skill version while preserving the original skill ID, ensuring that existing agent configurations continue to reference valid resources while receiving the updated logic.

### What happens if an agent already exists when running the deployment?

The `ensure_agent` function retrieves the existing agent by name, extracts its current version number, and issues an update to that specific version. If no agent exists, it creates a fresh one. This prevents duplicate agent creation and maintains continuity across deployments.

### Where are the resource IDs stored between deployments?

All identifiers for skills, environments, and agents are persisted in a local file named [`.stockpilot_ids.json`](https://github.com/anthropics/cwc-workshops/blob/main/.stockpilot_ids.json). The `load_ids` and `save_ids` utilities in [`agents/cma.py`](https://github.com/anthropics/cwc-workshops/blob/main/agents/cma.py) manage this cache, enabling the system to reuse existing resources on subsequent runs rather than creating new ones.

### How do I ensure my agent uses the latest version of a skill?

Configure the agent's skill references with `"version": "latest"` in the configuration builder, as implemented in [`agents/starter/agent.py`](https://github.com/anthropics/cwc-workshops/blob/main/agents/starter/agent.py). The deployment process uploads new skill versions first, and the runtime resolves the `"latest"` pointer to the most recently uploaded version when the agent executes.