AICC Runtime API
게시한 에이전트에 사용자 메시지와 최근 대화 상태를 전달하고 JSON 또는 SSE로 답변을 받습니다.
에이전트 대화
API Key와 Agent ID는 서버에만 보관하고 브라우저에서는 고객 서버 프록시를 호출하세요.
URL
https://console.humelo.com/api/v1/agents/chat인증 및 헤더
API Key는 서버 환경변수에 보관하고 요청 헤더로만 전달하세요.
Authorization: Bearer {YOUR_API_KEY}
Content-Type: application/json
Accept: application/json # SSE는 text/event-stream요청 필드
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
agent_id | UUID | 필수 | 호출할 에이전트 ID입니다. 에이전트 빌더에서 확인할 수 있습니다. |
message | string | 조건부 | 이번 턴의 사용자 입력입니다. 생략하거나 공백이면 history 또는 messages의 마지막 비어 있지 않은 user 메시지를 사용합니다. 대체할 user 메시지가 없으면 E4201/400; 최대 4,000자 |
session_id | string | 선택 | 운영 로그에서 같은 상담을 묶을 고객 측 세션 ID입니다. 영문, 숫자, `.`, `_`, `:`, `-`만 사용; 1–160자 |
history | Turn[] | 선택 | 최근 대화입니다. 각 항목은 role과 content를 가지며 messages보다 우선합니다. 기본값 [] · 마지막 16턴 사용; role은 user 또는 assistant; content는 턴당 최대 4,000자 |
messages | Turn[] | 선택 | history와 같은 형식의 별칭입니다. history가 없을 때만 사용됩니다. 기본값 [] · 마지막 16턴 사용 |
state | object | null | 선택 | 이전 응답의 state를 그대로 전달하면 멀티턴 상태가 이어집니다. 기본값 null · JSON 문자열 기준 최대 16,000자 |
stream | boolean | 선택 | true면 Server-Sent Events로 응답합니다. Accept 헤더로도 활성화할 수 있습니다. 기본값 false |
요청 예시
{
"agent_id": "00000000-0000-0000-0000-000000000000",
"message": "예약 취소 수수료가 어떻게 되나요?",
"session_id": "customer-42:chat-7",
"history": [],
"state": null,
"stream": false
}응답
JSON 응답
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
agent_id | UUID | 필수 | 응답한 에이전트 ID입니다. |
agent_name | string | 필수 | 에이전트 이름입니다. |
response | string | 필수 | 최종 답변입니다. |
matched_intent | string | null | 필수 | 매칭된 의도 이름입니다. |
handoff_required | boolean | 필수 | 상담원 연결이 필요한지 나타냅니다. |
retrieved_context | object[] | 필수 | 답변에 사용한 지식 항목입니다. |
actions | object[] | 필수 | 실행한 에이전트 액션입니다. |
state | object | 필수 | 다음 요청에 다시 보낼 멀티턴 상태입니다. |
end_call | boolean | 필수 | 음성 채널에서 통화 종료가 필요한지 나타냅니다. |
runtime | object | 필수 | 응답 채널 메타데이터입니다. |
{
"agent_id": "00000000-0000-0000-0000-000000000000",
"agent_name": "라온투어 고객센터",
"response": "예약 조건에 따라 취소 수수료가 달라질 수 있습니다.",
"matched_intent": "패키지 취소료 기준",
"handoff_required": false,
"retrieved_context": [],
"actions": [],
"state": { "topic": "cancellation_fee", "handoff": false },
"end_call": false,
"runtime": { "mode": "text", "voice_engine": "DIVE" }
}SSE 응답
stream이 true이거나 Accept가 text/event-stream이면 start, chunk, 선택적인 tool_call, done 순서로 전송됩니다. 실패 시 error 이벤트로 종료됩니다.
Content-Type: text/event-stream; charset=utf-8
Cache-Control: no-cache, no-transform
X-Accel-Buffering: no| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
start | event | 필수 | 의도, 핸드오프, 검색 지식, 초기 state입니다. |
chunk | event | 필수 | 화면에 이어 붙일 delta 문자열입니다. |
tool_call | event | 선택 | 도구 실행이 공개될 때의 이름과 인자입니다. |
done | event | 필수 | 사용량 정산까지 성공한 뒤 보내는 최종 response, actions, state, end_call입니다. |
error | event | 조건부 | 스트림 처리 실패 시 오류 메시지입니다. |
E4201 · 잘못된 요청
agent_id가 없거나, message와 history/messages의 user 입력이 모두 비어 있거나, 필드 형식이 잘못된 경우입니다. 예약·과금·provider 호출 전에 거절됩니다.
{
"error": "message or a user message in history is required",
"code": "E4201"
}E4001 / E4002 · 인증 오류
Bearer API Key가 없거나 유효하지 않습니다.
E4601 · 크레딧 부족
최대 예상 사용량을 예약할 크레딧이 부족합니다.
E4301 · 에이전트 없음
API Key 조직에서 agent_id를 찾을 수 없습니다.
E4302 · 게시 버전 없음
에이전트에 사용할 수 있는 게시 버전이 없습니다.
E4204 · 요청 크기 초과
요청 body 또는 state가 허용 크기를 초과했습니다.
E4403 · 호출 제한 초과
API Key 기준 분당 60회 제한을 초과했습니다.
E5001 / E5002 · 서버 또는 일시적 서비스 오류
E5002는 backoff 후 제한적으로 재시도할 수 있습니다. 실패한 요청의 최대 예약분은 정산 전에 환급되며, SSE는 정산 실패 시 done 대신 error 이벤트로 종료됩니다.
- 요청 body는 최대 64,000 bytes이며 API Key별 호출 제한은 분당 60회입니다.
- message와 각 history content는 앞뒤 공백을 제거한 뒤 최대 길이까지만 사용합니다.
- message와 history/messages의 user 입력이 모두 비어 있으면 E4201/400이며 사용량 예약, provider 호출, 런타임 로그가 발생하지 않습니다.
- session_id가 허용 패턴과 맞지 않으면 요청은 처리되지만 세션 ID는 기록되지 않습니다.
연동 흐름
에이전트 빌더
문서와 지침으로 에이전트 지식과 응대 방식을 만들고 검수합니다.
배포
검수한 에이전트 지식을 런타임에서 사용할 버전으로 게시합니다.
API Key 발급
서버에서 사용할 API Key와 Agent ID를 안전하게 보관합니다.
서버 프록시 연결
브라우저와 앱은 고객 서버를 호출하고 고객 서버가 Prosody를 호출합니다.
스트리밍 요청
채팅 UI에서는 SSE chunk의 delta를 이어 붙이고, done 이벤트의 state를 저장해 다음 요청에 다시 보내세요.
curl https://console.humelo.com/api/v1/agents/chat \
-N \
-H "Authorization: Bearer ${PROSODY_API_KEY}" \
-H "Content-Type: application/json" \
-H "Accept: text/event-stream" \
-d '{
"agent_id": "00000000-0000-0000-0000-000000000000",
"message": "환불은 얼마나 걸리나요?",
"session_id": "customer-42:chat-7",
"stream": true
}'서버 프록시 패턴
private API Key는 브라우저에 넣지 않습니다. 브라우저는 고객 서버를 호출하고 고객 서버가 Prosody API를 호출합니다.
// app/api/agent/chat/route.ts
export async function POST(request: Request) {
const body = await request.json();
const response = await fetch("https://console.humelo.com/api/v1/agents/chat", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.PROSODY_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
agent_id: process.env.PROSODY_AGENT_ID,
message: body.message,
session_id: body.sessionId,
history: body.history ?? [],
state: body.state ?? null,
stream: false,
}),
});
return new Response(await response.text(), {
status: response.status,
headers: {
"Content-Type": response.headers.get("Content-Type") ?? "application/json",
},
});
}type Turn = { role: "user" | "assistant"; content: string };
let history: Turn[] = [];
let state: Record<string, unknown> | null = null;
async function sendToAgent(message: string) {
const response = await fetch("/api/agent/chat", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ message, history, state }),
});
if (!response.ok) throw new Error("Agent is temporarily unavailable");
const result = await response.json();
history = [
...history,
{ role: "user", content: message },
{ role: "assistant", content: result.response },
].slice(-16);
state = result.state ?? state;
return result;
}- 최근 8~16턴 정도의 history를 보냅니다.
- 응답의 state를 고객 상담 세션 단위로 저장합니다.
- 새 상담을 시작할 때 history와 state를 초기화합니다.
- API Key는 서버 환경변수나 secret manager에만 둡니다.
- 프록시에 자체 인증, origin, rate limit 정책을 둡니다.
- 고객 정보 저장 정책에 맞춰 transcript를 마스킹합니다.