팀카이의 KaiCX 는 고객사 고객센터를 AI 로 바꾸는 제품이고, FDE 는 한 고객사 instance 를 운영 지표가 움직일 때까지 책임지는 직무입니다. 문의 본문에서 답 초안과 에스컬레이션 판단을 만들고 자동해결률로 검증하는 이 사슬은, 고객센터 운영이라는 팀카이 고유의 데이터(문의 카테고리·응대 정책·상담사 검수)가 있어야 의미가 있습니다. 게다가 한 instance 의 재사용 코어와 도메인 로직을 분리하는 구조는 ‘현장 패턴을 제품으로 흡수’ 한다는 팀카이 작동 원리와 그대로 맞물립니다.
FDE 는 한 고객사의 에이전트를 직접 빌드해 운영 지표를 실제로 움직일 때까지 책임집니다. 도메인·시스템·정책에 맞춘 1개 instance 가 끝까지 도는 한 바퀴가 핵심입니다.
‘인간의 노동을 AI 에 위임’ 이 제품 문제의식입니다. 자동해결률·에스컬레이션 정확도 같은 운영 지표를 정의하고 매일 추적하는 구조가 있어야 ‘지표를 움직였다’ 가 증명됩니다.
고객사 현장에서 발견한 패턴을 팀 전체가 학습으로 흡수합니다. 한 instance 의 도메인 로직과 재사용 코어를 분리해 다음 고객사로 빠르게 옮기는 설계가 직무 적합성을 보여줍니다.
고객센터 문의 로그(채널·카테고리·본문)에 지식문서·응대 정책을 붙여 한 화면에서 봅니다. AI 에이전트가 답 초안과 ‘사람에게 넘길지’ 판단을 만들고, 자동해결률·에스컬레이션 정확도를 매일 아침 슬랙으로 리포트합니다. 1주차만으로 한 고객사용 instance 완성품이고, 답이 실제로 맞았는지 검수 확인(2주차)·응대 시간 절감(3주차)으로 단계적으로 키웁니다. 근거는 채용공고 정렬이고, 데이터는 작성자가 만든 더미입니다.
팀카이 FDE. 한 고객사에 들어가 에이전트를 빌드하면서, 답 초안을 매번 손으로 다듬고 ‘이건 사람이 봐야 하나’ 를 감으로 판단하는 상황을 끝내고, 그 판단이 실제로 맞았는지까지 확인하고 싶은 사람입니다.
문의·지식문서·응대 정책을 한 스키마로 묶으면, AI 에이전트가 (a) 답 초안과 (b) 에스컬레이션 여부를 몇 초 안에 답하고, (c) 상담사 실제 처리 결과로 그 판단이 맞았는지 확인합니다.
문의·지식문서·정책을 한곳에 모아, AI 에이전트가 답 초안과 사람 인계 여부를 만들고 자동해결률을 매일 아침 슬랙으로 보내는 한 고객사용 instance 입니다. 입력은 상담 시스템 실연동이 아니라 티켓을 내보낸 CSV/JSON(메타데이터)을 가정해, 사내망·CTI 연동 없이 1주에 혼자 완결합니다.
에이전트가 자동해결로 판단한 문의가 실제로 재문의 없이 끝났는지 다음 기간 실측과 맞춰보고, 상담사 검수자 2명이 답 초안이 타당한지 라벨링해 신뢰도를 보여주는 대시보드입니다.
확인된 판단을 바탕으로, 답이 확실한 문의는 자동 종결하고 애매한 문의만 사람에게 라우팅해, 자동해결률과 평균 응대 시간을 함께 개선하는 단계입니다.
실제 고객센터 문의 시나리오 10개를 넣으면, 답 초안과 사람 인계 여부 판단이 근거 문서와 함께 몇 초 안에 나오는 걸 시연합니다
일부러 만든 악성·결측 입력 30종(빈 본문·정책 충돌·미등록 카테고리)을 넣어도 출력 형식(스키마)이 한 번도 안 깨집니다. 형식 검증(Zod) 자동 통과를 보여줍니다
매일 아침 슬랙으로 자동해결률 리포트가 자동 발송되는 걸 14일치 시연으로 보여줍니다
내가 만든 정답 30개 중 에스컬레이션 판단이 일치한 게 24개(80%)입니다. 단, 정답과 데이터를 모두 작성자가 만든 합성 기준이라 ‘성능 검증’ 이 아니라 ‘데모 조건에서의 동작’ 임을 명시합니다
위 수치는 전부 작성자가 만든 더미데이터 자가채점이며, 실제 자동해결률·검수 일치도는 팀카이 고객사 실 상담 데이터 + 실 상담사 검수가 있어야 측정 가능합니다. 이 에이전트는 그 검증을 바로 돌릴 수 있는 상태까지 만듭니다.
이건 고객·실데이터 없이 혼자 만든 포트폴리오입니다. 모든 수치는 합성 데이터 자가채점이라 ‘성능 증명’ 이 아닙니다. 면접에서 솔직히 ‘데모 조건 동작 + 실검증 준비 상태’ 로 설명하는 게 오히려 신뢰를 줍니다
정답을 작성자가 만들었으니 잘 맞는 게 당연합니다. 그래서 일부러 헷갈리는 결측·악성·경계 케이스(정책 충돌 문의·빈 본문)를 더미에 섞어, 쉬운 문제만 푸는 게 아님을 보여줍니다
‘이 문의는 자동해결 가능’ 이 과확신일 수 있습니다. 환불·개인정보 같은 정책 민감 문의는 강제로 사람에게 인계하고 별도 LLM 검사로 우회 자동응답까지 거릅니다
문의 카테고리 표기가 채널마다 제각각입니다. 카테고리 유사도 + 정책 필터로 같은 유형으로 묶고, 못 묶은 건 추측하지 말고 ‘미매핑’ 으로 알립니다
실제 도입 시 달라지는 것을 명시합니다. 고객사별 실 문의 분포·지식문서·정책은 더미와 다르므로 기준폭·보정값을 다시 맞춰야 하고, 검수도 실 상담사로 교체해야 합니다(도입 단계 과제로 분리)
① 인라인 샘플 · ② seed.json 다운로드 · ③ 증강 프롬프트. 세 층 모두 동일한 schema 에서 파생.
채널·카테고리·본문 단위 고객센터 문의 로그입니다. 에이전트가 가장 먼저 질의하는 테이블입니다. 운영 현실대로 결측(본문 누락·만족도 미응답)·미등록 신규 카테고리·표기 별칭·경계값(빈 본문)을 일부러 섞어, 쉬운 데이터만 푸는 게 아님을 보여줍니다.
| ticket_id | date | channel | category_raw | category_id | body | reopened | csat_1to5 |
|---|---|---|---|---|---|---|---|
| T0001 | 2026-03-04 | chat | 배송조회 | c_delivery | 주문한 상품 언제 도착하나요? | false | 5 |
| T0002 | 2026-03-04 | 환불요청 | c_refund | 결제 취소하고 환불받고 싶어요. | false | 4 | |
| T0003 | 2026-03-04 | app | 배송 문의 | c_delivery | 송장번호가 안 떠요 | true | 2 |
| T0004 | 2026-03-05 | chat | 반품/교환 | c_return | 사이즈가 안 맞아서 교환하고 싶습니다 | false | 4 |
| T0005 | 2026-03-05 | voice | 개인정보 변경 | c_account | — | false | — |
아래 Zod 스키마에 맞는 고객센터 문의 로그 14일치(2주) JSON 배열로 생성하세요. 채널 4종(chat/email/voice/app), 카테고리 분포 포함.
z.object({ ticket_id: z.string(), date: z.string(), channel: z.enum(["chat","email","voice","app"]), category_raw: z.string(), category_id: z.string().nullable(), body: z.string().nullable(), reopened: z.boolean().nullable(), csat_1to5: z.number().nullable() })
쉬운 데이터만 만들지 말 것. 다음 하드 케이스를 의도적으로 섞어라(쉬운 문제만 푸는 함정 회피): (1) 같은 카테고리의 별칭 표기 혼입(category_raw '배송 문의'→category_id c_delivery, '환불'→c_refund 처럼 정규화돼야 함), (2) 미등록 신규 카테고리(category_id=null) 2~3건, (3) 결측. body/csat_1to5 가 null 인 행 각 1~2건(본문 누락·만족도 미응답), (4) 경계값 빈 본문(body="")·반복문의(reopened=true) 각 2건, (5) 정책 민감 문의(환불·개인정보삭제)는 반드시 포함. JSON 배열만.z.object({ ticket_id: z.string(), date: z.string(), channel: z.enum(["chat","email","voice","app"]), category_raw: z.string(), category_id: z.string().nullable(), body: z.string().nullable(), reopened: z.boolean().nullable(), csat_1to5: z.number().nullable() })에이전트가 답 초안의 근거로 인용하는 지식문서입니다. RAG 검색 대상이고, 같은 주제가 여러 표기로 들어와 별칭 정규화가 필요합니다.
주문 후 마이페이지 > 주문내역에서 송장번호와 배송 현황을 확인할 수 있습니다. 출고 후 평균 2~3일 소요됩니다.
단순 변심 환불은 수령 후 7일 이내 가능하며, 환불은 결제 수단으로 영업일 기준 3~5일 내 처리됩니다. 정책 민감 사안으로 자동응답 금지, 상담사 인계 대상입니다.
아래 Zod 스키마에 맞는 고객센터 지식문서 30건 JSON 배열로 생성하되, 각 항목은 {title, body} 형태로.
z.object({ doc_id: z.string(), title: z.string(), category_id: z.string().nullable(), body: z.string(), updated_at: z.string() })
조건: 환불·개인정보 같은 정책 민감 문서에는 body 에 ‘자동응답 금지, 상담사 인계 대상’ 을 명시. 같은 주제가 다른 제목으로 2건씩 들어가 RAG 가 중복 문서를 만나도록. JSON 배열만.z.object({ doc_id: z.string(), title: z.string(), category_id: z.string().nullable(), body: z.string(), updated_at: z.string() })자동응답 가드 룰입니다. 특정 카테고리는 강제로 사람에게 인계해야 합니다. 룰 우선순위 결측·미등록 카테고리 참조를 섞어, 정책 결측 시에도 안전하게(보수적으로 인계) 동작하는지 보여줍니다.
| rule_id | category_id | action | priority | note |
|---|---|---|---|---|
| R01 | c_delivery | auto_ok | 10 | 배송 조회는 자동응답 허용 |
| R02 | c_refund | force_human | 1 | 환불은 정책 민감, 강제 인계 |
| R03 | c_account | force_human | 1 | 개인정보 변경/삭제는 강제 인계 |
| R04 | c_return | need_review | 5 | 반품은 답 초안 후 검수 |
| R05 | c_payment | need_review | 3 | 결제 오류는 금액 확인 필요 |
아래 Zod 스키마에 맞는 policy_rules JSON 배열을 tickets 의 category_id 와 매칭되도록 생성하세요.
z.object({ rule_id: z.string(), category_id: z.string().nullable(), action: z.enum(["auto_ok","force_human","need_review"]), priority: z.number().int().nullable(), note: z.string() })
쉬운 데이터만 만들지 말 것. 하드 케이스 의도적 혼입: (1) category_id=null 인 기본 가드 룰(미등록 카테고리는 need_review/force_human 으로 보수 처리) 1건, (2) priority 결측 1건, (3) 환불·개인정보는 반드시 force_human. JSON 배열만.z.object({ rule_id: z.string(), category_id: z.string().nullable(), action: z.enum(["auto_ok","force_human","need_review"]), priority: z.number().int().nullable(), note: z.string() })상담사 검수 페르소나(LLM 시뮬 외부 평가자) 2명이 에이전트 답 초안·인계 판단에 부여한 라벨입니다. Cohen’s κ 의 입력입니다.
| ticket_id | evaluator | answer_valid | escalation_correct | policy_violation | note |
|---|---|---|---|---|---|
| T0001 | agent_reviewer_p1 | true | true | false | — |
| T0001 | agent_reviewer_p2 | true | true | false | 근거 문서 정확 |
| T0001 | self | true | true | false | — |
| T0002 | agent_reviewer_p1 | true | true | false | 환불 인계 정확 |
| T0002 | agent_reviewer_p2 | true | true | false | — |
아래 Zod 스키마에 맞는 external_labels 40 문의 × 평가자 3(p1/p2/self) = 120 행 JSON 배열로 생성하세요.
z.object({ ticket_id: z.string(), evaluator: z.enum(["agent_reviewer_p1","agent_reviewer_p2","self"]), answer_valid: z.boolean(), escalation_correct: z.boolean(), policy_violation: z.boolean(), note: z.string().nullable() })
조건: 평가자 간 일치 70% 내외, 불일치 시 note 에 도메인 사유, policy_violation=true 인 케이스(정책 민감 자동응답)는 10% 내외이고 그때 escalation_correct=false. JSON 배열만.z.object({ ticket_id: z.string(), evaluator: z.enum(["agent_reviewer_p1","agent_reviewer_p2","self"]), answer_valid: z.boolean(), escalation_correct: z.boolean(), policy_violation: z.boolean(), note: z.string().nullable() })| TypeScript | 에이전트 코어(문의 입력 → 답 초안/에스컬레이션 출력) + Zod 스키마 강제 + 런타임 검증의 주 언어 |
| Node.js | 일일 리포트 봇 워커(스케줄러 + Slack Webhook) + 인사이트 API(`POST /resolve`) 런타임 |
| LLM | few-shot + schema 강제로 답 초안 생성과 에스컬레이션 분류를 한 호출에 묶는 추론 엔진 |
| Claude | 답 초안 생성(톤·hedge 가 중요한 고객 응대)에 사용하는 기본 모델 |
| PostgreSQL | tickets / kb_docs / policy_rules / external_labels 단일 진실원 + 뷰(`v_daily_resolution`) |
| Next.js | 검수 대시보드(답 초안 카드 + 자동해결 적중률 차트) 프런트 |
✓ pass → 그대로 멈춰도 완결입니다. 더 키우고 싶으면 2주차(판단이 맞았는지 확인)로 진행합니다.
✓ pass → 여기서 멈춰도 완결입니다. 더 키우면 3주차(응대 시간 절감 라우팅 자동화)로 진행합니다.
1) 문의별 답 초안(근거 문서·정책 준수·완곡 표현), 2) 에스컬레이션 판단(자동해결/인계) + 확신도, 3) 다음 기간 실측(재문의 여부)으로 자동해결 적중 검증입니다. 제안→확인 한 주기를 한 스키마에 담습니다.
z.object({ period: z.string(), resolutions: z.array(z.object({ ticket_id: z.string(), draft_answer: z.string().min(20), cited_doc_ids: z.array(z.string()).min(0), action: z.enum(["auto_resolve","escalate","need_review"]), escalation_reason: z.string().nullable(), confidence: z.enum(["low","mid","high"]), confidence_prob: z.number() })).min(3).max(5), verification: z.object({ prior_period: z.string(), auto_resolve_hit_rate: z.number(), brier_score: z.number(), hits: z.array(z.object({ ticket_id: z.string(), predicted_auto_resolve: z.boolean(), actual_reopened: z.boolean(), correct: z.boolean(), confidence_prob: z.number() })) }).nullable() })[
{
"input_ref": "2026-03-10 (2주차 시작일. verification 은 1주차 자동해결 판단 결과)",
"output": {
"period": "2026-03-10",
"resolutions": [
{
"ticket_id": "T0001",
"draft_answer": "주문하신 상품은 마이페이지 > 주문내역에서 송장번호와 배송 현황을 확인하실 수 있습니다. 출고 후 평균 2~3일 소요됩니다.",
"cited_doc_ids": [
"kb_delivery_01"
],
"action": "auto_resolve",
"escalation_reason": null,
"confidence": "high",
"confidence_prob": 0.88
},
{
"ticket_id": "T0007",
"draft_answer": "환불 처리 지연으로 불편을 드려 죄송합니다. 환불은 정책 민감 사안이라 담당 상담사가 결제 내역을 확인해 바로 처리하도록 연결하겠습니다.",
"cited_doc_ids": [
"kb_refund_01"
],
"action": "escalate",
"escalation_reason": "환불 카테고리 force_human 룰 + 고객 강한 불만 신호",
"confidence": "high",
"confidence_prob": 0.9
},
{
"ticket_id": "T0006",
"draft_answer": "쿠폰 중복 적용 여부는 프로모션마다 다릅니다. 정확한 안내를 위해 담당자가 확인 후 답변드리겠습니다.",
"cited_doc_ids": [
"kb_promo_01"
],
"action": "need_review",
"escalation_reason": "미등록 프로모션 카테고리 기본 가드(need_review)",
"confidence": "mid",
"confidence_prob": 0.55
}
],
"verification": {
"prior_period": "2026-03-03 ~ 2026-03-09 (1주차 자동해결 판단)",
"auto_resolve_hit_rate": 0.83,
"brier_score": 0.15,
"hits": [
{
"ticket_id": "T0001",
"predicted_auto_resolve": true,
"actual_reopened": false,
"correct": true,
"confidence_prob": 0.88
},
{
"ticket_id": "T0003",
"predicted_auto_resolve": true,
"actual_reopened": true,
"correct": false,
"confidence_prob": 0.62
},
{
"ticket_id": "T0010",
"predicted_auto_resolve": true,
"actual_reopened": false,
"correct": true,
"confidence_prob": 0.9
}
]
}
}
},
{
"input_ref": "2026-03-12",
"output": {
"period": "2026-03-12",
"resolutions": [
{
"ticket_id": "T0013",
"draft_answer": "회원탈퇴와 개인정보 삭제 요청은 본인 확인이 필요한 정책 민감 사안이라, 담당 상담사가 절차를 안내하도록 연결하겠습니다.",
"cited_doc_ids": [
"kb_account_01"
],
"action": "escalate",
"escalation_reason": "개인정보 카테고리 force_human 룰",
"confidence": "high",
"confidence_prob": 0.92
},
{
"ticket_id": "T0012",
"draft_answer": "반품 회수가 진행되지 않은 점 확인했습니다. 회수 재예약을 도와드리겠습니다. 반복 문의라 처리 상태를 함께 점검합니다.",
"cited_doc_ids": [
"kb_return_01"
],
"action": "need_review",
"escalation_reason": "반품 need_review 룰 + reopened=true",
"confidence": "mid",
"confidence_prob": 0.58
},
{
"ticket_id": "T0010",
"draft_answer": "고객센터 운영시간은 평일 09시~18시입니다. 그 외 시간은 챗봇이 1차 응대합니다.",
"cited_doc_ids": [
"kb_info_01"
],
"action": "auto_resolve",
"escalation_reason": null,
"confidence": "high",
"confidence_prob": 0.9
}
],
"verification": {
"prior_period": "2026-03-10 ~ 2026-03-11 판단",
"auto_resolve_hit_rate": 0.8,
"brier_score": 0.17,
"hits": [
{
"ticket_id": "T0001",
"predicted_auto_resolve": true,
"actual_reopened": false,
"correct": true,
"confidence_prob": 0.88
},
{
"ticket_id": "T0006",
"predicted_auto_resolve": false,
"actual_reopened": false,
"correct": true,
"confidence_prob": 0.55
},
{
"ticket_id": "T0009",
"predicted_auto_resolve": false,
"actual_reopened": true,
"correct": true,
"confidence_prob": 0.6
}
]
}
}
}
]자동: (1) Zod parse, (2) cited_doc_ids 가 kb_docs 에 실재하는 doc_id 인지, (3) policy_rules 의 force_human 카테고리가 auto_resolve 로 나오면 정책 위반으로 자동 차단, (4) Brier score 자동 계산(사이클 1 reporting / 사이클 2+ KPI). confidence_prob 는 합성 기준 추정이라 검증 수치가 아닙니다. 수동: 상담사 검수자 2명 비동기 라벨 → bootstrap Cohen’s κ CI 하한 ≥ 0.6, judge 사람 spot check 5%. verification 은 차 기간 재문의 실측치 자동 조인.