lawful-legal-search-1
한국 판례·법령 코퍼스에 근거해 법률 질문에 답하는 모델입니다. REST API와 MCP 두 가지 형태로 제공합니다.
Overview
한눈에
모델
코퍼스
입력
출력
응답 형식
호출 한도
비교
| Legal Search API | Legal Search MCP | |
|---|---|---|
| 도구 실행 | 서버 | 연결한 AI |
| 응답 | 완성된 답변 | 도구 실행 결과 |
| 프로토콜 | REST · SSE | MCP · Streamable HTTP |
| 엔드포인트 | api.crow-tit.com/v1/agent |
mcp.crow-tit.com/mcp |
| 평균 응답 시간 | 30~60초 | 1초 내외 |
| 인증 | Bearer API 키 | Bearer API 키 |
Quick Start
키를 발급하고 네 줄이면 첫 답변을 받을 수 있습니다.
API 키 발급
콘솔에서 소셜 로그인 후 키를 만들어주세요.
Basic call
다음 코드는 Legal Search API를 쉽게 온보딩하는 데 도움이 되는 전체 샘플 코드입니다.
pip install crowtit
from crowtit import Lawful client = Lawful(api_key="ct_...") # 또는 환경변수 CROWTIT_API_KEY answer = client.ask("전세 보증금을 집주인이 안 돌려주는데 어떻게 대응해야 하나요?") print(answer.text)
curl https://api.crow-tit.com/v1/agent \ -H "Authorization: Bearer ct_..." \ -H "Content-Type: application/json" \ --max-time 300 \ -d '{"question": "전세 보증금을 안 돌려줍니다"}'
const res = await fetch("https://api.crow-tit.com/v1/agent", { method: "POST", headers: { Authorization: `Bearer ${process.env.CROWTIT_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ question: "전세 보증금을 안 돌려줍니다" }), }); const message = await res.json(); console.log(message.answer);
Stream call
답변이 생성되는 대로 받으려면 스트리밍 엔드포인트를 사용해주세요.
for text in client.stream("음주운전 초범인데 처벌 수위가 어떻게 되나요?"): print(text, end="", flush=True)
curl -N https://api.crow-tit.com/v1/agent/stream \ -H "Authorization: Bearer ct_..." \ -H "Content-Type: application/json" \ -d '{"question": "음주운전 초범인데 처벌 수위가 어떻게 되나요?"}'
const res = await fetch("https://api.crow-tit.com/v1/agent/stream", { method: "POST", headers: { Authorization: `Bearer ${key}`, "Content-Type": "application/json" }, body: JSON.stringify({ question: "음주운전 초범인데 처벌 수위가 어떻게 되나요?" }), }); const reader = res.body.pipeThrough(new TextDecoderStream()).getReader(); let buf = ""; for (;;) { const { value, done } = await reader.read(); if (done) break; buf += value; const lines = buf.split("\n"); buf = lines.pop(); for (const line of lines) { if (!line.startsWith("data:")) continue; const ev = JSON.parse(line.slice(5)); if (ev.type === "content_block_delta" && ev.delta.type === "text_delta") { process.stdout.write(ev.delta.text); } } }
API Reference
엔드포인트는 두 개입니다. 동기 호출과 스트리밍 호출을 제공합니다.
요청
모든 요청에 Bearer 토큰이 필요합니다. 키는 콘솔에서 발급합니다. 키를 붙인 전체 요청은 다음과 같습니다.
from crowtit import Lawful client = Lawful(api_key="ct_...") # 또는 환경변수 CROWTIT_API_KEY question = "전세 보증금을 안 돌려줍니다. 대응 절차를 알려주세요." answer = client.ask( question, depth="deep", instructions="결론을 먼저 쓰고, 근거 조문은 뒤에 정리해주세요.", ) print(answer.text) # 생성되는 대로 받으려면 메서드만 stream() # for text in client.stream(question, depth="deep"): # print(text, end="", flush=True)
curl https://api.crow-tit.com/v1/agent \ -H "Authorization: Bearer ct_..." \ -H "Content-Type: application/json" \ --max-time 300 \ -d '{ "question": "전세 보증금을 안 돌려줍니다. 대응 절차를 알려주세요.", "depth": "deep", "instructions": "결론을 먼저 쓰고, 근거 조문은 뒤에 정리해주세요." }' # 생성되는 대로 받으려면 경로 끝에 /stream # curl -N https://api.crow-tit.com/v1/agent/stream \ # -H "Authorization: Bearer ct_..." -H "Content-Type: application/json" \ # -d '{"question": "..."}'
const res = await fetch("https://api.crow-tit.com/v1/agent", { method: "POST", headers: { Authorization: `Bearer ${process.env.CROWTIT_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ question: "전세 보증금을 안 돌려줍니다. 대응 절차를 알려주세요.", depth: "deep", instructions: "결론을 먼저 쓰고, 근거 조문은 뒤에 정리해주세요.", }), }); const message = await res.json(); console.log(message.answer); // 생성되는 대로 받으려면 경로 끝에 /stream // await fetch("https://api.crow-tit.com/v1/agent/stream", { ...같은 요청 });
법률 질문입니다. 계약서나 사실관계 전문을 함께 넣을 수 있으며, 최대 32,000 토큰(한국어 약 45,000자)입니다.
deep 이 기본값이며 품질을 우선합니다. quick 은 추론을 생략하고 얕게 검색합니다.
답변 형식과 어조 지시입니다. 최대 2,000 토큰이며 기존 규칙에 덧붙습니다. 사실 확인·인용·안전 규칙은 변경할 수 없습니다.
응답
동기 호출은 완성된 message 객체 하나로 오고,
스트리밍은 같은 message 를 이벤트로 쪼갠 것입니다.
{
"id": "msg_...",
"type": "message",
"role": "assistant",
"model": "lawful-legal-search-1",
"content": [
{ "type": "text", "text": "관련 법령을 먼저 확인하겠습니다." },
{ "type": "server_tool_use", "name": "precedent_search",
"display_name": "판례 검색", "id": "srvtoolu_..." },
{ "type": "text", "text": "## 대응 절차 ..." }
],
"stop_reason": "end_turn",
"answer": "## 대응 절차 ...",
"sources": [{ "url": "https://lawful.crow-tit.com/cases/5706" }],
"usage": { "input_tokens": 27698, "output_tokens": 1569, "tool_calls": 3 }
}
event: message_start
data: {"type": "message_start", "message": {"id": "msg_...", "model": "lawful-legal-search-1", ...}}
event: content_block_start
data: {"type": "content_block_start", "index": 0, "content_block": {"type": "text", "text": ""}}
event: content_block_delta
data: {"type": "content_block_delta", "index": 0, "delta": {"type": "text_delta", "text": "관련 "}}
event: content_block_stop
data: {"type": "content_block_stop", "index": 0}
event: content_block_start
data: {"type": "content_block_start", "index": 1, "content_block": {"type": "server_tool_use", "name": "precedent_search", "display_name": "판례 검색", ...}}
event: content_block_stop
data: {"type": "content_block_stop", "index": 1}
event: content_block_start
data: {"type": "content_block_start", "index": 2, "content_block": {"type": "text", "text": ""}}
event: content_block_delta
data: {"type": "content_block_delta", "index": 2, "delta": {"type": "text_delta", "text": "## 대응"}}
event: content_block_stop
data: {"type": "content_block_stop", "index": 2}
event: message_delta
data: {"type": "message_delta", "delta": {"stop_reason": "end_turn"}, "sources": [...], "usage": {...}}
event: message_stop
data: {"type": "message_stop"}
블록 목록입니다. 종류는 답변인 text 와 서버가 실행한 도구인
server_tool_use 두 가지이며, 사람에게 보여줄 도구 이름은
display_name 에 담깁니다.
마지막 text 블록의 사본입니다. 대부분의 경우 이 값만 사용하면 됩니다.
도구가 반환한 판례·법령 페이지 URL입니다. 참고 메타데이터이며 답변 문장과 1:1로 대응하지는 않습니다.
end_turn 은 정상 종료입니다. max_rounds 는 라운드나 도구 호출이
소진된 경우로, 오류가 아니며 그때까지의 부분 답변이 함께 옵니다.
input_tokens · output_tokens · tool_calls
스트리밍 이벤트
event: 이름은 언제나 payload의
type 과 같으므로 data: 만 읽으면 됩니다.
| 이벤트 | 내용 |
|---|---|
| message_start | 스트림 시작. id 와 model 을 담습니다. |
| content_block_start | 블록 시작. index 와 블록 종류를 담습니다. |
| content_block_delta | 텍스트 조각. delta.text |
| content_block_stop | 블록 종료 |
| message_delta | stop_reason · sources · usage |
| message_stop | 스트림 종료 |
블록 index 는 시작 순서입니다. 도구가 병렬로 실행되면
블록이 겹쳐 열리므로 index 로 묶어 처리합니다. 15초마다 오는
keepalive 주석(: ping)은 data: 줄만 읽으면 걸러집니다.
오류
오류 응답은 한 가지 형식이며, 구체적인 사유는 message 에 담깁니다.
{"type": "error", "error": {"type": "invalid_request_error", "message": "..."}}
| type | 상태 | 의미 |
|---|---|---|
| authentication_error | 401 | 키가 없거나 유효하지 않습니다 |
| invalid_request_error | 400 · 422 | 요청 형식이 맞지 않습니다 |
| request_too_large | 413 | 요청 본문이 상한을 넘었습니다 |
| api_error | 5xx | 서버 오류 |
제한
| 항목 | 값 | |
|---|---|---|
| question | 32,000 토큰 | 한국어 약 45,000자 |
| instructions | 2,000 토큰 | |
| 요청 본문 | 512 KB | 초과 시 request_too_large |
| 도구 호출 | 요청당 30회 | 소진 시 stop_reason: max_rounds |
| 모델 왕복 | 요청당 25회 | |
| 응답 시간 | 동기 280초 · 스트리밍 600초 | 초과 시 타임아웃 |
MCP Reference
코퍼스 도구 5종을 개별 도구로 연결합니다.
연결
claude mcp add --transport http lawful https://mcp.crow-tit.com/mcp \
--header "Authorization: Bearer ct_..."
{
"mcpServers": {
"lawful": {
"url": "https://mcp.crow-tit.com/mcp",
"headers": { "Authorization": "Bearer ct_..." }
}
}
}
도구
precedent_search
키워드·사건번호·심급·법원·연도로 판례를 검색합니다.
precedent_dive
선택한 판결문 본문에서 쟁점을 추출해 요약합니다.
statute_lookup
법령명과 조문 단위로 법령·고시 본문을 조회합니다.
sentence_statistics
죄명별 1심 선고 분포를 조회합니다.
compute_sentencing_range
가중·감경을 반영한 양형기준 권고 형량을 계산합니다.
제한
| 도구 | 인자 | 상한 |
|---|---|---|
| statute_lookup | limit | 50 (기본 10) |
| statute_lookup | articles | 8개 |
| precedent_dive | question | 1,000자 |