KeyP
KeyP API

팀 공유용 API 문서

KeyP의 Planner → Collector → Verifier → Deliverer 파이프라인을 단일 HTTP 엔드포인트로 노출합니다. 다른 팀원은 이 API 하나만 호출하면 관심사에 대한 SNS 기반 실시간 피드를 받을 수 있어요.

🔌 엔드포인트

MethodPath설명
POST/api/public/keyp/search관심사 → AI 분석 → SNS 피드
GET/api/public/keyp/search?interest=…간단 조회용 (동일 결과)

CORS 개방 · 인증 불필요 (해커톤 MVP)

📥 요청 본문

{
  "interest": "string (필수)",     // 자연어 관심사
  "limit":    "number (1~10, 기본 5)",
  "language": "string (기본 'ko')",
  "platforms": ["youtube"|"instagram"|"facebook"|"linkedin"|"x"|"tiktok"|"reddit"|"news"|"blog"|"community"]
}

🧪 cURL 예제

curl -X POST https://<your-domain>/api/public/keyp/search \
  -H "Content-Type: application/json" \
  -d '{"interest":"BTS 월드투어 일정","limit":5,"language":"ko"}'

📘 TypeScript 클라이언트

src/lib/keyp/client.ts — 그대로 복사해서 다른 프로젝트에서도 사용 가능.

import { keypClient } from "@/lib/keyp/client";

const res = await keypClient.search({
  interest: "AI 스타트업 투자 기회",
  platforms: ["linkedin", "news", "x"],
  limit: 5,
});

if (res.ok) {
  for (const item of res.items) {
    console.log(item.headline, item.credibility, item.sources);
  }
}

📤 응답 예시

{
  "ok": true,
  "interest": "BTS 월드투어 일정",
  "plan": {
    "intent": "BTS 월드투어 관련 최신 공식/팬 정보 수집",
    "queries": ["BTS world tour 2025", "BTS 콘서트 일정", ...],
    "targetPlatforms": ["youtube", "x", "news", "instagram"]
  },
  "items": [
    {
      "id": "1720000000000-0",
      "interest": "BTS 월드투어 일정",
      "headline": "BTS 월드투어 앙코르 발표",
      "summary": "2025년 추가 공연 일정과 예매 정보 요약...",
      "keywords": ["BTS", "월드투어", "앙코르"],
      "credibility": 88,
      "sources": [
        { "platform": "youtube", "url": "https://www.youtube.com/results?search_query=BTS+world+tour", "title": "관련 영상" },
        { "platform": "news", "url": "https://news.google.com/search?q=BTS+world+tour", "title": "관련 뉴스" }
      ],
      "createdAt": "2026-07-10T09:00:00.000Z"
    }
  ],
  "generatedAt": "2026-07-10T09:00:00.000Z"
}

⚙️ 내부 파이프라인

  1. Planner — 자연어 관심사를 의도(intent) + 검색쿼리 3~5개 + 타겟 SNS 2~4개로 구조화.
  2. Collector — 타겟 SNS(YouTube / Instagram / Facebook / LinkedIn / X / TikTok / Reddit / 뉴스 / 블로그 / 커뮤니티)에서 후보 정보 수집.
  3. Verifier — 여러 소스 교차검증 후 신뢰도(0~100) 부여.
  4. Deliverer — 요약·중복 제거 후 푸시 가능한 피드 카드로 정제.

현재 Collector는 Lovable AI Gateway(Gemini) 지식을 기반으로 후보를 생성합니다. 실제 실시간 스크래핑이 필요하면 Firecrawl 커넥터를 붙여 collectVerifyDeliver 함수 안의 수집 단계를 교체하세요.

🚀 KeyP × Daytona — Opportunity Agent

KeyP doesn't just find opportunities. It executes the work required to pursue them.
From Interest to Action.

KeyP Planner가 찾은 기회를 실제 Daytona 샌드박스 안에서 실행해 적격성 검증과 지원 서류 패키지를 자동 생성합니다.

KeyP Planner / Verifier
        │  (기회 후보 + 신뢰도)
        ▼
Daytona Sandbox  (isolated, 서버에서만 생성)
        │  opportunity.json + company-profile.json + agent.py
        ▼
Requirements 추출 → Company Profile 비교 → Eligibility 판정
        ▼
Generated Application Package
  /output/eligibility-report.md
  /output/application-draft.md
  /output/submission-checklist.csv

엔드포인트

GET/api/daytona/status{ configured: boolean }
POST/api/daytona/run-opportunity샌드박스 실행 → 지원 패키지
// 요청
{
  "opportunity": { "id": "...", "title": "...", "category": "...", "deadline": "...",
                   "organizer": "...", "location": "...", "matchScore": 92,
                   "why": "...", "url": "https://..." },
  "companyProfile": { "company": "XrisP", "location": "Seoul",
                      "industry": "AI / Content / Education",
                      "companyType": "Startup / SME", "interests": ["AI grants"] },
  "demoMode": false
}

// 응답 (성공)
{ "ok": true, "mode": "real", "sandboxId": "…", "matchScore": 92,
  "eligible": "yes|review|no", "missingDocuments": [...],
  "steps": [...], "log": [...], "files": [{ "name": "...", "content": "..." }],
  "startedAt": "...", "finishedAt": "...", "elapsedMs": 12345 }

// 응답 (시크릿 미설정 — 절대 성공으로 위장하지 않음, HTTP 503)
{ "ok": false, "code": "not_configured", "error": "DAYTONA_API_KEY is not configured..." }

필수 시크릿

DAYTONA_API_KEY — Project Settings → Secrets 에 추가. 서버에서만 읽으며 브라우저에 절대 노출되지 않습니다. (선택: DAYTONA_API_URL, DAYTONA_TARGET, DAYTONA_ORGANIZATION_ID)

REAL vs DEMO

  • REAL RUN — 시크릿이 설정된 경우에만. 실제 Daytona 샌드박스를 생성하고 그 안에서 python3 agent.py를 실행한 뒤 샌드박스를 정리합니다. 응답에 실제 sandbox id가 포함됩니다.
  • DEMO RUNdemoMode: true로 명시적으로 요청할 때만 동작하는 발표 백업용 시뮬레이션입니다. 샌드박스를 만들지 않고, UI·응답 모두 항상 DEMO로 표시됩니다.
  • 시크릿이 없으면 REAL 호출은 절대 가짜 성공을 반환하지 않고 not_configured를 반환합니다.

3분 데모 경로

Dashboard → Opportunities (샘플 1번 선택) → Run Opportunity Agent → Agent Runs 타임라인 → Results. 대시보드 하단의 데모 데이터 초기화 버튼으로 샘플 3건과 실행 기록을 초기 상태로 되돌릴 수 있습니다.

참고: 공식 @daytonaio/sdk는 Node 전용 의존성(opentelemetry sdk-node, tar, fast-glob, ws)으로 이 프로젝트의 엣지 서버 런타임에 번들되지 않습니다. 따라서 동일한 Daytona 클라우드 API를 fetch로 직접 호출하는 얇은 서버 클라이언트(src/lib/daytona/client.server.ts)를 사용합니다.

🛰️ Context Watch — 의도 기반 24/7 감시

KeyP의 "관심사"는 키워드가 아니라 자연어 의도 + 맥락(시간·장소·조건·부정조건)입니다. 입력 문장을 ContextPlan으로 구조화하고, 소스 전략에 따라 검색한 뒤, 근거를 직접 확인하고 조건 일치도를 판정합니다.

1. Intent & Context Reasoner (OpenAI Responses API, 기본 gpt-5.6-terra)
   · ambiguityScore가 높으면 gpt-5.6-sol로 1회 escalation
   · OPENAI_API_KEY 없으면 Lovable AI로 graceful fallback (UI에 fallback 표시)
2. Source Router — ContextPlan.sourceStrategy 우선순위대로
   · X/실시간 소셜 → Grok x_search + web_search
   · 공개 웹/공식 문서 → Gemini Google Search (없으면 Lovable AI 지식 = live search 아님)
   · 데이팅앱/로그인 뒤 개인정보/미성년자 → 접근하지 않음(차단 목록)
3. Direct verification — 후보 URL 실제 HTTP GET, 우회 없음, 실패는 "확인 필요"
4. Daytona — JS 렌더링·PDF·다중 링크가 필요할 때만 on-demand 생성 후 즉시 destroy
5. Evidence-based Match Judge — matchScore / matchedConstraints /
   missingConstraints / contradiction / whyMatched / confidence
6. 알림 기준 미달 결과는 저장·알림하지 않고 "참고용"으로만 표시

엔드포인트 & 저장소

POST /api/watches           자연어 → ContextPlan → DB 저장
GET  /api/watches           watch 목록 + findings
POST /api/watches/:id/run   즉시 실행
POST /api/scheduler/tick    next_run_at <= now() 인 watch를 제한 개수 처리
GET  /api/research/status   엔진 configured boolean + 모델명 (키 값 반환 없음)

DB: context_watches · watch_runs · findings · source_evidence · notification_queue
24/7의 source of truth는 next_run_at. claim_due_watches()가 FOR UPDATE SKIP LOCKED로
행을 선점하므로 tick이 겹쳐도 같은 watch가 중복 실행되지 않습니다.

공개 소스 전용(privacyMode: public_only). 비공개 프로필·로그인/CAPTCHA/robots 우회·미성년자·비공개 개인정보·사진이나 이름 기반 속성 추론은 하지 않습니다. 개인 관련 결과는 본인의 공개 자기진술과 공개 출처 URL이 있을 때만 표시합니다. 현재 앱 로그인 기능이 없어 DB 쓰기는 서버 라우트에서만 수행합니다 — TODO(auth): 로그인 도입 시 owner_id 기반 RLS 정책 추가.

TODO(deploy): 배포 후 /api/scheduler/tick을 15분 주기 cron(pg_cron + pg_net 또는 외부 스케줄러)으로 호출하면 24/7 감시가 완성됩니다. 프리뷰 URL은 하드코딩하지 않았습니다.

🔎 Multi-Source Research Agent (Gemini + Grok + Daytona)

1. Lovable UI / KeyP orchestration
2. Daytona isolated research runtime (모든 수집·검증이 샌드박스 안에서 실행)
3. Gemini — Google Search grounding (공식 출처 우선)
4. Grok — web_search + x_search (X/트위터 발표·커뮤니티 신호)
5. Direct source verification — 후보 URL에 실제 HTTP GET (status/final URL/title/snippet)
6. Evidence fusion — 중복 제거, 출처 등급, 신뢰도 산정
7. Application package generation — eligibility + 지원 서류 초안

엔드포인트

GET/api/research/status{daytonaConfigured, geminiConfigured, grokConfigured, lovableAiAvailable, geminiModel, grokModel}
POST/api/research/opportunities라이브 리서치 → 검증된 기회 목록
// 요청
{ "query": "서울 AI 스타트업 정부지원사업/해커톤", "companyProfile": { ... }, "maxResults": 8 }

// 응답 (성공)
{ "ok": true, "sandboxId": "…", "enginesUsed": ["gemini","grok"], "query": "…",
  "results": [{ "id": "...", "title": "...", "deadline": "공식 공고 확인 필요",
                "url": "https://...", "sample": false,
                "discoveredBy": ["gemini"], "sourceType": "official",
                "sourceEvidence": [{ "engine": "gemini", "url": "...", "statusCode": 200, "snippet": "..." }],
                "xEvidence": [...], "verified": true, "confidence": 84 }],
  "logs": [...], "engineErrors": [...], "elapsedMs": 41234 }

// 응답 (Daytona 미설정 — 가짜 라이브 결과 없음, HTTP 503)
{ "ok": false, "code": "not_configured", "error": "DAYTONA_API_KEY is not configured..." }

시크릿

  • DAYTONA_API_KEY필수. 라이브 샌드박스 리서치/실행.
  • GEMINI_API_KEY — 권장. Google Search 그라운딩 기반 라이브 웹 리서치 (GEMINI_MODEL 기본 gemini-2.5-flash).
  • XAI_API_KEY — 선택(권장). Grok x_search + web_search (GROK_MODEL 기본 grok-4.6).

Cursor 크레딧 안내 — Cursor의 Grok 크레딧은 Cursor 안에서만 적용되며, 배포된 이 KeyP 앱의 XAI_API_KEY 결제로 사용할 수 없습니다. Grok X Search를 켜려면 xAI API 키를 XAI_API_KEY로 추가하세요.

  • GEMINI_API_KEY 미설정 시: 직접 Google Search 그라운딩 없음 — 추론/요약 폴백만 사용하며 라이브 검색이 일어난 것처럼 표기하지 않습니다.
  • XAI_API_KEY 미설정 시: X 결과를 생성하지 않고 상태를 “연결 필요”로 표시합니다.
  • 마감일은 절대 추정하지 않습니다 — 근거가 없으면 “공식 공고 확인 필요”로 남습니다.
  • 소셜 근거만 있는 항목은 Needs verification으로 표시되며 official 사실을 덮어쓰지 않습니다.