판결 — 정책이 충돌할 때
Source: Dev.to
Algolia Agent Studio Challenge – Consumer‑Facing Non‑Conversational Experiences
Submission Overview
대부분의 지원 도구는 정책을 가져와 에이전트에게 전달하기만 합니다. 실제로는 티켓이 여러 정책, 때로는 상충되는 정책들의 교차점에 놓여 있는 경우가 많습니다.
예시: 트레드밀 모터가 6주 후에 고장남.
- 30일 반품 기간 → 아니오
- 2년 모터 보증 → 예
Verdict는 이러한 충돌을 해결하는 의사결정 엔진입니다. 에이전트가 티켓을 클릭하면 Verdict가 Algolia에서 관련 정책 조항을 가져와 모순을 감지하고 해결 계층을 적용합니다:
- 제품‑특정이 일반보다 우선
- 상황별이 모든 것보다 우선
그 결과는 전체 인용이 포함된 구조화된 판결이며, 챗봇이나 왕복 대화가 없습니다.
Demo Highlights
| Scenario | Outcome | Note |
|---|---|---|
| Treadmill X500 (Warranty vs. Return) | ✅ APPROVED (green) | 모터 보증이 만료된 반품 기간을 우선합니다. |
| SoundPro Earbuds (Hygiene Override) | ❌ DENIED (red) | 위생 예외가 30일 이내라 하더라도 반품을 차단합니다. |
| Alpine Hiking Boots (Damage Override) | ✅ APPROVED (green) | 배송 손상 상황별 예외가 만료된 반품 기간보다 우선합니다. |
| TrailBlazer Daypack (Standard Return) | ✅ APPROVED (green) | 충돌이 없으며 단순한 경우입니다. |
| Custom ticket | Live analysis | 텍스트를 붙여넣으면 Verdict가 실시간으로 이유를 보여줍니다. |
| Policy Index | Browse 26 records | 3개의 미끼 정책이 포함되어 있지만 올바르게 무시됩니다. |
- Live URL: (link omitted)
- Demo video: (link omitted)
Policy Index Details
- Index name:
apex_gear_policies - Records: 가상의 소매업체 Apex Gear를 위한 26개의 개별 정책 조항(레코드당 하나의 조항)
- Metadata per record:
{
"policy_layer": 1‑4,
"priority_score": number,
"policy_type": "string",
"product_tags": ["string"],
"conditions": "string",
"effect": "string"
}
-
왜 조항‑단위 인덱싱인가?
충돌 해결은 전체 문서가 아니라 개별 조항을 비교해야 하며, 각 레코드를 Algolia의 10 KB 무료 티어 제한 이하로 유지할 수 있습니다. -
미끼 정책 (3 레코드):
- 만료된 휴일 반품 연장
- 로열티 회원 혜택
- 대량 할인 정책
이들은 데모 시나리오와 동일한 제품 카테고리를 공유하지만 절대 인용되지 않아야 합니다. 에이전트는 일관되게 이를 무시합니다.
Algolia Configuration
| Feature | Description |
|---|---|
| Custom ranking | desc(policy_layer), desc(priority_score), desc(specificity_score) – 가장 권위 있는 조항이 먼저 표시되도록 보장합니다. |
| Index‑level Rules (3) | 트리거 단어가 나타날 때 중요한 예외 정책을 승격합니다. 예시: “hygiene”이 포함된 쿼리는 HYG‑4.1(인이어 오디오 위생 예외)을 위치 1로 끌어올립니다. |
| Synonym groups (6) | 어휘 확장: • “defective” ↔ “broken”, “malfunction”, “stopped working” • “earbuds” ↔ “in‑ear audio”, “personal audio” |
| Result flow | 검색‑시점 기능(랭킹, 규칙, 동의어)은 LLM이 보는 내용을 형성하고, 추론‑시점 기능(조건 매칭, 설명)은 LLM이 처리합니다. |
이 레이어들은 함께 작동합니다: Algolia가 정렬되고 어휘가 정규화된 조항 집합을 제공하고, LLM이 이를 기반으로 최종 판결을 도출합니다.
Agent Studio Loop
-
System prompt가 다단계 프로토콜을 정의합니다:
- 티켓에서 핵심 정보를 추출합니다.
- 세 가지 목표 Algolia 검색을 수행합니다(일반 반품, 제품‑특정 보증, 상황별 예외).
- 검색된 모든 정책을 분석하고, 충돌을 감지한 뒤 계층에 따라 해결하고, 구조화된 XML 판결을 출력합니다.
-
Dynamic search selection
Source: …
– 에이전트는 티켓 내용에 따라 실행할 쿼리를 결정합니다.
- Earbuds 티켓:
"hygiene earbuds in‑ear audio return" - Treadmill 티켓:
"Pro‑Treadmill X500 warranty" - Hiking boots 티켓:
"shipping damage carrier report override"
- 반환(anti‑hallucination) 가드 – 판결에 포함되는 모든
clause_id는 검색 결과에서 그대로 복사해야 합니다. 에이전트는 정책을 만들어 내거나 고객에게 추가 정보를 요청할 수 없으며, 결정을 내리거나 에스컬레이션해야 합니다.
탐색 방법
- 데모 UI에서 티켓을 클릭 → 판결 카드, 정책 비교 패널, 충돌 추적을 확인합니다.
- 인용문 위에 마우스를 올리면 정확한 조항 텍스트를 볼 수 있습니다.
- Policy Index를 탐색하여 26개의 레코드(디코이 포함)를 모두 확인합니다.
요점
판결은 비대화형, 사전형 의사결정이 Algolia의 검색 기능과 LLM 추론 위에 구축될 수 있음을 보여줍니다. 에이전트의 워크플로는 간단합니다:
티켓 확인 → 클릭 → 구조화된 판결 읽기 → 실행
채팅 버블도, 왔다 갔다 하는 대화도 없으며, Algolia와 LLM이 구동하는 신뢰할 수 있고 설명 가능한 판결을 제공합니다.
개요
Agent Studio의 /completions 엔드포인트는 Server‑Sent Events (SSE) 스트림을 반환합니다. 나는 API 라우트에 맞춤형 SSE 파서를 구현하여 에이전트 추론 체인에 있는 모든 이벤트를 캡처했습니다 – 최종 텍스트 출력만이 아니라.
파서는:
tool-input-start이벤트(검색 쿼리와toolCallId를 포함)와tool-output-available이벤트(해당toolCallId에 대한 실제 Algolia 히트를 포함)를 연관시킵니다.- 전체 파이프라인 뷰를 제공합니다:
- 에이전트가 검색한 내용
- Algolia가 반환한 결과
- LLM이 최종적으로 인용한 레코드
프런트엔드 렌더링
UI는 이 파이프라인 추적을 눈에 보이게 렌더링합니다:
- 각 Algolia 검색 단계는 쿼리 텍스트, 히트 수, 그리고 반환된 개별 정책 레코드를 보여줍니다.
- 최종 판결에 인용된 레코드에는 “Cited in verdict” 배지가 붙어, 어떤 조항이 결정에 영향을 미쳤는지 정확히 확인할 수 있습니다.
LLM이 기대 형식에서 벗어나면 UI는 경고 배너와 함께 원시 응답을 표시하도록 폴백하며, 절대 크래시되지 않습니다.
시스템 프롬프트 – XML‑태그 출력
<verdict>
<status>APPROVED</status>
<type>warranty_claim</type>
<explanation>Motor warranty overrides expired return window...</explanation>
<clause>
<id>WAR-3.1</id>
<title>Pro-Treadmill Motor Warranty</title>
<valid>true</valid>
<outcome>warranty_approved</outcome>
<details>Motor failed within 2-year warranty period</details>
</clause>
<rule>
<id>WAR-3.1</id>
<description>Product-specific warranty overrides general return</description>
</rule>
</verdict>
- 프런트엔드는 이를 정규식 기반 태그 추출기를 사용해 타입드 컴포넌트로 파싱합니다.
- 시나리오당
temperature=0으로 20회 이상 테스트했을 때, XML은 매번 정상적으로 형성되었습니다.
Algolia 기능이 검색을 형성하는 방식
| Feature | What it does |
|---|---|
| Custom ranking | 모든 검색 결과가 정책 권한에 따라 미리 정렬된 상태로 도착합니다. |
| Index‑level Rules | 트리거 조건이 충족될 때 중요한 오버라이드 조항을 최상위에 승격합니다. |
| Synonyms | 어휘를 정규화합니다(예: “motor stopped working” → “mechanical defect”), 그래서 LLM이 추측할 필요가 없습니다. |
이 모든 설정은 Algolia 대시보드에서 구성되며, Agent Studio를 통해 투명하게 작동합니다 – 추가 API 코드는 필요하지 않습니다.
왜 벡터 데이터베이스가 아닌가?
- 벡터 DB는 “의미적으로 유사한” 정책을 검색하지만, 이는 컴플라이언스 데이터에 필요한 방식이 아닙니다.
- 고객이 트레드밀 모터 고장을 보고할 때 우리는 정확한 모터‑보증 조항(
policy_layer:3, applies_to:Pro‑Treadmill X500)이 필요합니다. 이는 임베딩 거리로 순위가 매겨진 몇 개의 느슨하게 연관된 피트니스 장비 정책이 아니라, 메타데이터 기반 정밀 필터링이 맞는 검색 모델입니다. - 구조화된 메타데이터와 정확한 필터링이 이 사용 사례에 가장 적합한 검색 모델입니다.
se‑case.
Performance
- Total analysis time (UI에 각 판결 후 표시됨): 5‑10 seconds – 거의 전부 LLM 추론.
- Algolia retrieval: < 50 ms (세 번의 검색 모두에서).
에이전트가 수십 개의 티켓을 분류하는 지원 워크플로우에서는, 이 검색 속도가 병목을 데이터 대기 시간이 아니라 추론에 두게 합니다.