diff --git a/docs/superpowers/specs/2026-04-11-agent-office-design.md b/docs/superpowers/specs/2026-04-11-agent-office-design.md new file mode 100644 index 0000000..8776224 --- /dev/null +++ b/docs/superpowers/specs/2026-04-11-agent-office-design.md @@ -0,0 +1,444 @@ +# Agent Office - AI 에이전트 사무실 시각화 설계 + +## 개요 + +Lab 하위에 2D 픽셀아트 스타일의 가상 사무실을 구현하여, AI 에이전트들이 실시간으로 작업하는 모습을 게임처럼 시각화하고 상호작용하는 페이지. + +### 핵심 컨셉 +- **게임 같은 사무실**: 2D 픽셀아트 오픈 오피스에 에이전트 캐릭터들이 배치 +- **실제 작업 수행**: 에이전트들이 기존 백엔드 서비스 API를 호출하여 실제 결과물 생성 +- **직접 지시**: 에이전트 클릭 → 채팅/명령 패널로 지시, 승인 요청 시 알림 표시 +- **텔레그램 양방향**: 알림 발송 + 인라인 버튼으로 승인/거절/수정 +- **아이들 행동**: 장시간 명령 없으면 휴게실에서 커피, 졸기, 동료 잡담 등 + +### MVP 범위 +- **에이전트 2개**: StockAgent (주식 뉴스/주가 알람), MusicAgent (작곡 파이프라인) +- **사무실**: 단일 오픈 오피스 (향후 방/층 확장 가능) +- **텔레그램**: 양방향 (알림 + 인라인 버튼 승인) + +--- + +## 1. 아키텍처 + +``` +┌─────────────────────────────────────────────────┐ +│ Frontend (React) │ +│ │ +│ ┌──────────────┐ ┌─────────────────────────┐ │ +│ │ OfficeCanvas │ │ React Overlay │ │ +│ │ (Canvas 2D) │ │ - ChatPanel │ │ +│ │ - 타일맵 렌더 │ │ - AgentStatus │ │ +│ │ - 스프라이트 │ │ - TaskHistory │ │ +│ │ - 클릭 히트맵 │ │ - ApprovalDialog │ │ +│ └──────────────┘ └─────────────────────────┘ │ +│ │ +│ ┌──────────────────────────────────────────┐ │ +│ │ useAgentManager (상태 + WebSocket) │ │ +│ └──────────────────────────────────────────┘ │ +└──────────────────┬──────────────────────────────┘ + │ WebSocket + REST +┌──────────────────▼──────────────────────────────┐ +│ Backend: agent-office (새 서비스, 포트 18900) │ +│ │ +│ ┌────────────┐ ┌────────────┐ ┌──────────────┐ │ +│ │ Scheduler │ │ Agent FSM │ │ Telegram Bot │ │ +│ │(APScheduler)│ │ (상태머신) │ │ (양방향) │ │ +│ └────────────┘ └────────────┘ └──────────────┘ │ +│ │ +│ ┌──────────────────────────────────────────┐ │ +│ │ Service Proxy (기존 서비스 API 호출) │ │ +│ │ stock-lab / music-lab 등 │ │ +│ └──────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────┘ +``` + +### 핵심 결정 +- **agent-office**: 새 백엔드 서비스 (포트 18900). 기존 서비스는 수정하지 않음 +- **Service Proxy 패턴**: agent-office가 기존 서비스 API를 HTTP 호출 +- **WebSocket**: 에이전트 상태 변화를 실시간 전달 +- **Canvas + React 오버레이 하이브리드**: 게임 렌더링은 Canvas, UI 패널은 React DOM + +--- + +## 2. 에이전트 상태 머신 (FSM) + +### 상태 전이 + +``` +┌──────┐ 스케줄/지시 ┌──────────┐ 완료 ┌──────────┐ +│ idle │ ──────────────→ │ working │ ───────→ │ reporting│ +└──┬───┘ └────┬─────┘ └────┬─────┘ + │ │ 승인 필요 │ + │ 장시간 idle ▼ │ 결과 전달 후 + │ ┌───────────┐ │ + ▼ │ waiting │ │ +┌──────┐ │ (승인대기) │ │ +│ break│ └───────────┘ │ +│ (휴식)│ │ +└──┬───┘◄───────────────────────────────────────────┘ + │ 새 작업 발생 + └──────────→ idle +``` + +### 상태별 시각화 + +| 상태 | 캐릭터 행동 | 위치 | 오버레이 | +|------|------------|------|---------| +| `idle` | 모니터 보며 대기 애니메이션 | 자기 데스크 | 없음 | +| `working` | 타이핑 애니메이션, 모니터에 진행 표시 | 자기 데스크 | 작업명 말풍선 | +| `waiting` | 살짝 좌우 흔들림 | 자기 데스크 | `❗` 아이콘 (클릭 유도) | +| `reporting` | 결과물 들고 걸어감 | 데스크 → 회의 테이블 | 결과 요약 말풍선 | +| `break` | 커피 마시기/졸기/산책/잡담 | 휴게실/복도 | `☕`/`💤` 아이콘 | + +### 아이들 행동 규칙 +- idle 상태 5분 경과 → 50% 확률로 break 전환 +- break 지속: 1~3분 랜덤 → idle 복귀 +- break 중 에이전트끼리 근처에 있으면 잡담 애니메이션 +- 새 작업 발생 시 즉시 break 종료 → idle → working + +### 승인 흐름별 분류 + +| 에이전트 | 자동 실행 | 승인 필요 | +|---------|----------|----------| +| Stock | 뉴스 요약, 주가 알람 | - | +| Music | - | 작곡 (프롬프트 확인 후) | +| Lotto (향후) | 통계 분석, 추천번호 | 구매 관련 | +| Blog (향후) | - | 키워드 제시 후 글 생성 | +| Realestate (향후) | 공고 수집, 매칭 | - | +| Claude AI (향후) | - | 직접 지시 + 승인 | + +--- + +## 3. 사무실 맵 & 렌더링 + +### 타일맵 구조 (MVP: 단일 오픈 오피스) + +``` +┌─────────────────────────────────────────┐ +│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │ +│ │Stock│ │Music│ │Claude│ │ (빈) │ │ +│ │Desk │ │Desk │ │Desk │ │향후용│ │ +│ └─────┘ └─────┘ └─────┘ └─────┘ │ +│ │ +│ ┌───────────┐ │ +│ │ 회의 테이블 │ │ +│ │ (보고구역) │ │ +│ └───────────┘ │ +│ │ +│ ┌──────────┐ ┌─────────────────┐ │ +│ │ 휴게실 │ │ CEO 데스크 (나) │ │ +│ │ coffee │ │ │ │ +│ └──────────┘ └─────────────────┘ │ +└─────────────────────────────────────────┘ +``` + +### 렌더링 계층 (아래→위) +1. **바닥 타일**: 카펫, 나무 바닥 +2. **가구**: 데스크, 의자, 소파, 화분, 커피머신 +3. **캐릭터**: 에이전트 스프라이트 (상태별 애니메이션) +4. **오버레이**: 말풍선, 상태 아이콘, 이름표 + +### 스프라이트 에셋 +- 무료 픽셀아트 에셋팩 활용 (타일셋, 가구) +- 에이전트 캐릭터: 기본 인물 스프라이트 + 액세서리로 구분 + - Stock: 넥타이 + 차트 모니터 + - Music: 헤드폰 + 음표 이펙트 + - Claude: 보라색 톤 + AI 아이콘 +- 스프라이트시트: 4방향 × 4프레임 (idle, walk, work, break) + +### Canvas 렌더링 엔진 +- **게임 루프**: `requestAnimationFrame` 기반, 60fps 타겟 +- **카메라**: 고정 뷰 (MVP), 향후 줌/팬 추가 가능 +- **클릭 히트맵**: 캐릭터 바운딩 박스 체크 → 클릭 시 React 이벤트 발생 +- **이동**: 웨이포인트 기반 lerp (데스크↔회의실↔휴게실) + +--- + +## 4. 백엔드: agent-office 서비스 + +### 파일 구조 + +``` +agent-office/ +├── app/ +│ ├── main.py # FastAPI + WebSocket + lifespan +│ ├── db.py # SQLite (agent_tasks, agent_logs, agent_config) +│ ├── config.py # 환경변수, 서비스 URL 설정 +│ ├── scheduler.py # APScheduler 스케줄 관리 +│ ├── telegram_bot.py # Telegram Bot API 양방향 +│ ├── websocket_manager.py # WebSocket 연결 관리 + 브로드캐스트 +│ ├── service_proxy.py # 기존 서비스 API 호출 래퍼 +│ ├── agents/ +│ │ ├── base.py # BaseAgent (FSM, 공통 로직) +│ │ ├── stock.py # StockAgent +│ │ └── music.py # MusicAgent +│ └── models.py # Pydantic 모델 +├── Dockerfile +└── requirements.txt +``` + +### DB 테이블 (agent_office.db) + +**agent_config** +| 컬럼 | 타입 | 설명 | +|------|------|------| +| agent_id | TEXT PK | 에이전트 식별자 (stock, music, ...) | +| display_name | TEXT | 표시명 ("주식 트레이더") | +| enabled | BOOLEAN | 활성 상태 | +| schedule_config | TEXT (JSON) | 스케줄 설정 | +| custom_config | TEXT (JSON) | 에이전트별 커스텀 설정 (감시 종목 등) | +| created_at | TEXT | 생성 시각 | +| updated_at | TEXT | 수정 시각 | + +**agent_tasks** +| 컬럼 | 타입 | 설명 | +|------|------|------| +| id | TEXT PK (UUID) | 작업 ID | +| agent_id | TEXT FK | 에이전트 | +| task_type | TEXT | 작업 유형 (news_summary, price_alert, compose, ...) | +| status | TEXT | pending / approved / working / succeeded / failed | +| input_data | TEXT (JSON) | 입력 파라미터 | +| result_data | TEXT (JSON) | 결과 데이터 | +| requires_approval | BOOLEAN | 승인 필요 여부 | +| approved_at | TEXT | 승인 시각 | +| approved_via | TEXT | 승인 경로 (web / telegram) | +| created_at | TEXT | 생성 시각 | +| completed_at | TEXT | 완료 시각 | + +**agent_logs** +| 컬럼 | 타입 | 설명 | +|------|------|------| +| id | INTEGER PK | 자동 증가 | +| agent_id | TEXT FK | 에이전트 | +| task_id | TEXT FK | 관련 작업 (nullable) | +| level | TEXT | info / warn / error | +| message | TEXT | 로그 메시지 | +| created_at | TEXT | 시각 | + +**telegram_state** +| 컬럼 | 타입 | 설명 | +|------|------|------| +| callback_id | TEXT PK | 텔레그램 콜백 ID | +| task_id | TEXT FK | 매핑된 작업 | +| agent_id | TEXT FK | 매핑된 에이전트 | +| action | TEXT | approve / reject / modify | +| responded | BOOLEAN | 응답 완료 여부 | +| created_at | TEXT | 생성 시각 | + +### BaseAgent 인터페이스 + +```python +class BaseAgent: + agent_id: str + state: str # idle, working, waiting, reporting, break + + async def on_schedule(self) -> None: + """스케줄러에 의해 호출. 자동 작업 실행.""" + + async def on_command(self, command: str, params: dict) -> dict: + """사용자 직접 지시 처리.""" + + async def on_approval(self, task_id: str, approved: bool, feedback: str) -> None: + """승인/거절 콜백.""" + + async def get_status(self) -> dict: + """현재 상태 + 최근 작업 요약.""" +``` + +### MVP 에이전트 상세 + +**StockAgent:** +- 스케줄: 매일 08:00 `on_schedule()` → `stock-lab GET /api/stock/news` 호출 +- AI 요약: 뉴스 데이터를 Ollama(192.168.45.59)로 요약 생성 +- 텔레그램 전송: 요약 결과를 포맷팅하여 발송 (자동, 승인 불필요) +- 주가 알람: `agent_config.custom_config`에 감시 종목/조건 저장, 주기적 체크 +- 상태 전이: idle → working(뉴스 수집) → reporting(텔레그램 전송) → idle + +**MusicAgent:** +- 트리거: 사용자 웹/텔레그램 지시 → `on_command()` +- 프롬프트 확인: 사용자 입력 프롬프트를 텔레그램으로 전송 + 인라인 버튼 +- 승인 시: `music-lab POST /api/music/generate` 호출 +- 상태 폴링: `music-lab GET /api/music/status/{task_id}` → 완료까지 반복 +- 결과 알림: 생성된 음악 URL을 텔레그램 + 웹에 전달 +- 상태 전이: idle → waiting(프롬프트 승인 대기) → working(생성 중) → reporting(결과 전달) → idle + +--- + +## 5. 텔레그램 봇 + +### 구성 +- **Telegram Bot API** + **Webhook 수신** (NAS에서) +- agent-office 서비스 내부에 통합 (별도 프로세스 아님) +- Nginx: `/api/agent-office/telegram/webhook` → `agent-office:8000` + +### 환경변수 +- `TELEGRAM_BOT_TOKEN`: Bot Father에서 발급 +- `TELEGRAM_CHAT_ID`: 사용자 채팅 ID (1:1 봇) +- `TELEGRAM_WEBHOOK_URL`: Webhook 수신 URL (NAS 외부 접근 가능 URL) + +### 메시지 포맷 + +**자동 알림 (뉴스 요약):** +``` +📈 [주식 에이전트] 아침 뉴스 요약 +━━━━━━━━━━━━━━━━ +• 삼성전자: 반도체 수출 호조... +• 코스피: 외인 순매수 전환... +• 미국 CPI 발표 예정... + +📊 관심종목 현황 +삼성전자 82,500원 (+2.1%) +AAPL $185.20 (+1.2%) +``` + +**승인 요청 (작곡):** +``` +🎵 [음악 에이전트] 작곡 요청 +━━━━━━━━━━━━━━━━ +프롬프트: "Lo-fi hip hop, rainy day, piano" +스타일: Chill, Ambient +모델: V5.5 + +[✅ 승인] [❌ 거절] [✏️ 수정] +``` + +**주가 알람:** +``` +🚨 [주식 에이전트] 주가 알림 +━━━━━━━━━━━━━━━━ +삼성전자 82,500원 +조건: 82,000원 이상 → 도달! +현재 등락: +2.1% +``` + +### 양방향 흐름 +1. 에이전트 → `telegram_bot.send_message()` → 텔레그램 +2. 사용자 → 인라인 버튼 클릭 or 텍스트 입력 +3. 텔레그램 → Webhook POST → `telegram_bot.handle_webhook()` +4. `handle_webhook()` → `telegram_state` 조회 → 에이전트 `on_approval()` 호출 +5. 에이전트 FSM 상태 전이 → WebSocket 브로드캐스트 → 프론트엔드 반영 + +--- + +## 6. 프론트엔드 구조 + +### 파일 구조 + +``` +src/pages/agent-office/ +├── AgentOffice.jsx # 메인 페이지 (Canvas + Overlay 컨테이너) +├── AgentOffice.css # 스타일 +├── canvas/ +│ ├── OfficeRenderer.js # Canvas 렌더링 엔진 (게임루프) +│ ├── SpriteSheet.js # 스프라이트시트 로더 + 프레임 애니메이션 +│ ├── TileMap.js # 타일맵 데이터 + 렌더링 +│ └── AgentSprite.js # 에이전트 캐릭터 (위치, 상태, 이동, 애니메이션) +├── components/ +│ ├── ChatPanel.jsx # 에이전트 채팅/명령 패널 +│ ├── AgentBubble.jsx # 말풍선/상태 아이콘 오버레이 +│ ├── TaskHistory.jsx # 작업 이력 사이드패널 +│ └── ApprovalDialog.jsx # 승인 요청 다이얼로그 +├── hooks/ +│ ├── useAgentManager.js # WebSocket + 에이전트 상태 관리 +│ └── useOfficeCanvas.js # Canvas 초기화 + 이벤트 바인딩 +└── assets/ + ├── tileset.png # 사무실 타일셋 (16x16 or 32x32) + ├── agents.png # 에이전트 스프라이트시트 + └── office-map.json # 타일맵 데이터 +``` + +### WebSocket 프로토콜 + +**서버 → 클라이언트:** +```json +{"type": "agent_state", "agent": "stock", "state": "working", "detail": "뉴스 수집 중..."} +{"type": "agent_state", "agent": "music", "state": "waiting", "detail": "프롬프트 승인 대기", "task_id": "abc-123"} +{"type": "task_complete", "agent": "stock", "task_id": "...", "result": {"summary": "..."}} +{"type": "agent_move", "agent": "stock", "target": "break_room"} +``` + +**클라이언트 → 서버:** +```json +{"type": "command", "agent": "music", "action": "compose", "params": {"prompt": "...", "style": "..."}} +{"type": "approval", "agent": "music", "task_id": "abc-123", "approved": true} +{"type": "query", "agent": "stock", "action": "status"} +``` + +### ChatPanel 기능 +- 에이전트별 채팅 히스토리 표시 +- 텍스트 입력 + 빠른 액션 버튼 +- 승인 대기 중인 작업 강조 표시 +- 최근 작업 결과 인라인 표시 + +--- + +## 7. 인프라 변경 + +### Docker Compose 추가 + +```yaml +agent-office: + build: ./agent-office + container_name: agent-office + ports: + - "18900:8000" + volumes: + - ${RUNTIME_PATH}/data:/app/data + environment: + - TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN} + - TELEGRAM_CHAT_ID=${TELEGRAM_CHAT_ID} + - TELEGRAM_WEBHOOK_URL=${TELEGRAM_WEBHOOK_URL} + - STOCK_LAB_URL=http://stock-lab:8000 + - MUSIC_LAB_URL=http://music-lab:8000 + depends_on: + - stock-lab + - music-lab + restart: unless-stopped +``` + +### Nginx 라우팅 추가 + +```nginx +location /api/agent-office/ { + proxy_pass http://agent-office:8000; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; # WebSocket 지원 +} +``` + +### 라우팅 (React Router) + +```javascript +// routes.jsx +{ path: 'agent-office', lazy: () => import('./pages/agent-office/AgentOffice') } +``` + +Lab 페이지(EffectLab.jsx)의 LAB_ITEMS에 Agent Office 항목 추가. + +--- + +## 8. 향후 확장 (Phase 2+) + +| 단계 | 내용 | +|------|------| +| Phase 2 | LottoAgent, BlogAgent, RealestateAgent 추가 | +| Phase 3 | Claude AI Agent (자연어 복합 지시) | +| Phase 4 | 방/층 확장 (부서별 공간 분리) | +| Phase 5 | 에이전트 간 협업 시각화 (회의 테이블에서 토론) | +| Phase 6 | 에이전트 커스텀 (이름, 외형, 성격 설정) | + +--- + +## 9. 기술 스택 요약 + +| 레이어 | 기술 | +|--------|------| +| 사무실 렌더링 | HTML5 Canvas 2D (커스텀 엔진) | +| 프론트엔드 | React 18 + Vite | +| 실시간 통신 | WebSocket (FastAPI) | +| 백엔드 | FastAPI (Python 3.12) | +| DB | SQLite (agent_office.db) | +| 스케줄러 | APScheduler | +| 메시징 | Telegram Bot API (Webhook) | +| 서비스 연동 | HTTP Proxy (기존 서비스 API 호출) |