How to Manage Prompts with the SDK
This guide covers all prompt management operations using the Agenta SDK: creating variants, committing changes, deploying to environments, and fetching configurations.
Prerequisites
Before starting, familiarize yourself with how versioning works in Agenta. Details are available on the concepts page.
Agenta uses a Git-like structure for prompt versioning:
- Create multiple branches called variants
- Each variant is versioned.
- Deploy specific versions to environments (development, staging, production)
Typical workflow:
- Create a variant (branch)
- Commit changes to the variant creating a new version
- Deploy the version to an environment
Setup
Initialize the SDK before using any operations:
import os
import agenta as ag
# Set your API credentials
os.environ["AGENTA_API_KEY"] = "your-api-key-here"
os.environ["AGENTA_HOST"] = "https://cloud.agenta.ai" # only needed if self-hosting
# Initialize the SDK
ag.init()
Creating a new application
You can create a new application from the UI or programmatically.
Creating a new application from the UI
Go to the App Management page and click on the "Create New Prompt" button, then choose the type of application you want to create (chat for multi-turn chat applications or completion for single-turn applications).
Creating a new application from the SDK
# Creates an empty application
app = ag.AppManager.create(
app_slug="my-app-slug",
template_key="SERVICE:completion", # we define here the app type
# template_key="SERVICE:chat" # chat prompts
# template_key="CUSTOM" # custom configuration (schema-less, however unless you provide a URI, you can only use the registry but not the playground)
)
The app created until now is empty. You cannot use it from the UI yet. You need to create a variant and commit changes to it to be able to use it (next section).
Creating and Managing Variants
Create a New Variant
Use VariantManager.create to create a new variant with initial configuration:
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",
)
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.
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)
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']}")
- Deploying a variant without specifying a
variant_versiondeploys the latest version. - 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.
# 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.")
- Deleting a variant removes all versions of the variant. This action is irreversible.
- Attempting to delete 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.
# 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)
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.list method.
# 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)
Sample Output:
Same as VariantManager.list but limited to the history of a specific variant.
Asynchronous Operations
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(...)
# Fetch configuration asynchronously
config = await ag.ConfigManager.aget_from_registry(...)
