통화 컨텍스트 (CallContext)
통화 한 건에만 적용할 지시와 변수를 에이전트에 주입하는 CallContext. 발신은 요청 본문으로, 착신은 응답 전 조회 webhook 으로 전달합니다.
CallContext 는 저장된 에이전트 설정을 건드리지 않고 이 통화 한 건에만 적용할 지시와 변수입니다. 같은 에이전트가 상대가 누구냐에 따라 다르게 말해야 할 때 씁니다 — 예약 확인 전화에서 예약 시각을 알려 주거나, 걸려온 번호로 고객을 찾아 이전 상담 내용을 들려주는 식입니다.
주입 경로는 셋입니다.
| 경로 | 전달 방법 | 시점 |
|---|---|---|
| 발신 (outbound) | 발신 요청 본문의 CallContext 필드 | 발신을 거는 순간 |
| 배치 발신 | 명단의 수신자별 Tasks[].Variables | 그 수신자에게 걸 때 |
| 착신 (inbound) | 번호에 등록한 callContextUrl 로 ClawOps 가 조회 | 전화를 받기 직전 |
어느 경로든 결과는 같습니다 — 그 통화의 에이전트 지시문 뒤에 지시와 변수가 덧붙습니다. 저장된 에이전트 설정은 바뀌지 않으므로, 동시에 진행되는 다른 통화에 내용이 새지 않습니다.
페이로드
모든 경로가 같은 모양을 씁니다(배치는 이 중 Variables 만 씁니다).
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
| Instruction | string | 선택 | 이 통화에만 적용할 지시. 4,000자 이내. 데이터만 넘길 때는 생략합니다. |
| Variables | object | 선택 | 이 통화에만 쓸 데이터. 최대 50개, 직렬화 후 8KB 이내. |
Instruction·Variables 중 하나는 있어야 합니다. 둘 다 비어 있으면 형식 위반입니다.
Variables 의 이름은 [A-Za-z_][A-Za-z0-9_]* 형식이어야 합니다. 값은 문자열·숫자·불리언을 받아 문자열로 저장합니다.
{
"Instruction": "이 고객은 어제 배송 지연으로 문의한 이력이 있습니다. 먼저 사과하고 현재 배송 상태를 안내하세요.",
"Variables": {
"customer_name": "김지은",
"order_id": "ORD-20260812-001",
"delayed_days": 2
}
}발신 — 요청 본문으로
발신 API 본문에 CallContext 를 넣습니다.
POST /v1/accounts/{accountId}/calls
Body:
{
"To": "01012345678",
"From": "07011112222",
"AgentId": "ag_...",
"CallContext": {
"Instruction": "예약 확인 전화입니다. 예약 시각을 안내하고 변경 의사를 물어보세요.",
"Variables": { "reserved_at": "8월 14일 오후 3시" }
}
}형식이 잘못되면 발신이 400 으로 거절됩니다 — 잘못된 컨텍스트로 통화가 나가는 일은 없습니다.
에이전트에게 어떻게 보이나
지시와 변수는 저장된 에이전트 지시문 뒤에 이렇게 붙습니다. 지시를 생략하면 [이번 통화의 요청] 절 없이 데이터만 붙습니다.
<저장된 에이전트 지시문>
[이번 통화의 요청]
예약 확인 전화입니다. 예약 시각을 안내하고 변경 의사를 물어보세요.
[이번 통화의 데이터]
{"reserved_at":"8월 14일 오후 3시"}에이전트 지시문에는 {{변수}} 치환이 없습니다(콜 플로우·문자와 다릅니다). 지시문에 {{customer_name}} 이라고 쓰면
그 글자가 그대로 모델에 갑니다. 「데이터의 customer_name 으로 고객을 부르세요」처럼 변수 이름으로 가리키세요.
배치 발신 — 명단의 Variables 로
배치 발신을 AgentId 로 만들면, 수신자마다 넣은 Tasks[].Variables 가 그 통화의
CallContext.Variables 로 전달됩니다. 대시보드에서 명단 열을 변수로 매핑한 경우도 같습니다.
POST /v1/accounts/{accountId}/call-batches
Body:
{
"Name": "10월 재주문 안내",
"From": "07011112222",
"AgentId": "ag_...",
"Tasks": [
{
"To": "0212345678",
"Variables": { "company": "(주)한빛", "contact_name": "김지은 과장" }
},
{
"To": "0312223333",
"Variables": { "company": "대성정밀", "contact_name": "박민수 대리" }
}
]
}배치에는 수신자별 Instruction 이 없습니다. 모든 수신자에게 같은 지시는 에이전트 지시문에 적고,
수신자마다 다른 것은 Variables 로 넘기세요. Variables 가 없는 수신자는 컨텍스트 없이 저장된
에이전트 그대로 통화합니다.
착신 — 조회 webhook 으로
착신은 거는 쪽이 우리가 아니라 고객이라, 발신처럼 미리 실어 보낼 수 없습니다. 대신 번호에 조회 endpoint 를 등록해 두면, 전화가 오는 순간 ClawOps 가 그 주소로 물어봅니다.
등록
대시보드에서는 번호 상세 → 인바운드 라우팅 → 에이전트 를 고른 뒤 통화 컨텍스트 URL 에 입력합니다.
REST 로도 설정할 수 있습니다.
PUT /v1/accounts/{accountId}/numbers/{number}
Body:
{
"callContextUrl": "https://my-app.com/clawops/call-context"
}callContextUrl 은 routingType 이 agent 인 번호에서만 사용할 수 있습니다. 라우팅을
에이전트가 아닌 값으로 바꾸면 이 설정도 함께 해제됩니다.
요청
Content-Type: application/x-www-form-urlencoded POST 입니다.
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
| CallId | string | 필수 | 통화 ID |
| AccountId | string | 필수 | 계정 ID |
| From | string | 필수 | 발신자 번호 — 고객을 식별할 때 쓰는 값 |
| To | string | 필수 | 착신된 우리 번호 |
| ForwardedFrom | string | 선택 | 착신전환으로 들어온 통화에서 발신자가 원래 건 번호 — 여러 번호를 우리 번호 하나로 착신전환했을 때 어느 번호로 걸려왔는지에 따라 다른 컨텍스트를 돌려줄 수 있습니다. 착신전환을 실행한 통신사가 전환 정보를 함께 보내온 경우에만 실립니다 |
| CallerIdRestricted | string | 필수 | 발신자가 번호 표시제한(`*23#` 등)을 걸고 건 통화면 `true`, 아니면 `false`. 번호는 `From` 에 그대로 전달되고, 표시제한 여부만 이 값으로 알려 드립니다. 통신사가 표시제한 여부를 보내지 않은 통화는 `false` 로 올 수 있습니다 — 발신자가 번호를 숨기려 한 통화에 다르게 응대하려면 이 값으로 가르세요 |
| CallStatus | string | 필수 | 항상 `ringing` — 아직 전화를 받기 전입니다 |
| Direction | string | 필수 | 항상 `inbound` |
요청에는 다른 webhook 과 같은 X-Signature 헤더가 실립니다. 검증 방법은
서명 검증 을 참고하세요.
응답
CallContext 를 담은 JSON 을 돌려주세요.
{
"CallContext": {
"Instruction": "이 고객은 VIP 입니다. 대기 없이 바로 담당자에게 연결하세요.",
"Variables": { "customer_name": "김지은", "tier": "vip" }
}
}줄 컨텍스트가 없으면 빈 본문으로 응답하세요. 정상으로 처리되며, 저장된 에이전트 설정만으로 통화가 진행됩니다.
Instruction·Variables 를 응답 최상위에 올리지 마세요. 반드시 CallContext 로 한 겹 감싸야
합니다. 이 연동에서 가장 흔한 실수이고, 200 을 받은 채로 지시만 조용히 빠진 것처럼 보입니다.
감싸지 않은 응답은 「컨텍스트 없음」이 아니라 형식 위반으로 판정해 실패로 기록합니다.
// ❌ 지시가 실리지 않습니다
{ "Instruction": "...", "Variables": {} }// ✅ CallContext 로 감쌉니다
{ "CallContext": { "Instruction": "...", "Variables": {} } }실패해도 통화는 진행됩니다
이 조회는 통화를 막지 않습니다. 아래 경우 모두 컨텍스트 없이 통화가 그대로 이어집니다.
- 응답이 없거나 타임아웃 (10초)
- 2xx 가 아닌 상태 코드
- JSON 파싱 실패, 형식 위반 (
Instruction·Variables가 둘 다 없음 등)
컨텍스트가 통화 품질에 필수라면, 이 fail-open 동작을 전제로 설계하세요 — 조회가 실패한 통화도 에이전트는 정상적으로 응대합니다.
이 조회는 전화를 받기 전에 동기로 일어납니다. 응답이 느리면 그만큼 발신자가 듣는 링백이 길어집니다. 무거운 조회는 미리 캐시해 두고, 이 endpoint 는 빠르게 응답하도록 만드세요.
성공·실패 모두 통화 이벤트로 기록됩니다. 대시보드 통화 기록 → 통화 상세 의 이벤트 타임라인에서
「통화 컨텍스트 조회」(hasContext 가 컨텍스트를 실제로 받았는지 나타냅니다)와
「통화 컨텍스트 조회 실패」(error 에 판정 사유)를 확인하세요.
통화 이벤트 조회 API 로도 같은 항목이 내려갑니다.
그 밖의 제약
- 응답 본문은 1MB 까지 받습니다.
- 리다이렉트는 따라가지 않습니다 — 최종 주소를 직접 등록하세요.
- 공개된 HTTP(S) 주소만 등록할 수 있습니다(내부·사설 IP 차단).