API Prompt
Disparador HTTP en lenguaje natural para flujos de trabajo orientados a IA.
El disparador API Prompt expone un endpoint HTTP que acepta un prompt en lenguaje natural (más contexto estructurado y metadatos opcionales) y ejecuta un flujo de trabajo con esos campos disponibles como salidas de bloque. Es el disparador adecuado cuando quieres que tu API se sienta como "conversar con un flujo de trabajo" en lugar de "completar este esquema JSON."
Contrato de la solicitud
POST /api/webhooks/prompt/{path}
Content-Type: application/json
{
"prompt": "Summarize these PDFs and email me the result",
"context": { "pdf_ids": ["abc", "def"] },
"metadata": { "request_origin": "internal-app-v2" }
}prompt(string, obligatorio) — instrucción en lenguaje natural. Limitado amaxPromptLength(por defecto 10 000 caracteres, lÃmite máximo 50 000).context(objeto, opcional) — JSON arbitrario. Úsalo para pasar referencias estructuradas (IDs, rutas de archivos, perfil de usuario) junto al prompt.metadata(objeto, opcional) — identificadores proporcionados por el llamador que quieres exponer para enrutamiento/registro.
Cualquier campo adicional en el nivel raÃz será ignorado. El JSON anidado dentro de context y metadata se conserva.
Salidas del bloque
Disponibles en bloques posteriores mediante <apiprompt1.*>:
| Salida | Tipo | Descripción |
|---|---|---|
prompt | string | El prompt del llamador, recortado y validado en longitud |
context | json | null | El objeto context, o null si no se proporcionó |
metadata | json | null | El objeto metadata, o null si no se proporcionó |
requestId | string | ID generado por el servidor — se propaga en logs/trazas |
caller | string | Identidad derivada del llamador (bearer-hash / header-hash / hmac-hash / IP) |
timestamp | string | Hora de recepción en el servidor en formato ISO-8601 |
guardrailsTriggered | boolean | Verdadero si algún patrón conocido de inyección de prompt coincidió |
matchedInjectionPatterns | array | Nombres de los patrones que coincidieron (vacÃo si ninguno) |
Autenticación
Admite los mismos 4 modos que el disparador Webhook genérico:
| Modo | Encabezado enviado | Adecuado para |
|---|---|---|
none | — | Endpoints públicos, herramientas internas detrás de otra pasarela |
bearer | Authorization: Bearer <token> | Llamadores de IA programáticos — opción recomendada |
custom_header | <configured-name>: <token> | Compatibilidad con convenciones heredadas |
hmac_sha256 | X-Signature: <hex> sobre el cuerpo sin procesar | Máxima seguridad — sin estado, protegido contra reproducción |
Consulta Webhooks → Autenticación para ver ejemplos de firma en bash / Node / Python.
Llamar desde un consumidor — inicio rápido con HMAC
Cuando configuras la autenticación HMAC-SHA256, la plataforma espera un resumen hexadecimal de
los bytes exactos sin procesar del cuerpo de tu solicitud, firmado con tu secreto compartido, enviado en el
encabezado X-Signature (o el nombre que hayas definido en Signature header).
La firma debe cubrir los bytes que realmente envÃas por la red. Si tu cliente HTTP
vuelve a serializar el JSON (reordena claves, elimina espacios en blanco, escapa Unicode de forma diferente),
la firma no coincidirá. Construye la cadena del cuerpo una sola vez, fÃrmala, envÃala.
En curl, usa --data-raw. En Python, codifica previamente con json.dumps(...).encode()
y pasa data=body. En Node, construye la cadena y pásala como body de fetch.
curl
WEBHOOK_URL="https://staging-app.mybotbox.com/api/webhooks/prompt/<path>"
SECRET="<your HMAC secret>"
BODY='{"prompt":"Summarize last week of standup notes","context":{"team":"platform"}}'
TIMESTAMP=$(date +%s)
SIGNATURE=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')
curl -X POST "$WEBHOOK_URL" \
-H 'Content-Type: application/json' \
-H "X-Signature: $SIGNATURE" \
-H "X-Timestamp: $TIMESTAMP" \
--data-raw "$BODY"Notas:
X-Timestamp(segundos Unix o ISO-8601) es obligatorio cuando la ventana de reproducción del disparador está activa (por defecto 300s). Sin él recibirás401 — timestamp outside replay window.- El prefijo
sha256=es aceptado pero no obligatorio — el servidor lo elimina sin distinguir mayúsculas/minúsculas. X-Idempotency-Key: <your-request-id>es opcional pero recomendado para que los reintentos devuelvan200 { "status": "duplicate" }en lugar de volver a ejecutar el flujo de trabajo.
Python
import hmac, hashlib, json, time, requests
WEBHOOK_URL = "https://staging-app.mybotbox.com/api/webhooks/prompt/<path>"
SECRET = b"<your HMAC secret>"
body = json.dumps(
{"prompt": "Summarize last week of standup notes", "context": {"team": "platform"}},
separators=(",", ":"),
).encode()
sig = hmac.new(SECRET, body, hashlib.sha256).hexdigest()
resp = requests.post(
WEBHOOK_URL,
data=body,
headers={
"Content-Type": "application/json",
"X-Signature": sig,
"X-Timestamp": str(int(time.time())),
"X-Idempotency-Key": "req-2026-05-17-001",
},
)
print(resp.status_code, resp.text)Node.js / TypeScript
import { createHmac } from 'node:crypto'
const WEBHOOK_URL = 'https://staging-app.mybotbox.com/api/webhooks/prompt/<path>'
const SECRET = process.env.MBB_HMAC_SECRET! // never hardcode
const body = JSON.stringify({
prompt: 'Summarize last week of standup notes',
context: { team: 'platform' },
})
const sig = createHmac('sha256', SECRET).update(body).digest('hex')
const res = await fetch(WEBHOOK_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Signature': sig,
'X-Timestamp': Math.floor(Date.now() / 1000).toString(),
},
body,
})
console.log(res.status, await res.text())Incorporación de un consumidor
Cuando le das acceso a un tercero a uno de tus disparadores API Prompt, comparte exactamente cuatro cosas — y nada más:
- URL del webhook —
https://staging-app.mybotbox.com/api/webhooks/prompt/<path> - Secreto HMAC — el valor que escribiste en el campo "HMAC secret"
- Nombre del encabezado de firma —
X-Signature(por defecto) o el nombre personalizado que hayas definido - Contrato del cuerpo — la forma
{ prompt: string, context?: object, metadata?: object }, más tumaxPromptLengthconfigurado y sirequireContextestá activo
Cómo compartir el secreto de forma segura
El secreto HMAC autentica cada llamada. Si se filtra, cualquiera puede ejecutar tu flujo de trabajo con prompts arbitrarios. Trátalo como una contraseña de base de datos.
No hagas:
- Enviarlo por correo electrónico o Slack en texto plano
- Pegarlo en documentos compartidos (Notion, Confluence, Google Docs)
- Committearlo en ningún repositorio, ni siquiera privado
- Reutilizar el mismo secreto en staging y producción
Haz, en orden de preferencia:
- Elemento compartido en 1Password / Bitwarden — con alcance al correo del destinatario y una fecha de expiración. La mayorÃa de los equipos ya disponen de esto.
- Mensaje cifrado — Signal, o
gpg --encrypt --recipient <them@…>y luego envÃa el texto cifrado por cualquier canal. - Enlace de un solo uso —
https://onetimesecret.como un equivalente autoalojado. Vista única, se autodestruye en pocos minutos. - Léelo en voz alta en una videollamada — el destinatario lo pega directamente en su gestor de secretos y ambos cierran el elemento compartido. Nada queda escrito.
Higiene operacional
- Genera un secreto robusto:
openssl rand -hex 32(256 bits). Los marcadores de posición tipo1234567890están bien para la primera prueba de humo, pero rota antes de compartirlo externamente. - Rota cada 90 dÃas, o de inmediato si un consumidor se desvincula. Actualiza el secreto en la interfaz del disparador, guarda y notifica a tu consumidor. Las firmas antiguas dejan de funcionar en el momento en que guardas — si necesitas un perÃodo de gracia, ejecuta dos disparadores en paralelo durante la transición.
- Indica a los consumidores dónde almacenarlo: su gestor de secretos (AWS Secrets Manager / GCP Secret Manager / HashiCorp Vault / Doppler) o su almacén de variables de entorno de CI. Nunca en el código fuente.
- Revisa los logs tras la rotación: un repunte repentino de errores 401 generalmente significa que un consumidor no recibió el aviso de rotación.
La URL que muestra la interfaz del disparador hoy es el endpoint canónico:
/api/webhooks/prompt/<path>. La forma antigua /api/webhooks/trigger/<path> (que la
interfaz generaba para todos los tipos de disparador en versiones anteriores) sigue funcionando por compatibilidad
— ambas rutas comparten la misma verificación HMAC y salvaguardas. Prefiere la forma /prompt/ al
documentar integraciones.
Protección contra reproducción, idempotencia y limitación de tasa
- Ventana de reproducción (solo modo HMAC): rechaza solicitudes donde
X-Timestampesté a más de N segundos de la hora del servidor. Por defecto 300s;0la deshabilita. - Idempotencia: cuando está habilitada, las solicitudes duplicadas (identificadas por
X-Idempotency-Key, el campoiddel cuerpo o el hash del cuerpo) devuelven200 { status: "duplicate" }sin volver a ejecutar el flujo de trabajo. Ventana de deduplicación de 7 dÃas. - LÃmite de tasa por llamador: por defecto 20 solicitudes/min, identificadas por la identidad derivada del llamador. Genera un
429con el encabezadoRetry-Aftercuando se supera.
Salvaguardas contra inyección de prompt
Cuando están habilitadas (por defecto activas), la plataforma analiza el prompt contra una pequeña lista de patrones de inyección comunes (ignore previous instructions, prefijo system:, marcadores de plantilla de chat, etc.) y expone el resultado como guardrailsTriggered + matchedInjectionPatterns. Las salvaguardas son no bloqueantes — el flujo de trabajo sigue ejecutándose — por lo que puedes decidir por flujo de trabajo si rechazar, enrutar a revisión humana o continuar.
Las salvaguardas son un prefiltro de mejor esfuerzo, no un reemplazo para las defensas en el lado del LLM. Trata siempre el prompt como entrada no confiable en los bloques posteriores. Para operaciones de alto riesgo (enviar correos, ejecutar código, llamar a APIs de pago), añade pasos de confirmación explÃcita o enruta a revisión cuando guardrailsTriggered sea verdadero.
Forma tÃpica de un flujo de trabajo
- Disparador API Prompt (este bloque) — el llamador envÃa
{ prompt, context }. - Bloque Agent / LLM — recibe
<apiprompt1.prompt>y<apiprompt1.context>, planifica las siguientes acciones mediante llamadas a herramientas. - Bloques de acción posteriores (correo electrónico, base de datos, APIs de terceros) — ejecutan el plan.
- Bloque Response — devuelve el resumen del agente al llamador original.
Ejemplo — resumidor de PDFs
curl -X POST https://staging-app.mybotbox.com/api/webhooks/prompt/abc123 \
-H 'Authorization: Bearer $MBB_API_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"prompt": "Summarize these PDFs into bullet points and email to team@example.com",
"context": {
"pdf_gcs_paths": [
"gs://my-bucket/docs/report-2026-q1.pdf",
"gs://my-bucket/docs/report-2026-q2.pdf"
]
}
}'Configuración del flujo de trabajo:
- Bloque API Prompt → bloque Agent (Claude Haiku) con herramientas
[gcs_read_file, gmail_send]y prompt de sistema"Follow the user's instructions. Use tools as needed.". - Mensaje de usuario del agente:
<apiprompt1.prompt>\n\nContext: <apiprompt1.context>.
Verificar con los scripts incluidos
# Bearer token mode (recommended default).
bun apps/sat/tests/staging/triggers/api_prompt/verify.ts \
https://staging-app.mybotbox.com/api/webhooks/prompt/<path> \
--secret=<bearer-token>
# Or HMAC mode.
bun apps/sat/tests/staging/triggers/api_prompt/verify.ts \
https://staging-app.mybotbox.com/api/webhooks/prompt/<path> \
--hmac=<hmac-secret>python3 apps/sat/tests/staging/triggers/api_prompt/verify.py \
https://staging-app.mybotbox.com/api/webhooks/prompt/<path> \
--secret=<bearer-token>Fuente: apps/sat/tests/staging/triggers/api_prompt/.
Cuándo usar API Prompt frente a Generic Webhook
| Usa API Prompt cuando… | Usa Generic Webhook cuando… |
|---|---|
| El cuerpo es un prompt + contexto | El cuerpo es JSON estructurado con campos fijos |
| El primer bloque es un LLM/agente que planifica | El primer bloque es una condición o acción de base de datos |
| El llamador es un sistema de IA o un chatbot | El llamador es un servicio que publica eventos |
| Quieres salvaguardas y lÃmites de tasa por llamador de serie | Quieres HMAC al estilo de proveedor + deduplicación |
Generic Webhook es más simple y rápido cuando los campos del cuerpo se mapean 1:1 a variables del flujo de trabajo. Usa API Prompt cuando quieras que el LLM sea el enrutador.