Dynamic Choices
Dynamic choices allow your agent's form fields to display options that are resolved at runtime rather than being hardcoded in the field definition. This is useful when the available options depend on external data sources like databases, APIs, or configuration files.
When to use
Use dynamic choices when:
- The list of options changes over time (e.g., active projects, team members, available models)
- The options come from an external source (database, API)
- The options are environment-specific (dev vs. prod)
Use static choices when the options are fixed and known at definition time (e.g., country codes, status values).
Setup
1. Define the field with dynamic_choices
Instead of providing a choices list, set dynamic_choices to a key name:
from supervaizer import AgentMethodField
field = AgentMethodField(
name="List of projects",
type=str,
field_type="ChoiceField",
dynamic_choices="projects", # key name
required=True,
)
choices and dynamic_choices are mutually exclusive. Setting both will raise a validation error.
2. Define the callback function
Create a function that takes a method name and a context dictionary, and returns a dictionary mapping choice keys to their value/label pairs:
def get_dynamic_choices(method_name: str, context: dict) -> dict[str, list[tuple[str, str]]]:
"""Return dynamic choices for the given method.
Args:
method_name: The method requesting choices (e.g., "start")
context: Dict with workspace_id and mission_id from the request
Returns:
Dict mapping choice key names to lists of (value, label) tuples
"""
if method_name == "start":
# Fetch from your data source
# context contains workspace_id and mission_id
projects = fetch_projects_from_db()
return {
"projects": [(p.id, p.name) for p in projects],
}
return {}
The return format is dict[str, list[tuple[str, str]]]:
- Keys match the
dynamic_choicesvalues on your fields - Values are lists of
(value, label)tuples — same format as staticchoices
You can return multiple keys if multiple fields use dynamic choices:
def get_dynamic_choices(method_name: str, context: dict) -> dict[str, list[tuple[str, str]]]:
return {
"projects": [("P1", "Project 1"), ("P2", "Project 2")],
"teams": [("T1", "Team Alpha"), ("T2", "Team Beta")],
}
3. Pass the callback to the Agent
from supervaizer import Agent
agent = Agent(
name="my_agent",
author="Your Name",
version="1.0",
description="My agent with dynamic choices",
methods=AgentMethods(job_start=job_start_method),
dynamic_choices_callback=get_dynamic_choices,
)
How it works
When Supervaize Studio renders the job start form:
- Studio checks if any field has
dynamic_choicesset - If so, it calls
POST /supervaizer/agents/{agent_slug}/start/dynamic_choiceswithworkspace_idandmission_id - The endpoint invokes your callback with
"start"as the method name and the context dict - The returned choices are used to populate the form dropdowns
┌──────────────┐ POST /start/dynamic_choices ┌───────────────┐
│ Supervaize │ ──────────────────────────────────► │ Supervaizer │
│ Studio │ {workspace_id, mission_id} │ Controller │
│ │ ◄────────────────────────────────── │ │
│ (renders │ {"choices": {"projects": ...}} │ (calls your │
│ the form) │ │ callback) │
└──────────────┘ └───────────────┘
API Reference
Endpoint
POST /supervaizer/agents/{agent_slug}/start/dynamic_choices
Headers: X-API-Key: {your_api_key}
Request body:
{
"workspace_id": "your-workspace-id",
"mission_id": "your-mission-id"
}
The workspace_id and mission_id are passed to the callback as a context dict, allowing the callback to return choices specific to the current workspace and mission.
Response
{
"choices": {
"projects": [
["P1", "Project 1"],
["P2", "Project 2"],
["P3", "Project 3"]
]
}
}
Error responses
| Status | Meaning |
|---|---|
| 200 | Choices returned successfully |
| 404 | Agent has no dynamic_choices_callback configured |
| 500 | Callback raised an error |
Complete example
from supervaizer import Agent, AgentMethod, AgentMethodField, AgentMethods, Server
def get_dynamic_choices(method_name: str, context: dict) -> dict[str, list[tuple[str, str]]]:
if method_name == "start":
return {
"projects": [("P1", "Project 1"), ("P2", "Project 2"), ("P3", "Project 3")],
}
return {}
job_start = AgentMethod(
name="start",
method="my_agent.start_job",
fields=[
AgentMethodField(
name="Company name",
type=str,
field_type="CharField",
required=True,
),
AgentMethodField(
name="Project",
type=str,
field_type="ChoiceField",
dynamic_choices="projects",
required=True,
),
],
description="Start a new research job",
)
agent = Agent(
name="research_agent",
author="Your Name",
version="1.0",
description="Research agent with dynamic project selection",
methods=AgentMethods(job_start=job_start),
dynamic_choices_callback=get_dynamic_choices,
)
server = Server(agents=[agent])