Version Prompts
This guide covers how to create variants and commit changes to them using the Agenta SDK.
Creating and Managing Variants
The REST endpoints used below identify applications, variants, and revisions by UUID. When you only have a slug, resolve it with a prior call to POST /api/applications/query (each example below shows the resolve step inline). The Python SDK handles this automatically.
Create a New Variant
Use VariantManager.create to create a new variant with initial configuration:
- Python SDK
- JS/TS
- API
from agenta.sdk.types import PromptTemplate, Message, ModelConfig
from pydantic import BaseModel
# Define your configuration model
class Config(BaseModel):
prompt: PromptTemplate
# Create the initial configuration
config = Config(
prompt=PromptTemplate(
messages=[
Message(role="system", content="You are an assistant that provides concise answers"),
Message(role="user", content="Explain {{topic}} in simple terms"),
],
llm_config=ModelConfig(
model="gpt-3.5-turbo",
max_tokens=150,
temperature=0.7,
top_p=1.0,
frequency_penalty=0.0,
presence_penalty=0.0,
),
)
)
# Create the variant
variant = ag.VariantManager.create(
parameters=config.model_dump(),
app_slug="my-app-slug",
variant_slug="my-variant-slug",
)
const baseUrl = 'https://cloud.agenta.ai';
const headers = {
'Content-Type': 'application/json',
'Authorization': 'ApiKey YOUR_API_KEY'
};
// Step 1: Resolve the application slug to a UUID
const appLookup = await fetch(`${baseUrl}/api/applications/query`, {
method: 'POST', headers,
body: JSON.stringify({ application_refs: [{ slug: 'my-app-slug' }] })
});
const { applications } = await appLookup.json();
const applicationId = applications[0].id;
// Step 2: Create the variant under that application
const createVariantResponse = await fetch(`${baseUrl}/api/applications/variants/`, {
method: 'POST',
headers,
body: JSON.stringify({
application_variant: {
application_id: applicationId,
slug: 'my-variant-slug',
name: 'my-variant-slug'
}
})
});
const { application_variant } = await createVariantResponse.json();
// Step 3: Commit the initial revision with parameters
// `slug` must be unique within the variant's revision history.
const commitResponse = await fetch(`${baseUrl}/api/applications/revisions/commit`, {
method: 'POST',
headers,
body: JSON.stringify({
application_revision_commit: {
application_variant_id: application_variant.id,
slug: 'initial',
message: 'Initial commit',
data: {
parameters: {
prompt: {
messages: [
{ role: 'system', content: 'You are an assistant that provides concise answers' },
{ role: 'user', content: 'Explain {{topic}} in simple terms' }
],
llm_config: {
model: 'gpt-3.5-turbo',
max_tokens: 150,
temperature: 0.7,
top_p: 1.0,
frequency_penalty: 0.0,
presence_penalty: 0.0
}
}
}
}
}
})
});
console.log(await commitResponse.json());
# Step 1: Resolve the application slug to a UUID
curl -X POST "https://cloud.agenta.ai/api/applications/query" \
-H "Content-Type: application/json" \
-H "Authorization: ApiKey YOUR_API_KEY" \
-d '{"application_refs":[{"slug":"my-app-slug"}]}'
# → copy applications[0].id into APPLICATION_UUID below
# Step 2: Create the variant under that application
curl -X POST "https://cloud.agenta.ai/api/applications/variants/" \
-H "Content-Type: application/json" \
-H "Authorization: ApiKey YOUR_API_KEY" \
-d '{
"application_variant": {
"application_id": "APPLICATION_UUID",
"slug": "my-variant-slug",
"name": "my-variant-slug"
}
}'
# → copy application_variant.id into VARIANT_UUID below
# Step 3: Commit the initial revision with parameters
# `slug` must be unique within the variant's revision history.
curl -X POST "https://cloud.agenta.ai/api/applications/revisions/commit" \
-H "Content-Type: application/json" \
-H "Authorization: ApiKey YOUR_API_KEY" \
-d '{
"application_revision_commit": {
"application_variant_id": "VARIANT_UUID",
"slug": "initial",
"message": "Initial commit",
"data": {
"parameters": {
"prompt": {
"messages": [
{ "role": "system", "content": "You are an assistant that provides concise answers" },
{ "role": "user", "content": "Explain {{topic}} in simple terms" }
],
"llm_config": {
"model": "gpt-3.5-turbo",
"max_tokens": 150,
"temperature": 0.7,
"top_p": 1.0,
"frequency_penalty": 0.0,
"presence_penalty": 0.0
}
}
}
}
}
}'
Use VariantManager.acreate for async variant creation.
This command will create a new variant and initialize it with the first commit containing the parameters provided
- Parameters:
app_slug: The slug of your application.variant_slug: The slug of the new variant.parameters: A dictionary containing the initial configuration parameters.
Note: If a variant with the same slug and version already exists, the SDK will raise an exception.
Sample Output:
{
"messages": [
{
"role": "system",
"content": "You are an assistant that provides concise answers"
},
{
"role": "user",
"content": "Explain {{topic}} in simple terms"
}
],
"llm_config": {
"model": "gpt-3.5-turbo",
"max_tokens": 150,
"temperature": 0.7,
"top_p": 1.0,
"frequency_penalty": 0.0,
"presence_penalty": 0.0
},
"template_format": "curly"
}
Committing changes to a variant (Creating a new version in a variant)
To save changes to a variant (creating a new version), use the VariantManager.commit method with explicit parameters.
- Python SDK
- JS/TS
- API
config2=Config(
prompt=PromptTemplate(
messages=[
Message(role="system", content="You are an assistant that provides VERY concise answers"),
Message(role="user", content="Explain {{topic}} in simple terms"),
],
llm_config=ModelConfig(
model="anthropic/claude-3-5-sonnet-20240620",
max_tokens=150,
temperature=0.7,
top_p=1.0,
frequency_penalty=0.0,
presence_penalty=0.0,
),
)
)
# Commit the new version
variant = ag.VariantManager.commit(
parameters=config2.model_dump(),
app_slug="my-app-slug",
variant_slug="my-variant-slug",
)
print("Committed new version of variant:")
print(variant)
# Commit the new version asynchronously (optional)
# async def commit_variant():
# variant = await ag.VariantManager.acommit(
# parameters=my_prompt2.model_dump(),
# app_slug="my-app-slug",
# variant_slug="my-variant-slug",
# )
# print("Committed new version of variant (async):")
# print(variant)
// Commit a new revision on an existing variant
const commitResponse = await fetch('https://cloud.agenta.ai/api/applications/revisions/commit', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'ApiKey YOUR_API_KEY'
},
body: JSON.stringify({
application_revision_commit: {
application_variant_id: 'VARIANT_UUID',
slug: 'switch-to-claude',
message: 'Switch to Claude',
data: {
parameters: {
prompt: {
messages: [
{ role: 'system', content: 'You are an assistant that provides VERY concise answers' },
{ role: 'user', content: 'Explain {{topic}} in simple terms' }
],
llm_config: {
model: 'anthropic/claude-3-5-sonnet-20240620',
max_tokens: 150,
temperature: 0.7,
top_p: 1.0,
frequency_penalty: 0.0,
presence_penalty: 0.0
}
}
}
}
}
})
});
const result = await commitResponse.json();
console.log('Committed new version of variant:');
console.log(result);
# Commit a new revision on an existing variant
curl -X POST "https://cloud.agenta.ai/api/applications/revisions/commit" \
-H "Content-Type: application/json" \
-H "Authorization: ApiKey YOUR_API_KEY" \
-d '{
"application_revision_commit": {
"application_variant_id": "VARIANT_UUID",
"slug": "switch-to-claude",
"message": "Switch to Claude",
"data": {
"parameters": {
"prompt": {
"messages": [
{ "role": "system", "content": "You are an assistant that provides VERY concise answers" },
{ "role": "user", "content": "Explain {{topic}} in simple terms" }
],
"llm_config": {
"model": "anthropic/claude-3-5-sonnet-20240620",
"max_tokens": 150,
"temperature": 0.7,
"top_p": 1.0,
"frequency_penalty": 0.0,
"presence_penalty": 0.0
}
}
}
}
}
}'
Use VariantManager.acommit for async version commit.
Each commit creates a new version of the variant. Versions are immutable once created.
Sample Output:
{
"app_id": "01963413-3d39-7650-80ce-3ad5d688da6c",
"app_slug": "my-app-slug",
"variant_id": "01968c11-6f7c-7773-b273-922c5807be7b",
"variant_slug": "my-variant-slug",
"variant_version": 5,
"environment_id": null,
"environment_slug": null,
"environment_version": null,
"committed_at": "2025-05-01T07:26:08.935406+00:00",
"committed_by": "user@agenta.ai",
"committed_by_id": "0196247a-ec9d-7051-8880-d58279570aa1",
"deployed_at": null,
"deployed_by": null,
"deployed_by_id": null,
"params": {
"messages": [
{
"name": null,
"role": "system",
"content": "You are an assistant that provides concise answers",
"tool_calls": null,
"tool_call_id": null
},
{
"name": null,
"role": "user",
"content": "Explain {{topic}} in simple terms",
"tool_calls": null,
"tool_call_id": null
}
],
"input_keys": null,
"llm_config": {
"model": "gpt-3.5-turbo",
"tools": null,
"top_p": 1.0,
"stream": null,
"max_tokens": 150,
"temperature": 0.7,
"tool_choice": null,
"response_format": null,
"presence_penalty": 0.0,
"frequency_penalty": 0.0
},
"user_prompt": null,
"system_prompt": null,
"template_format": "curly"
}
}
The user_prompt and system_prompt are helper fields to populate the messages field in the PromptTemplate. Rely only on the messages field in your code.
Deploying to Environments
To deploy a variant to an environment, use the DeploymentManager.deploy method with the variant reference and environment_slug: The slug of the environment (development, staging, or production).
deployment = ag.DeploymentManager.deploy(
app_slug="my-app-slug",
variant_slug="my-variant-slug",
variant_version=None, # Deploys latest version if not specified
environment_slug="staging" # Options: development, staging, production
)
print(f"Deployed to {deployment['environment_slug']}")
- Omitting the revision (SDK
variant_version, RESTapplication_revision_ref) deploys the latest revision of the variant. - Only predefined environments with slugs
development,staging, andproductionare currently supported.
Sample Output:
Deployed variant to environment:
{
"app_id": "01963413-3d39-7650-80ce-3ad5d688da6c",
"app_slug": "completion",
"variant_id": "01968c11-6f7c-7773-b273-922c5807be7b",
"variant_slug": "my-variant-slug4",
"variant_version": 5,
"environment_id": "01968c14-c35d-7440-bcc8-9def594f017f",
"environment_slug": "staging",
"environment_version": 2,
"committed_at": "2025-05-01T07:26:08.935406+00:00",
"committed_by": "user@agenta.ai",
"committed_by_id": "0196247a-ec9d-7051-8880-d58279570aa1",
"deployed_at": "2025-05-01T13:41:33.149595+00:00",
"deployed_by": "user@agenta.ai",
"deployed_by_id": "0196247a-ec9d-7051-8880-d58279570aa1"
}
Fetching a Prompt Configuration
You can fetch the configurations from a variant reference (app_slug, variant_slug, variant_version) or an environment reference (app_slug, environment_slug). The default behavior when fetching is to fetch the latest configuration from the production environment. If you don't provide a _version parameter but only a variant_slug or an environment_slug, the SDK will fetch the latest version of the variant from the specified environment/variant.
Understanding the PromptTemplate
When you fetch a prompt configuration, you receive a PromptTemplate object. This object contains all the information needed to format and send your prompt to an LLM provider.
The PromptTemplate includes:
- messages: An ordered list of chat messages with roles and content
- llm_config: Model parameters like temperature, max tokens, and the model name
- template_format: The syntax used for variable placeholders in your prompt
- input_keys: An optional list of required variables for input validation
Here's what a fetched configuration looks like:
config = ag.ConfigManager.get_from_registry(
app_slug="my-app-slug"
)
print(config)
# Output:
# {
# "prompt": {
# "messages": [
# {"role": "system", "content": "You are a helpful assistant"},
# {"role": "user", "content": "Explain {{topic}} in simple terms"}
# ],
# "llm_config": {
# "model": "gpt-3.5-turbo",
# "temperature": 0.7,
# "max_tokens": 150
# },
# "template_format": "curly"
# }
# }
Template Format
The template_format field determines how Agenta replaces variable placeholders in your prompts. Agenta supports three formats:
Curly format (default): Uses double curly braces like {{variable}}. This format is simple and safe. It only replaces variables that were defined in your original template, which helps catch missing inputs early.
"Explain {{topic}} in {{language}}"
Jinja2 format: Uses Jinja2 syntax like {{ variable }} and supports advanced features like loops and filters. Choose this format when you need conditional logic or want to transform variables.
"{% if variable %}...{% endif %}"
Check the reference section for more details on the data format used for prompts.
Default Behavior when fetching
If you don't provide either variant or environment identifiers, the SDK fetches the latest configuration deployed to the production environment.
config = ag.ConfigManager.get_from_registry(
app_slug="my-app-slug",
variant_slug="my-variant-slug",
variant_version=2 # Optional: fetches latest if not provided
)
print("Fetched configuration from production:")
print(config)
Example Output:
{
"prompt": {
"messages": [
{
"role": "system",
"content": "You are an assistant that provides concise answers"
},
{
"role": "user",
"content": "Explain {{topic}} in simple terms"
}
],
"llm_config": {
"model": "gpt-3.5-turbo",
"top_p": 1.0,
"max_tokens": 150,
"temperature": 0.7,
"presence_penalty": 0.0,
"frequency_penalty": 0.0
},
"template_format": "curly"
}
}
Agenta provides a helper class PromptTemplate to format the configuration and then use it to generate the prompt.
from openai import OpenAI
from agenta.sdk.types import PromptTemplate
# Fetch configuration
config = ag.ConfigManager.get_from_registry(
app_slug="my-app-slug"
)
# Format the prompt with variables
prompt = PromptTemplate(**config['prompt']).format(topic="AI")
# Use with OpenAI
client = OpenAI()
response = client.chat.completions.create(
**prompt.to_openai_kwargs()
)
print(response.choices[0].message.content)
Fetching by Variant Reference
# Fetch configuration by variant
config = ag.ConfigManager.get_from_registry(
app_slug="my-app-slug",
variant_slug="my-variant-slug",
variant_version=2 # Optional: If not provided, fetches the latest version
)
print("Fetched configuration:")
print(config)
Fetching by Environment Reference
# Fetch the latest configuration from the staging environment
config = ag.ConfigManager.get_from_registry(
app_slug="my-app",
environment_slug="staging",
environment_version=1 # Optional: If not provided, fetches the latest version
)
print("Fetched configuration from staging:")
print(config)
Deleting a Variant
To delete a variant, use the VariantManager.delete method.
- Python SDK
- JS/TS
- API
# Delete a variant
ag.VariantManager.delete(
app_slug="my-app",
# app_id="my-app-id", # you can also use `app_id`
variant_slug="obsolete-variant"
)
print("Variant deleted successfully.")
// Archive a variant (soft-delete). Call /unarchive to restore.
const archiveResponse = await fetch(
`https://cloud.agenta.ai/api/applications/variants/VARIANT_UUID/archive`,
{
method: 'POST',
headers: {
'Authorization': 'ApiKey YOUR_API_KEY'
}
}
);
if (archiveResponse.ok) {
console.log('Variant archived successfully.');
} else {
console.error('Failed to archive variant:', archiveResponse.status);
}
# Archive a variant (soft-delete). Call /unarchive to restore.
curl -X POST "https://cloud.agenta.ai/api/applications/variants/VARIANT_UUID/archive" \
-H "Authorization: ApiKey YOUR_API_KEY"
Archiving is a soft delete. The variant is hidden from queries (unless include_archived: true is passed) and can be restored with POST /applications/variants/{variant_id}/unarchive.
- Archiving a variant hides all of its revisions.
- Attempting to archive a variant that is deployed to an environment will fail.
Listing All Variants
To list all variants of an application, use the VariantManager.list method.
- Python SDK
- JS/TS
- API
# List all variants (syncrhonously)
variants = ag.VariantManager.list(
app_slug="my-app"
# app_id="my-app-id", # you can also use `app_id`
)
print(variants)
const baseUrl = 'https://cloud.agenta.ai';
const headers = {
'Content-Type': 'application/json',
'Authorization': 'ApiKey YOUR_API_KEY'
};
// Step 1: Resolve the application slug to an id
const appLookup = await fetch(`${baseUrl}/api/applications/query`, {
method: 'POST', headers,
body: JSON.stringify({ application_refs: [{ slug: 'my-app' }] })
});
const { applications } = await appLookup.json();
const appId = applications[0].id;
// Step 2: List variants under that application
const listResponse = await fetch(`${baseUrl}/api/applications/variants/query`, {
method: 'POST', headers,
body: JSON.stringify({
application_refs: [{ id: appId }],
include_archived: false,
windowing: { limit: 50 }
})
});
const { count, application_variants } = await listResponse.json();
console.log(count, application_variants);
# Step 1: Resolve the application slug to an id
curl -X POST "https://cloud.agenta.ai/api/applications/query" \
-H "Content-Type: application/json" \
-H "Authorization: ApiKey YOUR_API_KEY" \
-d '{"application_refs":[{"slug":"my-app"}]}'
# → copy applications[0].id into APPLICATION_UUID below
# Step 2: List variants under that application
curl -X POST "https://cloud.agenta.ai/api/applications/variants/query" \
-H "Content-Type: application/json" \
-H "Authorization: ApiKey YOUR_API_KEY" \
-d '{
"application_refs": [{ "id": "APPLICATION_UUID" }],
"include_archived": false,
"windowing": { "limit": 50 }
}'
Sample Output:
[{
"app_id": "01963413-3d39-7650-80ce-3ad5d688da6c",
"app_slug": "completion",
"variant_id": "01968aba-9702-7263-a7fd-8b8565753230",
"variant_slug": "my-variant-slug3",
"variant_version": 2,
"environment_id": null,
"environment_slug": null,
"environment_version": null,
"committed_at": "2025-05-01T07:23:26.338901+00:00",
"committed_by": "user@agenta.ai",
"committed_by_id": "0196247a-ec9d-7051-8880-d58279570aa1",
"deployed_at": null,
"deployed_by": null,
"deployed_by_id": null,
"params": {
"prompt": {
"messages": [
{
"name": null,
"role": "system",
"content": "You are an assistant that provides concise answers",
"tool_calls": null,
"tool_call_id": null
},
{
"name": null,
"role": "user",
"content": "Explain {{topic}} in simple terms",
"tool_calls": null,
"tool_call_id": null
}
],
"input_keys": null,
"llm_config": {
"model": "gpt-3.5-turbo",
"tools": null,
"top_p": 1.0,
"stream": null,
"max_tokens": 150,
"temperature": 0.7,
"tool_choice": null,
"response_format": null,
"presence_penalty": 0.0,
"frequency_penalty": 0.0
},
"user_prompt": null,
"system_prompt": null,
"template_format": "curly"
}
}
}, {
"app_id": "01963413-3d39-7650-80ce-3ad5d688da6c",
"app_slug": "completion",
"variant_id": "01963f1f-28ea-78e1-b390-39d270fe93fe",
"variant_slug": "key",
"variant_version": 4,
"environment_id": null,
"environment_slug": null,
"environment_version": null,
"committed_at": "2025-04-16T15:02:08.874979+00:00",
"committed_by": "user@agenta.ai",
"committed_by_id": "0196247a-ec9d-7051-8880-d58279570aa1",
"deployed_at": null,
"deployed_by": null,
"deployed_by_id": null,
"params": {
"ag_config": {
"prompt": {
"messages": [
{
"role": "system",
"content": "You are an expert in geography"
},
{
"role": "user",
"content": "What is the capital of {{country}}? tell me its name in arabic"
}
],
"input_keys": [
"country"
],
"llm_config": {
"model": "gpt-3.5-turbo"
},
"template_format": "curly"
}
}
}
}]
Fetching a Variant's History
To list all versions for a variant of an application, use the VariantManager.history method.
- Python SDK
- JS/TS
- API
# List all variant versions/history (synchronously)
versions = ag.VariantManager.history(
variant_slug="variant-slug",
app_slug="my-app"
# app_id="my-app-id", # you can also use `app_id`
)
print(versions)
// List revisions for a specific variant
const historyResponse = await fetch('https://cloud.agenta.ai/api/applications/revisions/log', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'ApiKey YOUR_API_KEY'
},
body: JSON.stringify({
application: {
application_variant_id: 'VARIANT_UUID'
}
})
});
const { count, application_revisions } = await historyResponse.json();
console.log(count, application_revisions);
# List revisions for a specific variant
curl -X POST "https://cloud.agenta.ai/api/applications/revisions/log" \
-H "Content-Type: application/json" \
-H "Authorization: ApiKey YOUR_API_KEY" \
-d '{
"application": {
"application_variant_id": "VARIANT_UUID"
}
}'
Sample Output:
Same as VariantManager.list but limited to the history of a specific variant.
All SDK methods have async counterparts with an a prefix:
async def async_operations():
# Create variant asynchronously
variant = await ag.VariantManager.acreate(...)
# Commit changes asynchronously
updated_variant = await ag.VariantManager.acommit(...)
