GNL
Docs menu
Studio@gnldev/studio

Agent versioning

Keeps an agent's model/system/maxSteps versions in the journal, adds new versions, and activates the chosen version (promote) — the runtime runs whichever version is active.

What it's for / when to use it#

Used when you want to try out a code-defined agent's model/system-prompt/maxSteps combination before shipping it to prod, keep multiple versions side by side, and roll back to an older one when needed. Every new version is added to the journal via POST /managed-agents as an immutable record (a new attempt = a new version number); POST /managed-agents/:name/promote only moves the pointer that marks which version is "active" (prod) — rollback is nothing more than promoting an old version number again. The active version is applied automatically when that agent is run from the Studio Playground (run/stream), unless an explicit model/system override is given. Every version add and every promote is recorded in the audit log under the agent.version/agent.promote event names.

Setup / import#

There's no separate setup step — agent versioning is part of the @gnldev/studio Studio API, and it turns on by itself once given a writable journal (one that supports listKeys/get/put):

import { createStudioApp } from '@gnldev/studio';

app.route('/studio', createStudioApp({
  reader: toJournal(storage.runs), // a writable journal agent versioning is ON
  gnl: createStudioRunner(gnl, config),
  auth,
}));

The agentVersions field under GET /capabilities reports whether this view is enabled, based on whether the journal is writable; if not (a read-only reader), the corresponding endpoints return 501.

Step-by-step usage#

1) Add a new version — name and model are required, the rest are optional:

POST /studio/api/managed-agents
{ "name": "destek-botu", "model": "gpt-4o-mini", "system": "Kısa ve nazik yanıt ver.", "maxSteps": 4, "note": "daha kısa ton" }
// -> { ok: true, name: "destek-botu", version: 2, active: 1 }
//    a new version number + an audit 'agent.version'

The version number increments automatically (the latest version's version + 1); if the record is being created for the first time, it starts with active: null (meaning no version has been promoted to prod yet).

2) Activate the version you tried out (promote) — for rollback, promote the old version number again:

POST /studio/api/managed-agents/:name/promote
{ "version": 2 }
// -> { ok: true, name: "destek-botu", active: 2, previous: 1 }
//    switches the active version (passing the eval gate first, when one is configured)

3) List the records — version history plus the currently active version number are returned together:

GET /studio/api/managed-agents
GET /studio/api/managed-agents
// -> { agents: [ { name: "destek-botu", active: 2, versions: [ { version: 1, model: "...", createdAt }, { version: 2, model: "...", note: "daha kısa ton", createdAt } ] } ] }

The active version is applied automatically when POST /agents/:name/run or /agents/:name/stream is called from the Playground, unless model/system is given explicitly in the request body (when a managed version kicks in, managedVersion: true is flagged in the audit record).

API reference#

typeAgentVersion

A single (immutable) version record: version, model, system?, maxSteps?, note?, createdAt.

typeManagedAgentRecord

All versions plus the active (prod) version number for an agent: name, active (number | null), versions.

POST /managed-agents

Adds a new version with name + model (required) and system?/maxSteps?/note?; audit "agent.version".

POST /managed-agents/:name/promote

Marks the requested version number as active (rollback = promoting an old version again); audit "agent.promote".

GET /managed-agents

Lists every agent record scoped to that org (if any) — version history + active number.

Warning
Agent versioning requires a writable journal (one that supports listKeys/get/put) — in a Studio mounted with a read-only reader, the corresponding endpoints return 501. In multi-org setups, keep in mind that the bound identity (orgId) only sees/manages its own org's versions, while an unbound operator manages the shared (root) namespace.
Related
See eval-gate to require an eval suite before promote, studio-inspector for the general Studio surface, and audit-log to see the audit trail of every version/promote event.