Recetas

Enviar un informe semanal

Un informe del lunes por la mañana desde tu API de analítica, con una programación.

Cada lunes a las 09:00 en Tokio, lee las cifras de la semana pasada de tu API de analítica, escribe un informe breve y envíalo a Slack o por correo. El agente lee a través de una conexión que solo permite GET, así que puede ver tus números pero no cambiarlos.

La ejecución dura unos 10 segundos. La mayor parte del coste es el cómputo, que se factura a $0.0002 por segundo, así que cuatro ejecuciones al mes cuestan alrededor de un centavo. La parte del modelo depende del modelo que elijas; lee cost_micros en las primeras ejecuciones para verla.

  1. Reúne lo que necesitas

    • Una clave de API con el rol de administrador, porque solo los propietarios y administradores crean conexiones y programaciones. Consulta roles y claves.
    • Tu API de analítica por HTTPS y una clave de solo lectura para ella. Esta receta supone que tiene GET /metrics?period=…, donde period es last_week o una semana ISO como 2026-W40. Ajusta las rutas a tu API.
    • Una URL de webhook entrante de Slack, o un endpoint tuyo que envíe correo.
  2. Crea la conexión de solo lectura

    La conexión mantiene la clave de la API dentro de Ephemeral y permite solo GET. Las instructions le indican al agente qué ofrece la API.

    curl -X PUT $EPHEMERAL_URL/v1/connections/analytics-api \
      -H "Authorization: Bearer $EPHEMERAL_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "type": "http",
        "url": "https://analytics.example.com/v2",
        "auth": { "type": "header", "header": "X-API-Key", "token": "an_live_…" },
        "allowed_methods": ["GET"],
        "instructions": "GET /metrics?period=last_week or period=2026-W40 returns signups, active_users, revenue_cents and churned_accounts for that ISO week, with the same figures for the week before. Amounts are in cents."
      }'
  3. Guarda el flujo de trabajo

    El prompt lee el periodo de la entrada de la ejecución. El agente no dispone de un calendario fiable, así que pasa un periodo que tu API pueda resolver, como last_week, en lugar de pedirle al agente que calcule fechas.

    curl -X PUT $EPHEMERAL_URL/v1/workflows/weekly-report \
      -H "Authorization: Bearer $EPHEMERAL_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "prompt": "Write the weekly business report for input.period. Call GET /metrics?period=<input.period> on the analytics connection and use only what it returns. Reply in Markdown, at most 150 words: a one-line headline, then signups, active users, revenue in dollars and churned accounts, each with the change from the week before. If the call fails, say so instead of estimating.",
        "connections": { "analytics": { "ref": "analytics-api", "allowed_methods": ["GET"] } },
        "shell": false,
        "timeout_seconds": 120
      }'

    No hay ningún ajuste web, así que la ejecución no tiene acceso a internet en absoluto; su único alcance es la conexión de analítica. Un flujo de trabajo no puede contener input, un presupuesto ni un callback; esos vienen con cada ejecución.

  4. Prográmalo para el lunes por la mañana

    0 9 * * 1 son las 09:00 de los lunes, interpretadas en la timezone de la programación. El input de la programación es lo que recibe cada ejecución que inicia, así que aquí es donde defines el periodo. Previsualízala primero.

    curl -X POST $EPHEMERAL_URL/v1/schedules/preview \
      -H "Authorization: Bearer $EPHEMERAL_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{ "cron": "0 9 * * 1", "timezone": "Asia/Tokyo" }'

    Las horas están en UTC: las 00:00 UTC son las 09:00 en Tokio. Crea la programación:

    curl -X POST $EPHEMERAL_URL/v1/schedules \
      -H "Authorization: Bearer $EPHEMERAL_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "workflow": "weekly-report",
        "name": "Monday report",
        "cron": "0 9 * * 1",
        "timezone": "Asia/Tokyo",
        "input": { "period": "last_week" },
        "max_cost_micros": 300000
      }'

    El presupuesto de $0.30 se reserva en cada inicio y se libera cuando la ejecución se liquida. Como la entrada pertenece a la programación, puedes añadir otra programación sobre el mismo flujo de trabajo con una entrada distinta, o cambiar esta más adelante con PATCH /v1/schedules/{id} y un input nuevo. Para verla funcionar antes del lunes, inicia una ahora con POST /v1/schedules/{id}/run o ephemeral schedules run ID.

  5. Entrega el informe

    Las ejecuciones programadas no envían callbacks, así que la entrega se hace recogiendo el resultado. Este script, ejecutado cada diez minutos desde cron o CI, pide la ejecución con éxito más reciente de la programación, envía su salida una sola vez y recuerda el ID de la ejecución. Sustituye la llamada a Slack por una llamada a tu servicio de correo si prefieres email.

    report.mjs (Node.js 18 or later)
    import { readFile, writeFile } from "node:fs/promises";
    
    const { EPHEMERAL_URL, EPHEMERAL_API_KEY, SCHEDULE_ID, SLACK_WEBHOOK_URL } = process.env;
    const stateFile = "report-state.json";
    const { sent } = JSON.parse(await readFile(stateFile, "utf8").catch(() => "{}"));
    
    const response = await fetch(`${EPHEMERAL_URL}/v1/runs?schedule=${SCHEDULE_ID}&status=succeeded&limit=1`, {
      headers: { Authorization: `Bearer ${EPHEMERAL_API_KEY}` },
    });
    if (!response.ok) throw new Error(`Ephemeral returned ${response.status}`);
    const [run] = (await response.json()).items;
    if (!run || run.id === sent) process.exit(0); // nothing new since the last report
    
    await fetch(SLACK_WEBHOOK_URL, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ text: run.output }),
    });
    await writeFile(stateFile, JSON.stringify({ sent: run.id }));

    Una ejecución que falló no envía nada, así que consulta también GET /v1/runs?schedule={id}&status=failed&limit=1, o vigila el last_error de la programación, para que un informe ausente no pase desapercibido.

  6. Repite un informe de una semana pasada

    "Iniciar ahora" reutiliza la entrada de la programación, así que para otra semana inicia el flujo de trabajo directamente con el periodo que quieras. Esta vez puedes pedir un callback firmado, que entrega el resultado a tu endpoint en cuanto está listo. Usa una clave de idempotencia que nombre la semana, para que una solicitud repetida nunca envíe un segundo informe.

    curl $EPHEMERAL_URL/v1/runs \
      -H "Authorization: Bearer $EPHEMERAL_API_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: weekly-report-2026-W38" \
      -d '{
        "workflow": "weekly-report",
        "input": { "period": "2026-W38" },
        "max_cost_micros": 300000,
        "callback": {
          "url": "https://example.com/hooks/ephemeral",
          "secret": "'"$EPHEMERAL_CALLBACK_SECRET"'"
        }
      }'

    Tu endpoint de callback verifica la firma y reenvía run.output; el receptor está en la receta de investigar un pago. Una ejecución iniciada así no lleva el ID de la programación, por lo que no aparece en ?schedule=.

Conviene saber

TemaComportamiento
Zona horariaLas horas se interpretan en la timezone de la programación, así que un informe fijado a las 09:00 se mantiene a las 09:00 hora local en los cambios de horario de verano.
Inicios perdidosSi Ephemeral no estaba disponible a las 09:00, el informe se ejecuta una vez al volver, y después el calendario continúa.
SolapamientoCon skip_if_running activado, un inicio se omite mientras la ejecución anterior sigue en marcha.
Pausarephemeral schedules pause ID antes de unas vacaciones y resume después.
Por qué es seguro
La conexión permite solo GET, y la clave nunca llega a la microVM. El flujo de trabajo no tiene acceso web ni shell, así que la ejecución puede leer tu API de analítica y nada más. El presupuesto limita cada ejecución a $0.30. Usa una clave de analítica de solo lectura, para que ni siquiera la conexión pudiera escribir.
© 2026 EphemeralProducido por erni.works
esc

Nada coincide con “”.