ClawOps Docs

Summary Webhook

통화 요약(Structured Output) 완료/실패 시 전송되는 Summary Webhook의 파라미터를 안내합니다.

Summary Webhook 은 통화 받아쓰기(transcript)가 완료된 뒤 LLM 이 생성한 구조화된 요약(Structured Output) 이 완료되거나 실패했을 때 설정된 URL 로 알림을 전송합니다. 요약 Job 은 transcript 가 완료된 직후 자동으로 실행되며, 계정 레벨에서 REST API 로 등록합니다.

Summary Webhook 을 받으려면 먼저 조직 설정 → 통화 받아쓰기요약(Summary) Add-on 이 모두 활성화되어 있어야 합니다. 요약은 받아쓰기가 완료된 통화에 한해 실행되며, 사용량 기반으로 과금되는 유료 기능입니다.

등록

POST /v1/accounts/{accountId}/webhooks

Body:
{
  "url": "https://my-app.com/summary-webhook",
  "events": ["summary.completed", "summary.failed"]
}

배송 로그 조회

SDK 로 웹훅 배송 로그를 확인할 수 있습니다.

page = client.webhook_logs.list("cmob6...", page=0, page_size=20)
for log in page.data:
    print(log)

이벤트 종류

파라미터타입필수설명
summary.completedevent선택요약 생성 완료 — SummaryJson 포함
summary.failedevent선택요약 생성 실패 — Stage/ErrorMessage 포함

요청 파라미터

모든 요청은 Content-Type: application/x-www-form-urlencoded POST 입니다. 이벤트마다 전달되는 파라미터가 다르니 아래 두 표를 참고하세요.

summary.completed

LLM 호출이 정상 종료되어 결과 JSON 이 DB 에 저장된 직후 전송됩니다.

파라미터타입필수설명
CallIdstring필수통화 ID
AccountIdstring필수계정 ID
Fromstring필수발신 번호
Tostring필수수신 번호
Directionstring필수통화 방향 (inbound, outbound)
Eventstring필수고정값 summary.completed
Timestampstring필수이벤트 발생 시각 (ISO 8601)
Providerstring필수요약에 사용된 LLM Provider (예: anthropic)
Modelstring필수요약에 사용된 모델 ID (예: claude-sonnet-4-6)
PromptVersionstring필수사용된 시스템 프롬프트 버전. 기본 default:v1, 조직 커스텀 프롬프트는 org:{accountId}:{hash}
SchemaVersionstring필수사용된 출력 스키마 버전. 기본 default:v1, 조직 커스텀 스키마는 org:{accountId}:{hash}
SummaryJsonstring필수요약 결과 JSON 을 string 으로 직렬화한 값. 수신 측에서 JSON.parse 로 파싱해서 사용
CallId=CAabc123&AccountId=ACxxx&From=%2B821011112222&To=%2B821033334444
&Direction=inbound&Event=summary.completed&Timestamp=2026-04-23T09:13:08.456Z
&Provider=anthropic&Model=claude-sonnet-4-6
&PromptVersion=default%3Av1&SchemaVersion=default%3Av1
&SummaryJson=%7B%22coreSummary%22%3A%22...%22%2C%22decisions%22%3A%5B%5D%2C%22followUps%22%3A%5B%5D%2C%22sentiment%22%3A%22neutral%22%7D

summary.failed

요약 Job 이 중단되어 결과가 생성되지 않았을 때 전송됩니다.

파라미터타입필수설명
CallIdstring필수통화 ID
AccountIdstring필수계정 ID
Fromstring필수발신 번호
Tostring필수수신 번호
Directionstring필수통화 방향 (inbound, outbound)
Eventstring필수고정값 summary.failed
Timestampstring필수이벤트 발생 시각 (ISO 8601)
Stagestring필수실패 단계. runtime(LLM 호출/스키마 검증 중 예외)
ErrorMessagestring필수사람 읽을 수 있는 오류 메시지
CallId=CAabc123&AccountId=ACxxx&From=%2B821011112222&To=%2B821033334444
&Direction=inbound&Event=summary.failed&Timestamp=2026-04-23T09:13:10.012Z
&Stage=runtime&ErrorMessage=schema+validation+failed

SummaryJson 형식

SummaryJson 은 조직이 등록한 출력 스키마(또는 기본 스키마)에 맞춰진 JSON 문자열입니다. 기본 스키마(default:v1) 를 사용하는 경우 다음 필드가 보장됩니다.

{
  "coreSummary": "고객이 환불 절차를 문의함. 7일 이내 처리 안내됨.",
  "decisions": ["환불 신청서 이메일 발송"],
  "followUps": ["배송 운송장 번호 확인 후 회신"],
  "sentiment": "neutral"
}
  • coreSummary — 핵심 요지 1~2 문장
  • decisions — 주요 합의/결정사항 배열 (없으면 빈 배열)
  • followUps — 후속 조치 배열 (없으면 빈 배열)
  • sentimentpositive / neutral / negative 중 하나

조직에서 커스텀 프롬프트나 스키마를 등록한 경우 PromptVersion / SchemaVersionorg:{accountId}:{hash} 형태로 전달되며, SummaryJson 의 필드도 등록한 스키마에 따라 달라집니다.

예제

from flask import Flask, request
import json

app = Flask(__name__)

@app.route("/summary-webhook", methods=["POST"])
def summary_webhook():
    event = request.form.get("Event")
    call_id = request.form.get("CallId")

    if event == "summary.completed":
        provider = request.form.get("Provider")
        model = request.form.get("Model")
        summary = json.loads(request.form.get("SummaryJson") or "{}")
        print(f"요약 완료 [{call_id}] ({provider}/{model})")
        print(f"  요지: {summary.get('coreSummary')}")
        for d in summary.get("decisions", []):
            print(f"  - 결정: {d}")
        for f in summary.get("followUps", []):
            print(f"  - 후속: {f}")

    elif event == "summary.failed":
        stage = request.form.get("Stage")
        err = request.form.get("ErrorMessage")
        print(f"요약 실패 [{call_id}] ({stage}): {err}")

    return "", 204

Summary Webhook 요청에도 X-Signature 헤더가 포함됩니다. 서명 검증 가이드를 참고하여 요청의 무결성을 확인하세요.

Summary Webhook 은 전달 보장(at-least-once) 방식이므로 드물게 같은 이벤트가 두 번 이상 도착할 수 있습니다. 수신 서버에서 CallId를 idempotency key 로 사용해 중복 처리를 방지하세요.