OmniAI Automation
WhatsApp, Instagram, Facebook 및 X 전반에 걸친 통합 AI 자동화 기능을 제공합니다. 모든 채널에서 오는 메시지는 하나의 형태와 하나의 대기열(queue)로 도착합니다. AI가 확신하는 내용에 대해서는 답변하고, 나머지 모든 내용은 이유와 함께 담당자에게 전달합니다.
n8n이 오케스트레이션(orchestrates)을 수행하며, FastAPI가 데이터 모델(data model), AI 레이어 및 API를 소유합니다. React는 콘솔(console)을 제공합니다.
<img width="960" height="540" alt="Screenshot 2026-08-08 051554" src="https://github.com/user-attachments/assets/3412f854-8e9f-48e4-9ff8-ae298f0ff4f8" />
<img width="960" height="540" alt="Screenshot 2026-08-08 051406" src="https://github.com/user-attachments/assets/c379d773-d554-4eda-ad27-2d53c3533293" />
<img width="960" height="540" alt="Screenshot 2026-08-08 054421" src="https://github.com/user-attachments/assets/bd63ed79-7cd4-49f6-addc-45fa331f3dd8" />
<img width="960" height="540" alt="Screenshot 2026-08-08 051642" src="https://github.com/user-attachments/assets/b2205afd-9ef2-46d4-97ea-a6a43883c5a1" />
<img width="960" height="540" alt="Screenshot 2026-08-08 051635" src="https://github.com/user-attachments/assets/0e8f6d73-0a98-4171-8ac8-bfb573882b1b" />
---
빌드 상태(Build status)
이 프로젝트는 점진적으로 구축되었으며, 아래의 상태는 정확합니다. 구현 및 테스트되지 않은 항목은 '완료(done)'로 표시되지 않았습니다.
| 단계 | 범위 | 상태 |
|---|
| 1 | Docker, Postgres, Redis, FastAPI, React, n8n | 완료 |
| ... | | |
채널 어댑터(channel adapters)에 대해서는 특히: webhook 파싱 및 시그니처 검증(signature verification)은 구현되었고 포획된 페이로드(captured payloads)를 대상으로 단위 테스트(unit-tested)가 완료되었습니다. 아웃바운드 전송(Outbound sending)은 각 플랫폼의 문서화된 엔드포인트(documented endpoints)에 맞춰 작성되었지만, 라이브 비즈니스 계정(live Business accounts)이 필요하기 때문에 종단 간(end to end) 검증은 이루어지지 않았습니다. 자격 증명(credentials)을 구성하지 않은 경우, 어댑터는 성공한 척하는 대신 명시적인 실패와 설정 지침을 반환합니다. docs/integrations.md를 참조하십시오. | | |
빠른 시작(Quick start)
git clone <your-repo> omni-ai-automation
cd omni-ai-automation
...
그 다음으로:`}**
make init을 실행하면 JWT_SECRET, CREDENTIAL_ENCRYPTION_KEY, INTERNAL_SERVICE_TOKEN, N8N_ENCRYPTION_KEY 및 데이터베이스 비밀번호에 대한 실제 값이 생성됩니다. 실제 분류(classification)를 원한다면 .env 파일에 OPENAI_API_KEY를 추가하세요. 이것이 없으면 라우터는 결정론적 키워드 스텁(deterministic keyword stub)을 실행하여 파이프라인이 여전히 오프라인에서 작동하도록 합니다.
전체 명령어 목록은 make help을 실행하여 확인하세요.
플랫폼 자격 증명 없이도 작동합니다
자격 증명이 없는 경우 모든 채널은 모의 어댑터(mock adapter)로 폴백(fallback)합니다. 이 모의 어댑터는 전송을 수락하고 기록하며, 나타나는 모든 곳에서 **자신을 샌드박스(sandbox)**로 레이블링합니다. 대시보드의 어떤 것도 모의 전달(mock delivery)을 실제 전달로 오인할 수 없습니다.
Meta 또는 X 계정 없이 전체 파이프라인을 연습해 보세요:
curl -X POST http://localhost:5678/webhook/whatsapp \
-H 'Content-Type: application/json' \
--data @n8n/test-payloads/whatsapp-text.json
해당 메시지는 정규화(normalization), 저장소(storage), AI 라우팅을 거쳐 자동 응답 또는 승인 대기열 중 하나로 전달됩니다.
아키텍처
React Console
│
REST / WebSocket
...
n8n이 페이로드(payload)를 자체적으로 파싱하고 자격 증명을 보유하는 대신 백엔드를 호출하는 핵심 결정 사항은 ADR-001에 문서화되어 있습니다. 요약하자면: 페이로드 파싱은 테스트된 Python에서 처리되며, 테넌트 격리(tenant isolation)는 단 하나의 구현 방식을 가지고 있고, 내보내진 워크플로우 JSON에는 비밀 정보가 포함되지 않습니다.
통합 메시지 (The unified message)
모든 플랫폼 페이로드는 다른 어떤 것이 보기 전에 이 형태로 변환됩니다:
{
"platform": "instagram",
"external_user_id": "12345",
...
}
AI 레이어는 원시 플랫폼 페이로드(raw platform payload)를 절대 보지 않습니다. 다섯 번째 채널을 추가하는 것은 어댑터 하나만 작성하고 다른 것은 변경하지 않음을 의미합니다.
멱등성 (Idempotency)
Meta는 200 응답을 받을 때까지 약 24시간 동안 웹훅(webhooks)을 재시도합니다. 데이터 수집(Ingestion)은 (organization_id, platform, external_message_id)를 기준으로 키가 지정되므로, 재전송 시 기존 행을 찾아 created: false를 반환하며 — 대화 카운터는 움직이지 않고 두 번째 AI 답변이 발생하지 않습니다. WF-01도 같은 이유로 모든 AI 호출 이전에 Meta를 인지합니다.
휴먼인더루프(Human-in-the-loop)
모델이 분류합니다. 정책을 결정하지는 않습니다.
| Confidence | Outcome |
|---|
| ≥ 0.90 | Answered automatically |
| ... | |
환불, 불만 사항 및 인식되지 않은 의도는 신뢰도와 관계없이 사람에게 전달됩니다 — 모델이 0.99에서 이를 무효화할 수는 없습니다. 이 규칙은 프롬프트에 있는 것이 아니라 backend/app/ai/router.py의 apply_escalation_policy() 내에 순수하고 직접 테스트 가능한 함수로 존재합니다. AI 서비스가 연결되지 않으면, 라우팅은 폐쇄적으로 실패(fails closed)합니다: 알 수 없는 의도는 곧바로 사람에게 전달됩니다. | |
저장소 레이아웃
backend/app/
core/ config, security, logging, db, redis, errors
models/ SQLAlchemy models (22 entities)
...
보안(Security)
구현된 기능:
- Argon2id 비밀번호 해싱; 계정 누락과 잘못된 비밀번호가 동일한 시간이 걸리도록 시간 균등화(timing-equalised) 로그인 구현
- 짧은 수명의 JWT 접근 토큰; 리디스(Redis) 디나일리스트와 포스트그레스(Postgres) 감사 추적을 사용하여 재설정 토큰이 사용될 때마다 순환합니다. 재생된 토큰은 잠재적인 유출로 기록됩니다.
- 모든 요청에서 멤버십을 재확인하여, 권한이 취소된 좌석이 토큰 만료 시점이 아닌 즉시 작동을 멈추게 합니다.
- 채널 자격 증명은 저장 시 페르네트(Fernet) 암호화됩니다. 평문은 어떤 응답으로도 직렬화되지 않습니다.
compare_digest를 사용한 웹훅 서명 검증 (Meta HMAC-SHA256, X base64 HMAC)
- 모든 쿼리에서 조직 격리가 적용됩니다. 잘못된 테넌트 ID는 누락된 경우와 구별할 수 없는 404를 반환합니다.
- 비밀번호/토큰/비밀(secret)/키에 일치하는 모든 키를 자동으로 마스킹(redaction)하는 구조화된 로깅
- 속도 제한(Rate limiting), CORS 허용 목록(allowlist), 보안 헤더, 모든 입력에 대한 Pydantic 유효성 검사
- 프로덕션 시작 시 안전하지 않은 설정(기본 JWT 비밀값, 누락된 암호화 키, 와일드카드 CORS)에서는 부팅을 거부합니다.
/api/internal/*는 서비스 토큰으로 보호되며 브라우저에서 접근할 수 없습니다.
아직 할 일 (Step 19): 환경 변수 대신 channel_credentials에 테넌트별 자격 증명 저장, n8n에서 백엔드 로그로의 요청 ID 전파, 내부 API 버전 관리.
테스트
테스트는 인메모리(in-memory) SQLite를 대상으로 실행됩니다. conftest.py가 테스트 방언에 JSONB 및 UUID 렌더링을 가르쳐, 프로덕션 스키마가 테스트 용이성을 위해 약화되는 일이 없도록 합니다.
오늘 커버리지: 비밀번호 해싱 및 JWT 수명 주기, 자격 증명 암호화, 웹훅 서명 검증(변조된 본문 및 누락된 비밀 케이스 포함), 네 가지 플랫폼 전체에 대한 어댑터 정규화(텍스트, 미디어, 에코, 댓글, 잘못된 페이로드 포함), 수집의 Idempotency 및 테넌트 격리, 상태 업데이트 순서, 그리고 경계를 포함한 에스컬레이션 정책.
문서화
| 문서 | 내용 |
|---|
| ADR-001 | n8n과 백엔드의 분리가 그 위치에 있는 이유 |
| ... | |
라이선스
MIT. 자세한 내용은 [LICENSE]를 참조하십시오.