Skip to content

Support for releasing AI Catalog agent versions

What does this MR do and why?

This MR adds support for releasing AI Catalog agent versions.

Frontend changes

The frontend has been changed to create released agents. On master it currently always creates draft agents.

Shifting the UI to create released versions instead of drafts allows the backend to implement some features that require versions to be released, without it negatively affecting the UI experience. There are a few TODOs in our codebase around scoping things to released versions that the backend wasn't yet implementing because our UI only had the ability to create draft versions.

We could launch a beta with the UI having no concept of versioning if it's creating and editing released versions.

There is no actual difference experienced by the user at this point.

Backend changes

The backend has been changed to support the idea of releasing versions of an agent.

The logic is:

  • A version can be a draft or released
  • Draft versions can be edited:
    • Editing a draft version will result in the draft being updated
    • Editing a draft version and providing released: true will result in the draft being released
  • Released versions cannot be edited:
    • Editing a released version will result in a new draft version being created
    • Editing a released version and providing released: true will result in a new released version being created

A new ai_catalog_enforce_readonly_versions feature flag

There is a new ai_catalog_enforce_readonly_versions feature flag that when enabled will enforce that released versions cannot be edited, resulting in a new version being created.

The flag has been created to allow us to keep this flag as disabled, and so our MVP can continue to lack the UI necessary for allowing the user to choose between draft and release, without it creating endless released versions.

Potentially, we can release the feature in beta with this flag disabled if we need to. That would mean our MVC has no real user-facing concept of releases, and all changes to agents would always be "live", as the user would always be updating the same single version record which would be released. Ideally, this isn't our beta, but it allows it.

But when the flag is enabled locally, we can "move into the future", which allows the backend to continue to implement forward-features around versioning and releasing with the true future of released versions being immutable.

How to set up and validate locally

First, enable the global_ai_catalog feature flag:

Feature.enable(:global_ai_catalog)

frontend QA

The frontend has been changed to always create released agents. On master it currently always creates draft agents.

  1. Visit http://gdk.test:3000/explore/ai-catalog/agents
  2. Create a new agent
  3. Verify on the Rails console that the record was created with a version that was released:
    Ai::Catalog::Item.last.versions.first.released? # => true
  4. Now, edit the agent and update some properties
  5. Verify on the Rails console that the record still has only 1 version, and it is still released:
    Ai::Catalog::Item.last.versions.count # =>1
    Ai::Catalog::Item.last.versions.first.released? # => true

backend QA

Create an agent with a released version:

fragment VersionFragment on AiCatalogItemVersion {
  releasedAt
  released
  versionName
  ...on AiCatalogAgentVersion {
    systemPrompt
  }
}

mutation {
  aiCatalogAgentCreate(input: {
    projectId: "gid://gitlab/Project/1000000"
    name: "My name"
    description: "My description"
    released: true
    public: false
    systemPrompt: "My system prompt"
    userPrompt: "My user prompt"
  }) {
    errors
    item {
      id
      latestVersion {
        ...VersionFragment
      }
      versions {
        count
        nodes {
          ...VersionFragment
        }
      }
    }
  }
}

There will be 1 version, which will be released, and at 1.0.0:

{
  "data": {
    "aiCatalogAgentCreate": {
      "errors": [],
      "item": {
        "id": "gid://gitlab/Ai::Catalog::Item/75",
        "latestVersion": {
          "releasedAt": "2025-08-07T22:09:06Z",
          "released": true,
          "versionName": "v1.0.0"
          "systemPrompt": "My system prompt"
        },
        "versions": {
          "count": 1,
          "nodes": [
            {
              "releasedAt": "2025-08-07T22:09:06Z",
              "released": true,
              "versionName": "v1.0.0"
              "systemPrompt": "My system prompt"
            }
          ]
        }
      }
    }
  },
  "correlationId": "01K2399ANBDMMKM7TZG8VCNHCW"
}

Update the agent's systemPrompt. Replace id with the Global ID of the agent that was returned in the GraphiQL create response.

fragment VersionFragment on AiCatalogItemVersion {
  releasedAt
  released
  versionName
  ...on AiCatalogAgentVersion {
    systemPrompt
  }
}

mutation {
  aiCatalogAgentUpdate(input: {
    id: "gid://gitlab/Ai::Catalog::Item/75"
    name: "My name"
    description: "My description"
    released: true
    public: false
    systemPrompt: "My NEW system prompt"
    userPrompt: "My user prompt"
  }) {
    errors
    item {
      id
      name
      description
      public
      latestVersion {
        ...VersionFragment
      }
      versions {
        count
        nodes {
          ...VersionFragment
        }
      }
    }
  }
}

You will see that the same 1 released version has been updated, and no new versions have been created.

{
  "data": {
    "aiCatalogAgentUpdate": {
      "errors": [],
      "item": {
        "id": "gid://gitlab/Ai::Catalog::Item/75",
        "latestVersion": {
          "releasedAt": "2025-08-07T22:09:06Z",
          "released": true,
          "versionName": "v1.0.0",
          "systemPrompt": "My NEW system prompt"
        },
        "versions": {
          "count": 1,
          "nodes": [
            {
              "releasedAt": "2025-08-07T22:09:06Z",
              "released": true,
              "versionName": "v1.0.0",
              "systemPrompt": "My NEW system prompt"
            }
          ]
        }
      }
    }
  },
  "correlationId": "01K239GYZHS6NRF3D7SNZYVPYD"
}

Now enable the ai_catalog_enforce_readonly_versions feature flag:

Feature.enable(:ai_catalog_enforce_readonly_versions)

This feature flag takes the backend into the future where you cannot make changes to released versions, and instead you will be creating new version records. But you can make changes to draft records.

Run the update mutation again, but with a new systemPrompt argument value.

This time you will have created a second released version, which will have the versionName of v2.0.0 (a new major release).

{
  "data": {
    "aiCatalogAgentUpdate": {
      "errors": [],
      "item": {
        "id": "gid://gitlab/Ai::Catalog::Item/75",
        "latestVersion": {
          "releasedAt": "2025-08-07T22:16:01Z",
          "released": true,
          "versionName": "v2.0.0",
          "systemPrompt": "My NEWSS system prompt"
        },
        "versions": {
          "count": 2,
          "nodes": [
            {
              "releasedAt": "2025-08-07T22:16:01Z",
              "released": true,
              "versionName": "v2.0.0",
              "systemPrompt": "My NEWSS system prompt"
            },
            {
              "releasedAt": "2025-08-07T22:09:06Z",
              "released": true,
              "versionName": "v1.0.0",
              "systemPrompt": "My NEW system prompt"
            }
          ]
        }
      }
    }
  },
  "correlationId": "01K239NZPR2PY9XN5F3ANYRMQN"
}

Run the exact same update mutation again, without making and changes to the argument.

It should be a no-op with no new versions created.

Change the name, description, public argument values and run the update mutation.

It should update the name, description, public properties, but not create any new versions. This is because the name, description and public properties are properties of the item, and not one of its versions, and so can be changed at any time without affecting its versions.

Now make a change to the systemPrompt but also set released argument to false.

It should create a new version, which is a draft (released property will be false), and a versionName of v3.0.0-draft.

Make another change to the systemPrompt (keep released argument as false)

It should update the draft version and not create any new versions.

Now release the draft version, change released argument to true.

It should update the same draft version to be released at versionName of v3.0.0 and should not have created any new versions.

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Related to #560254 (closed)

Edited by Luke Duncalfe

Merge request reports

Loading