> For the complete documentation index, see [llms.txt](https://docs.umbraco.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.umbraco.com/ai-in-umbraco/17.latest/reference/services/ai-entity-version-service.md).

# IAIEntityVersionService

Service for accessing version history, comparing versions, and creating snapshots of AI entities.

## Namespace

```csharp
using Umbraco.AI.Core.Versioning;
```

## Interface

{% code title="IAIEntityVersionService" %}

```csharp
public interface IAIEntityVersionService
{
    Task<(IEnumerable<AIEntityVersion> Items, int Total)> GetVersionHistoryAsync(
        Guid entityId,
        string entityType,
        int skip,
        int take,
        CancellationToken cancellationToken = default);

    Task<AIEntityVersion?> GetVersionAsync(
        Guid entityId,
        string entityType,
        int version,
        CancellationToken cancellationToken = default);

    Task<TEntity?> GetVersionSnapshotAsync<TEntity>(
        Guid entityId,
        int version,
        CancellationToken cancellationToken = default)
        where TEntity : class, IAIVersionableEntity;

    Task SaveVersionAsync<TEntity>(
        TEntity entity,
        Guid? userId,
        string? changeDescription = null,
        CancellationToken cancellationToken = default)
        where TEntity : class, IAIVersionableEntity;

    Task SaveVersionAsync(
        Guid entityId,
        string entityType,
        int version,
        string snapshot,
        Guid? userId,
        string? changeDescription = null,
        CancellationToken cancellationToken = default);

    Task DeleteVersionsAsync(
        Guid entityId,
        string entityType,
        CancellationToken cancellationToken = default);

    Task<AIVersionComparison?> CompareVersionsAsync(
        Guid entityId,
        string entityType,
        int fromVersion,
        int toVersion,
        CancellationToken cancellationToken = default);

    string CreateSnapshot<TEntity>(TEntity entity)
        where TEntity : class, IAIVersionableEntity;

    TEntity? RestoreFromSnapshot<TEntity>(string snapshot)
        where TEntity : class, IAIVersionableEntity;

    Task<AIVersionCleanupResult> CleanupVersionsAsync(
        CancellationToken cancellationToken = default);
}
```

{% endcode %}

## Methods

### GetVersionHistoryAsync

Gets the version history for an entity.

| Parameter           | Type                | Description                                  |
| ------------------- | ------------------- | -------------------------------------------- |
| `entityId`          | `Guid`              | The entity ID                                |
| `entityType`        | `string`            | The entity type (e.g., "profile", "context") |
| `skip`              | `int`               | Records to skip                              |
| `take`              | `int`               | Records to take                              |
| `cancellationToken` | `CancellationToken` | Cancellation token                           |

**Returns**: Tuple of (versions, total count).

{% code title="Example" %}

```csharp
var (versions, total) = await _versionService.GetVersionHistoryAsync(
    profileId,
    "profile",
    skip: 0,
    take: 10);

foreach (var v in versions)
{
    Console.WriteLine($"Version {v.Version}: {v.DateCreated}");
}
```

{% endcode %}

### GetVersionAsync

Gets a specific version record.

| Parameter           | Type                | Description        |
| ------------------- | ------------------- | ------------------ |
| `entityId`          | `Guid`              | The entity ID      |
| `entityType`        | `string`            | The entity type    |
| `version`           | `int`               | The version number |
| `cancellationToken` | `CancellationToken` | Cancellation token |

**Returns**: The version record if found, otherwise `null`.

### GetVersionSnapshotAsync

Gets the entity state at a specific version.

| Parameter           | Type                | Description        |
| ------------------- | ------------------- | ------------------ |
| `entityId`          | `Guid`              | The entity ID      |
| `version`           | `int`               | The version number |
| `cancellationToken` | `CancellationToken` | Cancellation token |

**Returns**: The deserialized entity at that version, or `null`.

{% code title="Example" %}

```csharp
var previousProfile = await _versionService.GetVersionSnapshotAsync<AIProfile>(
    profileId,
    version: 3);

if (previousProfile != null)
{
    Console.WriteLine($"Profile name at v3: {previousProfile.Name}");
    Console.WriteLine($"Temperature at v3: {previousProfile.Settings?.Temperature}");
}
```

{% endcode %}

### SaveVersionAsync

Saves a version snapshot for an entity. This is typically called automatically by entity services. Two overloads are available: a generic one that snapshots a typed entity, and a non-generic one that accepts raw snapshot data.

{% code title="Generic overload" %}

```csharp
Task SaveVersionAsync<TEntity>(
    TEntity entity,
    Guid? userId,
    string? changeDescription = null,
    CancellationToken cancellationToken = default)
    where TEntity : class, IAIVersionableEntity;
```

{% endcode %}

| Parameter           | Type                | Description              |
| ------------------- | ------------------- | ------------------------ |
| `entity`            | `TEntity`           | The entity to snapshot   |
| `userId`            | `Guid?`             | User who made the change |
| `changeDescription` | `string?`           | Description of changes   |
| `cancellationToken` | `CancellationToken` | Cancellation token       |

{% code title="Raw-snapshot overload" %}

```csharp
Task SaveVersionAsync(
    Guid entityId,
    string entityType,
    int version,
    string snapshot,
    Guid? userId,
    string? changeDescription = null,
    CancellationToken cancellationToken = default);
```

{% endcode %}

| Parameter           | Type                | Description                            |
| ------------------- | ------------------- | -------------------------------------- |
| `entityId`          | `Guid`              | The entity ID                          |
| `entityType`        | `string`            | The entity type name (e.g., "Profile") |
| `version`           | `int`               | The version number                     |
| `snapshot`          | `string`            | The raw JSON snapshot                  |
| `userId`            | `Guid?`             | User who made the change               |
| `changeDescription` | `string?`           | Description of changes                 |
| `cancellationToken` | `CancellationToken` | Cancellation token                     |

### DeleteVersionsAsync

Deletes all version history for an entity.

| Parameter           | Type                | Description        |
| ------------------- | ------------------- | ------------------ |
| `entityId`          | `Guid`              | The entity ID      |
| `entityType`        | `string`            | The entity type    |
| `cancellationToken` | `CancellationToken` | Cancellation token |

### CompareVersionsAsync

Compares two versions and returns the differences.

| Parameter           | Type                | Description        |
| ------------------- | ------------------- | ------------------ |
| `entityId`          | `Guid`              | The entity ID      |
| `entityType`        | `string`            | The entity type    |
| `fromVersion`       | `int`               | Source version     |
| `toVersion`         | `int`               | Target version     |
| `cancellationToken` | `CancellationToken` | Cancellation token |

**Returns**: Comparison result with changes.

{% code title="Example" %}

```csharp
var comparison = await _versionService.CompareVersionsAsync(
    profileId,
    "profile",
    fromVersion: 2,
    toVersion: 5);

if (comparison != null)
{
    foreach (var change in comparison.Changes)
    {
        Console.WriteLine($"{change.Path}: {change.ChangeType}");
        Console.WriteLine($"  From: {change.FromValue}");
        Console.WriteLine($"  To: {change.ToValue}");
    }
}
```

{% endcode %}

### CreateSnapshot / RestoreFromSnapshot

Creates and restores JSON snapshots of entities.

{% code title="Example" %}

```csharp
// Create a snapshot
var snapshot = _versionService.CreateSnapshot(profile);

// Later, restore from snapshot
var restored = _versionService.RestoreFromSnapshot<AIProfile>(snapshot);
```

{% endcode %}

### CleanupVersionsAsync

Removes old versions based on retention settings.

**Returns**: Cleanup result with count of removed versions.

{% code title="Example" %}

```csharp
var result = await _versionService.CleanupVersionsAsync();
Console.WriteLine($"Cleaned up {result.DeletedCount} old versions");
```

{% endcode %}

## Entity Types

| Type String    | Entity Class                            |
| -------------- | --------------------------------------- |
| `"connection"` | `AIConnection`                          |
| `"profile"`    | `AIProfile`                             |
| `"context"`    | `AIContext`                             |
| `"prompt"`     | `AIPrompt` (requires Umbraco.AI.Prompt) |
| `"agent"`      | `AIAgent` (requires Umbraco.AI.Agent)   |

## Related

* [AIEntityVersion](/ai-in-umbraco/17.latest/reference/models/ai-entity-version.md) - The version model
* [Version History Concept](/ai-in-umbraco/17.latest/concepts/versioning.md) - Versioning concepts


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.umbraco.com/ai-in-umbraco/17.latest/reference/services/ai-entity-version-service.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
