---
name: generate-agent
description: >
  LangGraph ReAct(추론 → 도구 호출 → 재추론) 패턴 기반 FastAPI 도구 호출
  챗봇/에이전트 서버 자동 생성. `chatbot`(추론) ↔ `tools`(ToolNode 실행) 순환
  그래프, `MemorySaver` 체크포인터(`session_id` → `thread_id`) 기반 세션별
  대화 이력, 도메인 조회 도구 2개 이상, 도구 결과가 전부 정보 없음일 때 LLM
  재호출 없이 고정 문구로 답하는 `route_after_tools` 가드레일까지 포함한
  완전한 스캐폴딩.
  Trigger when: 챗봇 서버 만들기, 에이전트 서버 만들기, LangGraph, LangChain
  ReAct 패턴, tool calling/도구 호출 에이전트, 세션 기반 대화 이력, FAQ 봇,
  상담 챗봇, 사내 QA 봇, "정보 없으면 모른다고 답변" 같은 가드레일/폴백 요청,
  RAG 대신 정형 데이터(JSON/DB) 조회로 답하는 챗봇.
  Use this skill whenever the user wants to build any kind of tool-calling /
  agentic chatbot backend, even if they don't explicitly say "generate-agent",
  "LangGraph", or "ReAct".
version: 1.0.0
---

# Generate Agent

LangGraph의 ReAct(추론 → 도구 호출 → 결과 반영 재추론) 패턴으로 동작하는
FastAPI 챗봇/에이전트 서버를 생성합니다. `옥외광고 지도 서비스 챗봇` 프로젝트를
구현·검증하며 정리한 패턴이며, 도메인만 바꾸면 어떤 "정형 데이터 조회형 챗봇"
에도 그대로 적용됩니다(FAQ 봇, 사내 정책 봇, 상품/재고 조회 봇 등).

---

## 이 스킬이 만드는 것

1. **추론-도구호출 순환 그래프**: LLM이 사용자 질문을 보고 어떤 도구를 호출할지
   스스로 판단 → 도구 실행 → 결과를 다시 LLM에 보여주고 재판단(추가 도구 호출
   or 최종 답변) → 필요한 만큼 반복
2. **세션별 대화 이력**: `session_id`를 그래프의 `thread_id`로 사용하는
   체크포인터로, 같은 세션이면 이전 대화 맥락을 자동으로 참고
3. **도메인 조회 도구 2개 이상**: 사용자가 가진 데이터(JSON/DB/API)를 조회하는
   `@tool` 함수들. 정보를 못 찾으면 `[NOT_FOUND]` 마커가 붙은 문자열을 반환
4. **가드레일 폴백**: 이번 라운드에 호출된 도구 결과가 전부 `[NOT_FOUND]`면,
   LLM이 그럴듯하게 답을 지어내기 전에 그래프 코드가 직접 감지해 고정 안내
   문구로 즉시 답변을 대체

먼저 아키텍처를 한 번에 이해하려면 `references/graph-architecture.md`의
ASCII flowchart를 참고하세요.

---

## 작업 순서

### 1. 인터뷰 (반드시 먼저 확인)

코드를 쓰기 전에 아래 4가지를 사용자와 확정하세요. 각각 트레이드오프가 있고
프로젝트마다 다르므로 임의로 정하지 말고 짧게 물어보는 것이 좋습니다.

| 질문 | 선택지 | 기본 추천 |
| --- | --- | --- |
| 대화 이력 유지 방식 | `MemorySaver`(인메모리) vs `SqliteSaver`(영속) | 데모/목업이면 인메모리, 운영 서버면 Sqlite/Postgres |
| LLM/모델 | OpenAI `gpt-4o-mini` 등 | 비용·속도 우선이면 mini 계열 |
| 도메인 데이터 소스 | 이미 있는 JSON/DB/API 목록 | 사용자가 가진 것 그대로 사용, 없으면 mock 데이터 생성부터 |
| 도구 개수/역할 분담 | 질문 유형별로 몇 개의 조회 함수가 필요한지 | 질문 유형(일반 Q&A vs 특정 엔티티 조회)별로 최소 1개씩 |

git 저장소 여부, 배포 방식(uvicorn 단독 vs 컨테이너) 등 프로젝트 구조에 영향을
주는 사항도 이 시점에 함께 확인하세요.

### 2. 프로젝트 스캐폴딩

`references/project-structure.md`의 디렉터리 구조와 파일 템플릿을 그대로
따르세요. 핵심 파일:

```
app/
  main.py            FastAPI 엔트리포인트 (POST /chat, GET /health)
  config.py           .env 로드 및 모델 설정
  schemas.py          요청/응답 Pydantic 모델
  agent/
    graph.py           StateGraph 정의 (추론-도구호출 루프 + 가드레일)
    tools.py           도메인 조회 도구 (@tool 함수들)
    data.py            데이터 소스 로딩
```

### 3. 그래프 구현

`references/graph-architecture.md`를 읽고 다음을 그대로 구현하세요:

- `AgentState.messages`를 `Annotated[Sequence[BaseMessage], operator.add]`로
  선언해 노드를 지날 때마다 메시지가 누적되게 함
- `chatbot` 노드: 시스템 프롬프트 + 누적 메시지를 매번 새로 LLM에 전달
- `tools_condition`으로 `chatbot → tools` 또는 `chatbot → END` 분기
- `route_after_tools` 함수로 `tools → chatbot`(정보 찾음) 또는
  `tools → fallback`(이번 라운드 도구 결과가 전부 `NOT_FOUND`) 분기
- `MemorySaver` 체크포인터를 `session_id`를 `thread_id`로 매핑해 컴파일

### 4. 도구 작성

`references/qna-matching.md`를 참고해 도구를 작성하세요. 특히 텍스트 질문을
사전 등록된 Q&A 등과 매칭해야 하는 도구라면, 임베딩 모델 없이도 안정적으로
동작하는 TF-IDF 가중 문자 bigram 코사인 유사도 방식을 `scripts/qna_matcher.py`
템플릿에서 그대로 가져다 쓸 수 있습니다. **단순 `difflib.SequenceMatcher`나
공백 기준 단어 토큰 overlap은 한국어에서 "어떻게/하나요" 같은 흔한 어미가
점수를 왜곡해 엉뚱한 항목이 1등으로 뽑히는 실제 버그를 유발하니 피하세요**
(자세한 실패 사례와 원인은 해당 참조 문서 참고).

### 5. FastAPI 연결 및 검증

`POST /chat`(`session_id`, `message`) 엔드포인트로 그래프를 감싸고, 다음
시나리오를 실제로 서버를 띄워 curl/httpx로 검증하세요(코드가 컴파일된다고
동작이 맞다는 뜻은 아닙니다):

1. 각 도구가 정상적으로 답변하는 질문
2. 같은 `session_id`로 이어지는 후속 질문이 이전 맥락을 참고하는지
3. 도메인과 무관하거나 데이터가 없는 질문에서 가드레일 고정 문구가 나오는지
4. (한국어 텍스트 매칭 도구가 있다면) 패러프레이즈된 질문과, 겹치는 단어는
   있지만 실제로는 무관한 질문 양쪽으로 임계값을 검증

콘솔이 UTF-8을 cp949 등으로 잘못 표시해 한글이 깨져 보일 수 있으니, 응답을
파일에 UTF-8로 써서 확인하거나 Read 도구로 확인하는 것이 안전합니다.

### 6. 문서화

`README.md`(설치/실행/API 사용법)와, 그래프의 순환 구조를 텍스트 박스로 그린
`flowchart.md`(mermaid가 아닌 순수 ASCII — 렌더러 없이 바로 보이도록)를
함께 생성하세요. `references/graph-architecture.md`의 다이어그램을 프로젝트
실정에 맞게 재사용하면 됩니다.

---

## 참조 문서

- `references/graph-architecture.md` — StateGraph 노드/엣지 구조, 반복이
  가능한 이유, 가드레일 라우팅 로직, ASCII flowchart
- `references/qna-matching.md` — 텍스트 질의 매칭 알고리즘, 실패 사례와
  TF-IDF bigram 코사인 유사도로 고친 이유, 임계값 튜닝 방법론
- `references/project-structure.md` — 디렉터리 구조와 각 파일의 전체 코드
  템플릿 (config.py, schemas.py, data.py, main.py, graph.py, tools.py)
- `scripts/qna_matcher.py` — 바로 복사해 쓸 수 있는 TF-IDF bigram 매처 구현
