MyBotBoxMyBotBox

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 a maxPromptLength (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.*>:

SalidaTipoDescripción
promptstringEl prompt del llamador, recortado y validado en longitud
contextjson | nullEl objeto context, o null si no se proporcionó
metadatajson | nullEl objeto metadata, o null si no se proporcionó
requestIdstringID generado por el servidor — se propaga en logs/trazas
callerstringIdentidad derivada del llamador (bearer-hash / header-hash / hmac-hash / IP)
timestampstringHora de recepción en el servidor en formato ISO-8601
guardrailsTriggeredbooleanVerdadero si algún patrón conocido de inyección de prompt coincidió
matchedInjectionPatternsarrayNombres de los patrones que coincidieron (vacío si ninguno)

Autenticación

Admite los mismos 4 modos que el disparador Webhook genérico:

ModoEncabezado enviadoAdecuado para
none—Endpoints públicos, herramientas internas detrás de otra pasarela
bearerAuthorization: Bearer <token>Llamadores de IA programáticos — opción recomendada
custom_header<configured-name>: <token>Compatibilidad con convenciones heredadas
hmac_sha256X-Signature: <hex> sobre el cuerpo sin procesarMá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ás 401 — 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 devuelvan 200 { "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:

  1. URL del webhook — https://staging-app.mybotbox.com/api/webhooks/prompt/<path>
  2. Secreto HMAC — el valor que escribiste en el campo "HMAC secret"
  3. Nombre del encabezado de firma — X-Signature (por defecto) o el nombre personalizado que hayas definido
  4. Contrato del cuerpo — la forma { prompt: string, context?: object, metadata?: object }, más tu maxPromptLength configurado y si requireContext está 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:

  1. 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.
  2. Mensaje cifrado — Signal, o gpg --encrypt --recipient <them@…> y luego envía el texto cifrado por cualquier canal.
  3. Enlace de un solo uso — https://onetimesecret.com o un equivalente autoalojado. Vista única, se autodestruye en pocos minutos.
  4. 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 tipo 1234567890 está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-Timestamp esté a más de N segundos de la hora del servidor. Por defecto 300s; 0 la deshabilita.
  • Idempotencia: cuando está habilitada, las solicitudes duplicadas (identificadas por X-Idempotency-Key, el campo id del cuerpo o el hash del cuerpo) devuelven 200 { 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 429 con el encabezado Retry-After cuando 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

  1. Disparador API Prompt (este bloque) — el llamador envía { prompt, context }.
  2. Bloque Agent / LLM — recibe <apiprompt1.prompt> y <apiprompt1.context>, planifica las siguientes acciones mediante llamadas a herramientas.
  3. Bloques de acción posteriores (correo electrónico, base de datos, APIs de terceros) — ejecutan el plan.
  4. 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 + contextoEl cuerpo es JSON estructurado con campos fijos
El primer bloque es un LLM/agente que planificaEl primer bloque es una condición o acción de base de datos
El llamador es un sistema de IA o un chatbotEl llamador es un servicio que publica eventos
Quieres salvaguardas y límites de tasa por llamador de serieQuieres 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.