- AI 시스템 프롬프트: 에이전트 응답 그대로 전달 규칙 추가 - Deposit Agent 핵심 규칙 확장: - 자연어 금액 인식 (만원, 5천원 등) - 즉시 실행 (확인 질문 없이) - 간편 취소 (최근 pending 자동 선택) - 동시 요청 허용 - Deposit Agent 응답 포맷 예시 추가 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
16 KiB
16 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Auto-Read on Start
세션 시작 시 반드시 수행:
README.md를 Read 도구로 읽어 프로젝트 전체 구조 파악- 작업 대상 파일의 기존 코드 먼저 확인
필수 읽기: README.md → 작업 대상 파일
Critical Rules
절대 지켜야 할 규칙:
| 규칙 | 이유 |
|---|---|
배포 전 npm run dev 로컬 테스트 |
프로덕션 장애 방지 |
| D1 스키마 변경 시 마이그레이션 SQL 별도 작성 | 기존 데이터 보존 |
| Secrets(BOT_TOKEN, API_KEY 등) 코드에 하드코딩 금지 | 보안 |
wrangler.toml의 ID 값 변경 금지 |
리소스 연결 유지 |
Function Calling 도구 추가 시 tools 배열 + executeFunctionCall() 동시 수정 |
불일치 방지 |
위험한 작업:
wrangler d1 execute직접 실행 (production) → 반드시 확인 요청user_deposits,deposit_transactions테이블 직접 수정 → 금전 관련, 주의
Documentation Rules
작업 완료 후 문서 자동 업데이트:
트리거 조건
| 변경 유형 | 업데이트 대상 |
|---|---|
src/*.ts 파일 수정 |
CLAUDE.md (Core Services, Key Patterns) |
| 새 Function Calling 도구 추가 | 양쪽 (README: 지원 기능 테이블, CLAUDE: tools 목록) |
schema.sql 변경 |
양쪽 (Data Layer 섹션) |
wrangler.toml 환경변수 추가 |
양쪽 (Configuration 섹션) |
| 외부 API 연동 추가/변경 | 양쪽 (External Integrations) |
| 봇 명령어 추가 | 양쪽 (Commands 섹션) |
업데이트 체크리스트
[ ] CLAUDE.md - 기술 상세 (개발자용)
[ ] README.md - 사용자 가이드 (배포/운영자용)
[ ] 다이어그램/플로우 수정 필요 여부
[ ] wrangler.toml 주석 업데이트
Commands
npm run dev # 로컬 개발 (wrangler dev)
npm run deploy # Cloudflare Workers 배포
npm run db:init # D1 스키마 초기화 (production) ⚠️ 주의
npm run db:init:local # D1 스키마 초기화 (local)
npm run tail # Workers 로그 스트리밍
Secrets 설정:
wrangler secret put BOT_TOKEN # Telegram Bot Token
wrangler secret put WEBHOOK_SECRET # Webhook 검증용
wrangler secret put OPENAI_API_KEY # OpenAI API 키
Webhook 설정:
curl https://telegram-summary-bot.kappa-d8e.workers.dev/setup-webhook
curl https://telegram-summary-bot.kappa-d8e.workers.dev/webhook-info
Code Style & Conventions
TypeScript
- Strict mode:
tsconfig.json에서 strict 활성화 - 타입 정의:
types.ts에 인터페이스 집중 관리 - any 사용 금지: 불가피한 경우 주석으로 이유 명시
에러 핸들링
// 패턴: try-catch + 사용자 친화적 메시지
try {
// 작업
} catch (error) {
console.error('[ServiceName] 작업 실패:', error);
return '죄송합니다. 일시적인 오류가 발생했습니다.';
}
로깅 규칙
console.log('[ServiceName] 동작 설명'); // 정상 동작
console.error('[ServiceName] 에러 설명:', error); // 에러
// wrangler tail로 확인 가능
네이밍
- 파일:
kebab-case.ts(예:openai-service.ts) - 함수:
camelCase(예:executeFunctionCall) - 상수:
UPPER_SNAKE_CASE(예:SUMMARY_THRESHOLD) - 타입/인터페이스:
PascalCase(예:TelegramUpdate)
Testing
현재 테스트 스크립트 없음 - 수동 테스트 필수
로컬 테스트 절차
# 1. 로컬 D1 초기화 (최초 1회)
npm run db:init:local
# 2. 로컬 서버 실행
npm run dev
# 3. 다른 터미널에서 테스트 요청
curl -X POST http://localhost:8787/webhook \
-H "Content-Type: application/json" \
-H "X-Telegram-Bot-Api-Secret-Token: test-secret" \
-d '{"message":{"chat":{"id":123},"text":"테스트"}}'
배포 후 확인
# 로그 스트리밍
npm run tail
# Webhook 상태 확인
curl https://telegram-summary-bot.kappa-d8e.workers.dev/webhook-info
Troubleshooting
자주 발생하는 에러
| 증상 | 원인 | 해결 |
|---|---|---|
D1_ERROR: no such table |
스키마 미적용 | npm run db:init 실행 |
401 Unauthorized (OpenAI) |
API 키 만료/잘못됨 | wrangler secret put OPENAI_API_KEY |
| Webhook 응답 없음 | Secret Token 불일치 | WEBHOOK_SECRET 재설정 후 /setup-webhook |
| Function Calling 무한 루프 | tool_choice 설정 오류 | tool_choice: "auto" 확인 |
| 프로필 업데이트 안됨 | 메시지 20개 미만 | /context로 버퍼 수 확인 |
| Email Worker 파싱 실패 | SMS 형식 변경 | index.ts의 정규식 패턴 확인 |
| AI가 도구 호출 안 함 | 키워드 미인식 | 시스템 프롬프트 + 도구 description에 키워드 추가 |
| 예치금 최소 금액 제한 | Agent 프롬프트 문제 | Deposit Agent 프롬프트 수정 (OpenAI API) |
디버깅 명령어
# D1 데이터 직접 조회 (로컬)
wrangler d1 execute telegram-conversations --local --command "SELECT * FROM users LIMIT 5"
# D1 데이터 직접 조회 (production) ⚠️ 주의
wrangler d1 execute telegram-conversations --command "SELECT * FROM users LIMIT 5"
Architecture
Message Flow:
Telegram Webhook → Security Validation → Command/Message Router
↓
┌──────────────────────────┴──────────────────────────┐
↓ ↓
Command Handler AI Response Generator
(commands.ts) (openai-service.ts)
↓
Function Calling
(weather, search, time, calc, docs)
↓
Profile System
(summary-service.ts)
Core Services:
| 파일 | 역할 | 주요 함수 |
|---|---|---|
index.ts |
Worker 진입점, Email Handler | fetch(), email() |
openai-service.ts |
AI 응답 + Function Calling | generateResponse(), executeFunctionCall() |
summary-service.ts |
프로필 시스템 | updateSummary(), getConversationContext() |
deposit-agent.ts |
예치금 에이전트 (Assistants API) | callDepositAgent(), executeDepositFunction() |
security.ts |
Webhook 보안 | validateWebhook(), checkRateLimit() |
commands.ts |
봇 명령어 | handleCommand() |
telegram.ts |
Telegram API | sendMessage(), sendTypingAction() |
Function Calling Tools (7개):
| 도구 | 함수명 | 외부 API | 트리거 키워드 |
|---|---|---|---|
| 날씨 | get_weather |
wttr.in | 날씨 |
| 검색 | web_search |
Brave Search | ~란, ~뭐야 |
| 시간 | get_current_time |
내장 | 몇 시, 시간 |
| 계산 | calculate |
내장 | 계산, +, -, *, / |
| 문서 | lookup_docs |
Context7 | 문서, 사용법, API |
| 도메인 | manage_domain |
Domain Agent → Namecheap | 도메인, 네임서버, WHOIS |
| 예치금 | manage_deposit |
Deposit Agent → D1 | 입금, 충전, 잔액, 계좌, 송금 |
Data Layer (D1 SQLite):
| 테이블 | 용도 | 주요 컬럼 |
|---|---|---|
users |
사용자 | telegram_id, username |
message_buffer |
대화 기록 | user_id, role, content |
summaries |
프로필 | user_id, generation, summary |
user_deposits |
예치금 계정 | user_id, balance |
deposit_transactions |
거래 내역 | user_id, amount, status |
bank_notifications |
SMS 파싱 | depositor_name, amount, bank |
AI Fallback: OpenAI 미설정 시 Workers AI (Llama 3.1 8B) 자동 전환
Key Patterns
Function Calling 추가 방법
// 1. openai-service.ts의 tools 배열에 추가
const tools = [
// ... 기존 도구들
{
type: "function",
function: {
name: "new_tool",
description: "도구 설명",
parameters: { /* JSON Schema */ }
}
}
];
// 2. executeFunctionCall()에 케이스 추가
case 'new_tool':
return await executeNewTool(args);
프로필 시스템 흐름
메시지 수신 → message_buffer 저장 (최대 19개)
↓ 20개 도달
사용자 발언만 추출 → OpenAI 분석
↓
summaries 테이블 저장 (generation++)
↓
구버전 삭제 (최근 3개만 유지)
Context Enrichment
// getConversationContext() 반환값 구조
{
profile: "이전 프로필 요약",
recentMessages: [ /* 최근 10개 */ ]
}
// → AI 프롬프트의 system 메시지에 포함
AI 시스템 프롬프트 (summary-service.ts)
- 날씨, 시간, 계산, 검색 등의 요청은 제공된 도구를 사용하세요.
- 예치금, 입금, 충전, 잔액, 계좌 관련 요청은 반드시 manage_deposit 도구를 사용하세요.
금액 제한이나 규칙을 직접 판단하지 마세요.
- 도메인 관련 요청은 반드시 manage_domain 도구를 사용하세요.
- manage_deposit, manage_domain 도구 결과는 그대로 전달하세요.
추가 질문이나 "도움이 필요하시면~" 같은 멘트를 붙이지 마세요.
중요: 메인 AI가 도구를 호출하지 않고 직접 답변하는 경우:
- 시스템 프롬프트에 해당 키워드 추가 (
summary-service.ts:252-254) - 도구 description에 키워드 명시 (
openai-service.tstools 배열)
Deposit Agent 프롬프트 수정 방법
# Vault에서 API 키 조회
curl -s -H "X-Vault-Token: hvs.xxx" https://vault.anvil.it.com/v1/secret/data/openai
# Assistant 프롬프트 업데이트
curl -X POST 'https://api.openai.com/v1/assistants/asst_XMoVGU7ZwRpUPI6PHGvRNm8E' \
-H 'Authorization: Bearer sk-xxx' \
-H 'OpenAI-Beta: assistants=v2' \
-d @update-agent.json
Configuration
wrangler.toml 환경변수:
| 변수 | 기본값 | 설명 |
|---|---|---|
SUMMARY_THRESHOLD |
20 | 프로필 업데이트 주기 (메시지 수) |
MAX_SUMMARIES_PER_USER |
3 | 유지할 프로필 버전 수 |
DOMAIN_AGENT_ID |
- | 도메인 관리 Assistant ID |
DOMAIN_OWNER_ID |
- | 도메인 관리 권한 Telegram ID |
DEPOSIT_AGENT_ID |
- | 예치금 관리 Assistant ID |
DEPOSIT_ADMIN_ID |
- | 예치금 관리 권한 Telegram ID |
BANK_API_SECRET |
- | 입금 알림 API 인증 키 (wrangler secret) |
BRAVE_API_KEY |
- | Brave Search API 키 (wrangler secret) |
External Integrations
| 서비스 | 용도 | 엔드포인트 | 주의사항 |
|---|---|---|---|
| Context7 | 문서 조회 | context7.com API | - |
| Domain Agent | 도메인 관리 | OpenAI Assistants | asst_MzPFKoqt7V4w6bc0UwcXU4ob |
| Deposit Agent | 예치금 관리 | OpenAI Assistants | asst_XMoVGU7ZwRpUPI6PHGvRNm8E |
| Namecheap API | 도메인 백엔드 | namecheap-api.anvil.it.com | 날짜: MM/DD/YYYY → ISO 변환 |
| WHOIS API | WHOIS 조회 | whois-api-eight.vercel.app | ccSLD 미지원 |
| wttr.in | 날씨 | wttr.in | - |
| Brave Search | 검색 | api.search.brave.com | Free AI 플랜 (2,000/월) |
| Vault | API 키 관리 | vault.anvil.it.com | - |
| Gmail | 입금 SMS 수신 | deposit.anvil@gmail.com | Apps Script 연동 |
| Apps Script | Gmail → Worker 연동 | script.google.com | 1분마다 실행, message_id 중복 방지 |
Deposit System
자동 매칭 흐름:
[시나리오 1: 사용자 먼저]
"홍길동 50000원 입금" → bank_notifications 검색
↓
매칭 O → confirmed + 잔액↑ | 매칭 X → pending
[시나리오 2: SMS 먼저 - Gmail → Apps Script → Worker]
은행 SMS → Gmail(deposit.anvil@gmail.com) → Apps Script (1분마다)
↓
POST /api/bank-notification
↓
파싱 → bank_notifications 저장
↓
deposit_transactions 검색 (pending)
↓
매칭 O → confirmed + 잔액↑ + 사용자/관리자 알림
매칭 X → 저장만 + 관리자 알림
알림 시스템:
| 이벤트 | 사용자 알림 | 관리자 알림 |
|---|---|---|
| 자동 매칭 성공 | ✅ 입금액 + 현재 잔액 | ✅ 입금 정보 + 매칭 완료 |
| 매칭 대기 (SMS만) | - | ✅ 입금 정보 + 대기 상태 |
Gmail → Worker 연동:
- Gmail 계정:
deposit.anvil@gmail.com - Apps Script: 1분마다
is:unread 입금검색 → Worker API 호출 - 중복 방지: Gmail message_id 기반
API 엔드포인트:
POST /api/bank-notification
Content-Type: application/json
{
"content": "[Web발신]\n하나,01/16, 23:30\n427******27104\n입금5원\n황병하",
"messageId": "19bc737b3415596a",
"secret": "BANK_API_SECRET 값"
}
입금 계좌: 하나은행 427-910018-27104 (주식회사 아이언클래드)
- Vault 경로:
secret/companies/ironclad-corp
Deposit Agent 핵심 규칙:
1. 금액 제한 없음: 1원도 입금 가능
2. 입금 신고 시 반드시 입금자명 + 금액 확인 (빠지면 물어보기)
3. "계좌번호 주세요" → get_account_info 호출
4. 자연어 금액 인식: "만원"→10000, "5천원"→5000, "삼만오천원"→35000
5. 즉시 실행: 입금자명+금액 있으면 확인 없이 바로 request_deposit 호출
6. 간편 취소: "취소해줘" → 최근 pending 자동 선택
7. 동시 요청 허용: 기존 pending 있어도 새 입금 신고 가능
Deposit Agent 응답 포맷:
잔액 조회: "현재 잔액: 10,000원"
입금 성공: "입금 확인! 5,000원 충전. 잔액: 15,000원"
입금 대기: "입금 요청 등록! 은행 확인 후 자동 충전됩니다."
거래 내역: "#5: 입금 10원 ✓ (01/17)" (✓확인, ⏳대기, ✗취소)
Deposit Agent 도구:
| 함수 | 설명 | 권한 |
|---|---|---|
get_balance |
잔액 조회 | 모든 사용자 |
get_account_info |
입금 계좌 안내 | 모든 사용자 |
request_deposit |
입금 신고 | 모든 사용자 |
get_transactions |
거래 내역 | 모든 사용자 |
cancel_transaction |
입금 취소 | 모든 사용자 |
get_pending_list |
대기 목록 | 관리자 |
confirm_deposit |
입금 확인 | 관리자 |
reject_deposit |
입금 거절 | 관리자 |
Domain System
도구 목록:
| 도구 | 권한 | 설명 |
|---|---|---|
list_domains |
소유자 | 도메인 목록 |
get_domain_info |
소유자 | 상세 정보 (만료일 등) |
get_nameservers |
공개 | 네임서버 조회 |
set_nameservers |
소유자 | 네임서버 변경 |
get_price |
공개 | TLD 가격 (원화) |
check_domains |
공개 | 가용성 확인 |
whois_lookup |
공개 | WHOIS 조회 |
가격 정책: Namecheap 원가 + 13%, 매일 환율 업데이트
권한 체크: user_domains 테이블 verified=1