레시피

주간 보고서 보내기

분석 API를 바탕으로 매주 월요일 아침에 스케줄로 만드는 보고서.

매주 월요일 도쿄 시간 09:00에 분석 API에서 지난주 수치를 읽어 짧은 보고서를 작성하고 Slack이나 이메일로 보냅니다. 에이전트는 GET만 허용하는 연결을 통해 읽으므로, 수치를 볼 수는 있어도 바꿀 수는 없습니다.

실행은 약 10초가 걸립니다. 비용의 대부분은 초당 $0.0002로 청구되는 컴퓨팅이므로, 한 달에 네 번 실행해도 약 1센트입니다. 모델 사용량은 해당 모델의 자체 가격으로 청구되며 선택한 모델에 따라 달라지므로, 처음 몇 번의 실행에서 cost_micros를 확인하세요.

  1. 필요한 것 준비

    • admin 역할의 API 키입니다. 연결과 스케줄은 소유자와 관리자만 만들 수 있기 때문입니다. 역할과 키를 참고하세요.
    • HTTPS로 접근하는 분석 API와 그 API의 읽기 전용 키입니다. 이 레시피는 GET /metrics?period=…가 있다고 가정하며, period는 last_week 또는 2026-W40 같은 ISO 주차입니다. 경로는 사용하는 API에 맞게 바꾸세요.
    • Slack 수신 웹훅 URL 또는 이메일을 보내는 직접 운영하는 엔드포인트입니다.
  2. 읽기 전용 연결 만들기

    연결은 API 키를 Ephemeral 안에 보관하고 GET만 허용합니다. instructions는 에이전트에게 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. 워크플로 저장

    프롬프트는 실행의 입력에서 기간을 읽습니다. 에이전트는 신뢰할 수 있는 달력이 없으므로, 날짜를 계산하게 하는 대신 last_week처럼 API가 해석할 수 있는 기간을 전달하세요.

    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
      }'

    web 설정이 없으므로 실행은 인터넷에 전혀 접근하지 못하며, 닿을 수 있는 곳은 분석 연결뿐입니다. 워크플로는 input, 예산, 콜백을 가질 수 없으며 이들은 각 실행과 함께 전달됩니다.

  4. 월요일 아침으로 스케줄 지정

    0 9 * * 1은 월요일 09:00이며, 스케줄의 timezone 기준으로 해석됩니다. 스케줄의 input은 스케줄이 시작하는 모든 실행이 받는 값이므로, 기간은 여기서 지정합니다. 먼저 미리 봅니다.

    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" }'

    시각은 UTC입니다. 00:00 UTC는 도쿄의 09:00입니다. 스케줄을 만듭니다.

    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
      }'

    예산 $0.30는 시작할 때마다 예약되고 실행이 정산되면 해제됩니다. 입력은 스케줄이 가지고 있으므로, 같은 워크플로에 다른 입력의 스케줄을 추가하거나 나중에 PATCH /v1/schedules/{id}와 새 input으로 이 스케줄을 바꿀 수 있습니다. 월요일 전에 동작을 확인하려면 POST /v1/schedules/{id}/run 또는 ephemeral schedules run ID로 지금 하나 시작하세요.

  5. 보고서 전달

    스케줄된 실행은 콜백을 보내지 않으므로, 결과를 직접 가져와 전달합니다. cron이나 CI에서 10분마다 실행하는 이 스크립트는 스케줄의 가장 최근에 성공한 실행을 조회해 output을 한 번만 보내고 실행 ID를 기억합니다. 이메일을 원하면 Slack 호출을 메일 서비스 호출로 바꾸세요.

    report.mjs (Node.js 18 이상)
    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 }));

    실패한 실행은 아무것도 보내지 않으므로, 보고서가 빠져도 알아채지 못하는 일이 없도록 GET /v1/runs?schedule={id}&status=failed&limit=1도 확인하거나 스케줄의 last_error를 살펴보세요.

  6. 지난 주의 보고서 다시 실행

    "지금 시작"은 스케줄의 입력을 그대로 사용하므로, 다른 주의 보고서는 원하는 기간으로 워크플로를 직접 시작하세요. 이번에는 서명된 콜백을 요청할 수 있으며, 결과가 준비되는 즉시 엔드포인트로 전달됩니다. 주차가 드러나는 멱등성 키를 사용하면 같은 요청을 반복해도 보고서가 두 번 전송되지 않습니다.

    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"'"
        }
      }'

    콜백 엔드포인트는 서명을 검증하고 run.output을 전달합니다. 수신기는 결제 조사 레시피에 있습니다. 이렇게 시작한 실행에는 스케줄의 ID가 없으므로 ?schedule= 조회에는 나타나지 않습니다.

알아 두면 좋은 점

주제동작
시간대시각은 스케줄의 timezone 기준으로 해석되므로, 09:00으로 설정한 보고서는 서머타임이 바뀌어도 현지 시각 09:00을 유지합니다.
놓친 시작09:00에 Ephemeral을 사용할 수 없었다면, 복구된 후 보고서를 한 번 실행하고 이후에는 시간표를 따릅니다.
중복 실행skip_if_running이 켜져 있으면 이전 실행이 아직 진행 중일 때 시작을 건너뜁니다.
일시 중지휴일 전에는 ephemeral schedules pause ID를, 휴일 후에는 resume을 사용하세요.
안전한 이유
연결은 GET만 허용하며, 키는 microVM에 전달되지 않습니다. 워크플로에는 웹 액세스도 셸도 없으므로 실행은 분석 API를 읽을 수만 있고 그 밖의 일은 할 수 없습니다. 예산은 각 실행을 $0.30로 제한합니다. 읽기 전용 분석 키를 사용하면 연결이 있어도 쓰기는 불가능합니다.
© 2026 Ephemeral제작: erni.works
esc

“”와(과) 일치하는 항목이 없습니다.