> Source: https://wexa.ai/docs/agents/agent-versions

# agent-versions

Read an agent's promoted version history, newest first, or a field-level diff between two versions. Needs the `fabric:orchestrate.read` grant.

**Read an agent's versions**

**Wexa MCP server**

```bash
curl -sS -X POST https://fabric.wexa.ai/mcp/$FABRIC_PROJECT_ID \
  -H "authorization: Bearer $FABRIC_API_KEY" \
  -H "Mcp-Session-Id: $MCP_SESSION_ID" \
  -H "content-type: application/json" -H "accept: application/json" \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"agent-versions","arguments":{"agent_id":"6ab1945e7566f41b5c28e303.6ab1945e83ff5845d7db96bc"}}}'
```

```json
{
  "content": [
    {
      "type": "text",
      "text": "{\"lifecycle_id\":\"qlc_000176\",\"result\":{\"agent_id\":\"6ab1945e7566f41b5c28e303.6ab1945e83ff5845d7db96bc\",\"live_version\":0,\"versions\":[]}}"
    }
  ],
  "isError": false
}
```

**REST API**

```bash
curl -sS https://fabric.wexa.ai/v1/agent-versions \
  -H "authorization: Bearer $FABRIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"agent_id":"6ab1945e7566f41b5c28e303.6ab1945e83ff5845d7db96bc"}'
```

```json
{
  "lifecycle_id": "qlc_000176",
  "result": {
    "agent_id": "6ab1945e7566f41b5c28e303.6ab1945e83ff5845d7db96bc",
    "live_version": 0,
    "versions": []
  }
}
```

**TypeScript SDK**

```ts
import { Fabric } from '@wexa-fabric/sdk'

const fabric = new Fabric()
const result = await fabric.agentVersions({
  agent_id: '6ab1945e7566f41b5c28e303.6ab1945e83ff5845d7db96bc'
})
```

```ts
// result is the payload itself, with no `.result` to read
{
  agent_id: '6ab1945e7566f41b5c28e303.6ab1945e83ff5845d7db96bc',
  live_version: 0,
  versions: []
}
```

**Python SDK**

```python
from wexa import Fabric

fabric = Fabric()
out = fabric.agent_versions(
    agent_id="6ab1945e7566f41b5c28e303.6ab1945e83ff5845d7db96bc",
)
```

```python
# out is the result, already unwrapped
{
    "agent_id": "6ab1945e7566f41b5c28e303.6ab1945e83ff5845d7db96bc",
    "live_version": 0,
    "versions": []
}
```

## Parameters

| Parameter | Type | Required | Notes |
| --- | --- | --- | --- |
| `agent_id` | string | Required | Agent id (an agent inside a process flow). Any agent id; one with no promoted version lists as empty. |
| `from_version` | integer | Optional | With `to_version` (both or neither): return a diff between these two versions instead of the list. Starts at 1. |
| `to_version` | integer | Optional | With `from_version` (both or neither): the version to diff against. Starts at 1. |

**Errors**

- `NotFound` (404): a diff (`from_version` and `to_version`) names a version the agent does not have ("one or both versions not found").

**Show full response**

A real response, captured from a live call to `agent-versions`:

**Result of agent-versions**

**REST API**

```json
{
  "lifecycle_id": "qlc_000176",
  "result": {
    "agent_id": "6ab1945e7566f41b5c28e303.6ab1945e83ff5845d7db96bc",
    "live_version": 0,
    "versions": []
  }
}
```

**Wexa MCP server**

```json
{
  "content": [
    {
      "type": "text",
      "text": "{\"lifecycle_id\":\"qlc_000176\",\"result\":{\"agent_id\":\"6ab1945e7566f41b5c28e303.6ab1945e83ff5845d7db96bc\",\"live_version\":0,\"versions\":[]}}"
    }
  ],
  "isError": false
}
```

**TypeScript SDK**

```ts
// the object you get back IS the result — there is no `.result` to read
{
  agent_id: '6ab1945e7566f41b5c28e303.6ab1945e83ff5845d7db96bc',
  live_version: 0,
  versions: []
}

// The TS SDK names these camelCase — lifecycleId, traceId — where Python uses
// lifecycle_id and trace_id. Both are non-enumerable: readable, but omitted by
// Object.keys() and JSON.stringify(). `result.lifecycleId` here is undefined.
result.lifecycleId // 'qlc_000176'
```

**Python SDK**

```python
# a dict subclass; `result` is already unwrapped
{
 "agent_id": "6ab1945e7566f41b5c28e303.6ab1945e83ff5845d7db96bc",
 "live_version": 0,
 "versions": []
}

out.lifecycle_id  # 'qlc_000176' — an attribute, not a key
```

**More details**

Every promote records a snapshot: the version number, the config as promoted, who promoted it and with what role, its test pass rate, and which version it replaced. A version has one of three statuses: `promoted`, `superseded` or `rolled_back`. The live version is the one marked `promoted`, which is not necessarily the highest number, because a rollback can make an earlier version live again. Use [rollback-agent-version](/docs/agents/rollback-agent-version) to change which one is live.

A version exists only after a promote. An agent you have just made with `create-agent` has none, so `agent-versions` answers `versions: []` for it, and that is not an error. The first version of an agent is promoted in the console, in Agent Simulation. No tool creates it. Once an agent has versions, `rollback-agent-version` can make any of them live. A [Proxy agent](/docs/agents/create-agent#proxy) needs a promoted version before its chat completions endpoint answers. `run-agent` needs none.

In the console, open the agent, open the actions menu and choose **Version history**. It stays greyed out until the agent has a promoted version, and the live one is marked **Currently live**. For an agent there is no promote tool: choose **Simulate & Promote** in the same menu. Promotion is a step taken on a tested version, not a field you set on the agent definition.

### Two version tracks

Agents and process flows are versioned separately, and each track captures something the other cannot.

|  | Process-flow version | Agent version |
| --- | --- | --- |
| Snapshot of | The whole process flow when promoted: every agent, its configuration and the wiring | One agent's own configuration |
| Also records | Which version is live | Who promoted it, under what role, which version it replaced and how its tests scored |
| Catches | Structural change: an agent added, removed or rewired | Changes to that agent only |

They move independently. Making a different version of an agent live changes what every process flow naming that agent does, without the process flow's own version changing. Merging the two histories would make one of the two changes invisible.

Editing records nothing on its own: history exists because something was promoted. A process flow has [flow-versions](/docs/automation/flow-versions) to list its versions and name the live one, and [promote-flow](/docs/automation/promote-flow) to snapshot it. Numbers are never reassigned: roll back to v1 while v2 was live and v2 stays in the history as `rolled_back`, v1 is live again, and the next promote is v3.

Every tool call works the same way: [How every tool call works](/docs/sdks-and-apis/how-every-tool-call-works).
