List agent templates
GET /api/v1/agents/templates — built-in agent starter templates.
GET /api/v1/agents/templatesReturn the catalog of built-in agent templates. Templates are starting points — a partial config seed plus a base system_prompt that you fill in with a name, tweak, and save as a new agent via POST /agents.
Authentication
X-API-Key: zsk_...Response
{
"templates": [
{
"slug": "sales-qualifier",
"name": "Sales qualifier",
"description": "Asks 3 qualification questions and hands off if qualified.",
"icon": "phone",
"category": "sales",
"system_prompt": "You are {{agentName}}, a sales qualifier for ...",
"config": {
"greeting": { "firstMessages": ["Hi, this is {{agentName}}..."] },
"llm": { "provider": "openai", "model": "gpt-5.4-mini" },
"tts": { "provider": "elevenlabs" },
"stt": { "provider": "soniox" }
}
}
]
}| Field | Notes |
|---|---|
slug / name / description / category | Catalog metadata for rendering the template picker. |
icon | Icon name for the template card. |
system_prompt | Top-level sibling — not nested in config. The base prompt with a {{agentName}} placeholder. |
config | A partial AgentConfig seed (camelCase) — a starting point, not a complete body. |
Substitute {{agentName}} client-side
The consumer substitutes the chosen {{agentName}} into system_prompt and each entry of config.greeting.firstMessages client-side, then POSTs { ...config, name, systemPrompt: substituted } to POST /agents. system_prompt is passed as the top-level systemPrompt field — it is not part of the seed config.
Examples
curl https://dashboard.zoxa.ai/api/v1/agents/templates \
-H "X-API-Key: zsk_..."const { templates } = await fetch(
"https://dashboard.zoxa.ai/api/v1/agents/templates",
{ headers: { "X-API-Key": "zsk_..." } },
).then((r) => r.json());
// Use the first template: substitute {{agentName}} client-side, then POST.
const t = templates[0];
const agentName = "My copy";
const systemPrompt = t.system_prompt.replaceAll("{{agentName}}", agentName);
const config = { ...t.config };
if (config.greeting?.firstMessages?.length) {
config.greeting = {
...config.greeting,
firstMessages: config.greeting.firstMessages.map((m) =>
m.replaceAll("{{agentName}}", agentName),
),
};
}
const created = await fetch("https://dashboard.zoxa.ai/api/v1/agents", {
method: "POST",
headers: { "X-API-Key": "zsk_...", "Content-Type": "application/json" },
body: JSON.stringify({ ...config, name: agentName, systemPrompt }),
}).then((r) => r.json());import httpx
templates = httpx.get(
"https://dashboard.zoxa.ai/api/v1/agents/templates",
headers={"X-API-Key": "zsk_..."},
).json()["templates"]
# Use the first template: substitute {{agentName}} client-side, then POST.
t = templates[0]
agent_name = "My copy"
system_prompt = t["system_prompt"].replace("{{agentName}}", agent_name)
config = dict(t["config"])
greeting = config.get("greeting")
if greeting and greeting.get("firstMessages"):
config["greeting"] = {
**greeting,
"firstMessages": [
m.replace("{{agentName}}", agent_name) for m in greeting["firstMessages"]
],
}
httpx.post(
"https://dashboard.zoxa.ai/api/v1/agents",
headers={"X-API-Key": "zsk_..."},
json={**config, "name": agent_name, "systemPrompt": system_prompt},
)Related
POST /agents— create from a templateGET /agents/models/available— which providers/models are valid
Delete an agent
DELETE /api/v1/agents/{agent_uuid} — soft-delete (archive). Historical calls keep their references.
List available models
GET /api/v1/agents/models/available — every LLM, STT and TTS model an agent can use, with the exact provider and model values to send, display names, defaults and supported languages.