curl --request POST \
--url https://api-prod.studio.getsupervisor.ai/v1/agents/from-template \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"templateId": "0f92c4f0-62f7-4337-82c2-7d9b19c5b6a2",
"name": "Campaña de cobranza",
"status": "inactive",
"debounceDelayMs": 500
}
'import requests
url = "https://api-prod.studio.getsupervisor.ai/v1/agents/from-template"
payload = {
"templateId": "0f92c4f0-62f7-4337-82c2-7d9b19c5b6a2",
"name": "Campaña de cobranza",
"status": "inactive",
"debounceDelayMs": 500
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
templateId: '0f92c4f0-62f7-4337-82c2-7d9b19c5b6a2',
name: 'Campaña de cobranza',
status: 'inactive',
debounceDelayMs: 500
})
};
fetch('https://api-prod.studio.getsupervisor.ai/v1/agents/from-template', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api-prod.studio.getsupervisor.ai/v1/agents/from-template",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'templateId' => '0f92c4f0-62f7-4337-82c2-7d9b19c5b6a2',
'name' => 'Campaña de cobranza',
'status' => 'inactive',
'debounceDelayMs' => 500
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api-prod.studio.getsupervisor.ai/v1/agents/from-template"
payload := strings.NewReader("{\n \"templateId\": \"0f92c4f0-62f7-4337-82c2-7d9b19c5b6a2\",\n \"name\": \"Campaña de cobranza\",\n \"status\": \"inactive\",\n \"debounceDelayMs\": 500\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api-prod.studio.getsupervisor.ai/v1/agents/from-template")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"templateId\": \"0f92c4f0-62f7-4337-82c2-7d9b19c5b6a2\",\n \"name\": \"Campaña de cobranza\",\n \"status\": \"inactive\",\n \"debounceDelayMs\": 500\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-prod.studio.getsupervisor.ai/v1/agents/from-template")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"templateId\": \"0f92c4f0-62f7-4337-82c2-7d9b19c5b6a2\",\n \"name\": \"Campaña de cobranza\",\n \"status\": \"inactive\",\n \"debounceDelayMs\": 500\n}"
response = http.request(request)
puts response.read_body{
"agentId": "8e7a9b94-2d5f-4d26-a2d5-6ff5f08fc81f",
"workspaceId": "a44bb95e-9f01-4d19-8b62-1f6f2b8e8363",
"name": "Cobranza Outbound Baseline",
"agentType": "voice",
"description": null,
"status": "inactive",
"avatarUrl": null,
"ownerUserId": "0a3c8cf2-6b54-4e89-8d36-7e67c77dfba5",
"debounceDelayMs": 500,
"totalCalls": 0,
"totalOperationalDays": 0,
"goalAchievedPercentage": 0,
"knowledgeBaseIds": [],
"version": {
"id": "4c01f8ad-9ae5-4b20-98af-9559a2899a21",
"status": "draft",
"number": 1
},
"createdAt": "2025-10-15T09:21:45.000Z",
"updatedAt": "2025-10-15T09:21:45.000Z"
}{
"statusCode": 400,
"error": "Bad Request",
"message": "Workspace context is required to fork an agent from a template"
}{
"statusCode": 404,
"error": "Not Found",
"message": "No existe la plantilla solicitada"
}{
"code": "COPILOT_ATTACHMENTS_CLOSED",
"message": "Adjuntar archivos en el chat no está disponible para este workspace."
}Plantillas de agentes
Descubre plantillas publicadas y clónalas con blueprint, stages, triggers e instrucciones ya armados.
curl --request POST \
--url https://api-prod.studio.getsupervisor.ai/v1/agents/from-template \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"templateId": "0f92c4f0-62f7-4337-82c2-7d9b19c5b6a2",
"name": "Campaña de cobranza",
"status": "inactive",
"debounceDelayMs": 500
}
'import requests
url = "https://api-prod.studio.getsupervisor.ai/v1/agents/from-template"
payload = {
"templateId": "0f92c4f0-62f7-4337-82c2-7d9b19c5b6a2",
"name": "Campaña de cobranza",
"status": "inactive",
"debounceDelayMs": 500
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
templateId: '0f92c4f0-62f7-4337-82c2-7d9b19c5b6a2',
name: 'Campaña de cobranza',
status: 'inactive',
debounceDelayMs: 500
})
};
fetch('https://api-prod.studio.getsupervisor.ai/v1/agents/from-template', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api-prod.studio.getsupervisor.ai/v1/agents/from-template",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'templateId' => '0f92c4f0-62f7-4337-82c2-7d9b19c5b6a2',
'name' => 'Campaña de cobranza',
'status' => 'inactive',
'debounceDelayMs' => 500
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api-prod.studio.getsupervisor.ai/v1/agents/from-template"
payload := strings.NewReader("{\n \"templateId\": \"0f92c4f0-62f7-4337-82c2-7d9b19c5b6a2\",\n \"name\": \"Campaña de cobranza\",\n \"status\": \"inactive\",\n \"debounceDelayMs\": 500\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api-prod.studio.getsupervisor.ai/v1/agents/from-template")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"templateId\": \"0f92c4f0-62f7-4337-82c2-7d9b19c5b6a2\",\n \"name\": \"Campaña de cobranza\",\n \"status\": \"inactive\",\n \"debounceDelayMs\": 500\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-prod.studio.getsupervisor.ai/v1/agents/from-template")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"templateId\": \"0f92c4f0-62f7-4337-82c2-7d9b19c5b6a2\",\n \"name\": \"Campaña de cobranza\",\n \"status\": \"inactive\",\n \"debounceDelayMs\": 500\n}"
response = http.request(request)
puts response.read_body{
"agentId": "8e7a9b94-2d5f-4d26-a2d5-6ff5f08fc81f",
"workspaceId": "a44bb95e-9f01-4d19-8b62-1f6f2b8e8363",
"name": "Cobranza Outbound Baseline",
"agentType": "voice",
"description": null,
"status": "inactive",
"avatarUrl": null,
"ownerUserId": "0a3c8cf2-6b54-4e89-8d36-7e67c77dfba5",
"debounceDelayMs": 500,
"totalCalls": 0,
"totalOperationalDays": 0,
"goalAchievedPercentage": 0,
"knowledgeBaseIds": [],
"version": {
"id": "4c01f8ad-9ae5-4b20-98af-9559a2899a21",
"status": "draft",
"number": 1
},
"createdAt": "2025-10-15T09:21:45.000Z",
"updatedAt": "2025-10-15T09:21:45.000Z"
}{
"statusCode": 400,
"error": "Bad Request",
"message": "Workspace context is required to fork an agent from a template"
}{
"statusCode": 404,
"error": "Not Found",
"message": "No existe la plantilla solicitada"
}{
"code": "COPILOT_ATTACHMENTS_CLOSED",
"message": "Adjuntar archivos en el chat no está disponible para este workspace."
}1 · Descubrir plantillas
GET /v1/catalogs/templates requiere el scope catalogs:read. No
hardcodees identificadores de plantilla en tu integración: el catálogo cambia,
y el listado es la única fuente al día.curl --request GET \
--url "$API_BASE_URL/v1/catalogs/templates" \
--header "X-API-Key: $API_KEY" \
--header "X-Workspace-Id: $WORKSPACE_ID"
id de la plantilla, su slug, sus tags y el
agentVersionId que se clona. La visibility clasifica la plantilla: curada por
Leracom (system), compartida públicamente (community) o no publicada al
catálogo general (private).
?visibility=private como «las plantillas de mi workspace» — es una
etiqueta de la plantilla, no una pertenencia. Identifica las tuyas por slug o
por tags.GET /v1/catalogs/templates?visibility=system
GET /v1/catalogs/templates?tags=cobranza,voz
2 · Clonar la plantilla
SólotemplateId es obligatorio. Si omites templateVersionId se usa la versión
publicada más reciente de la plantilla.
curl --request POST \
--url "$API_BASE_URL/v1/agents/from-template" \
--header "X-API-Key: $API_KEY" \
--header "X-Workspace-Id: $WORKSPACE_ID" \
--header "Content-Type: application/json" \
--data '{
"templateId": "ec9205ec-7c0c-41b7-86da-67cc3c2dd0f2",
"name": "Cobranza Preventiva - Retail",
"status": "inactive"
}'
import { createClient } from '@getsupervisor/agents-studio-sdk';
const client = createClient({
baseUrl: process.env.API_BASE_URL!,
workspaceId: process.env.WORKSPACE_ID!,
apiKey: process.env.API_KEY!,
});
const agent = await client.agents.forkFromTemplate({
templateId: 'ec9205ec-7c0c-41b7-86da-67cc3c2dd0f2',
name: 'Cobranza Preventiva - Retail',
status: 'inactive',
});
console.log(agent.agentId, agent.name, agent.versionId);
Campos del cuerpo
| Campo | Requerido | Notas |
|---|---|---|
templateId | Sí | UUID de la plantilla del catálogo |
templateVersionId | No | Versión concreta a clonar; por defecto, la publicada más reciente |
name | No | Máx. 255 caracteres; hereda el de la plantilla si se omite |
description | No | Máx. 1000 caracteres |
status | No | inactive, training o active |
debounceDelayMs | No | Entero ≥ 0 |
brief | No | Máx. 10 000 caracteres; contexto de negocio para personalizar |
researchUrl | No | URL del sitio del cliente, para enriquecer la personalización |
voiceId | No | id de un ítem de catálogo de tipo voice |
documentRefs | No | Documentos previamente subidos con POST /v1/documents |
agents:write. La respuesta trae el agentId y el
versionId de la versión inicial.
inactive mientras lo revisas. Un agente que nace active
empieza a atender con la configuración de la plantilla, sin tus políticas
aplicadas.3 · Antes de publicar
- Conecta las herramientas que el caso de uso pida —agenda, función propia, transferencia— desde la pestaña Herramientas del agente.
- Ajusta el horario de atención con
POST /v1/agents/{agentId}/schedules, y las excepciones puntuales conPOST /v1/agents/{agentId}/schedules/exceptions. - Revisa saludo, reglas críticas y triggers contra tus políticas internas.
- Deja constancia del cambio en
notesal publicar la versión (PATCH /v1/agents/{agentId}/versions/{versionId}/notes).
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
Datos necesarios para clonar una plantilla del catálogo y crear un nuevo agente en el workspace activo. Permite sobrescribir metadatos básicos del agente generado.
Identificador de la plantilla a clonar.
Opcional. Si no se especifica, se usa el agent_version_id configurado como predeterminado en la tabla catalog_templates.
Opcional. Nombre a asignar al nuevo agente.
255Opcional. Descripción operativa del agente.
1000Opcional. Estado inicial del agente generado.
inactive, training, active Opcional. Delay antes de procesar eventos (milisegundos).
x >= 0Prompt de personalización para Claude Code headless. Si se proporciona, la respuesta cambia a SSE (text/event-stream) con eventos de progreso.
10000URL del sitio web del cliente para que Claude investigue contexto.
Voz seleccionada para el agente (UUID del catálogo de voces). Si se proporciona, se aplica al blueprint durante la personalización.
Los ficheros que el cliente adjuntó en el chat de creación, ya subidos y confirmados en el namespace agent-briefs, junto con lo que dijo de cada uno. Al crear el agente se reclaman, que es lo que impide que el barrido se los lleve a las 72 h.
Todo o nada: si un id no existe, no terminó de subirse, se subió a otro namespace o ya lo usa otro agente, la petición responde 422 nombrando cuáles fallaron y no se reclama ninguno. Un id de otro workspace se reporta como inexistente. Repetir el mismo uploadId en la lista responde 400.
10Show child attributes
Show child attributes
Response
Agente creado a partir de plantilla
chat, voice inactive, training, active, archived, building, failed Total de llamadas realizadas por el agente.
x >= 0Total de días operativos desde la creación del agente.
x >= 0Porcentaje de llamadas donde el objetivo fue alcanzado.
0 <= x <= 100La versión vigente del agente: la active si la hay y, si no, el borrador más
reciente. Es de aquí de donde sale el identificador de versión que piden las rutas
de blueprint, instrucciones y publicación — no hay un versionId plano.
Se omite cuando el agente todavía no tiene ninguna versión.
Show child attributes
Show child attributes
URL pública opcional utilizada para representar al agente.
Delay opcional antes de enviar respuestas (milisegundos).
x >= 0Las bases de conocimiento que este agente consulta durante la conversación. Vacío significa que no consulta ninguna, no que no se sepa. Es la selección del cliente, leída del mismo sitio del que la lee el sync al publicar una versión, así que no puede divergir de lo que se toma como entrada al publicar. Al publicar, el proveedor de voz recibe sólo las que además están listas y son suyas: una base a medio indexar aparece aquí y todavía no viaja.
