웹 기반 멀티 에이전트 워크플로우 플랫폼. 단일 에이전트 → 정적 워크플로우 → 동적 워크플로우 순으로 점진 확장한다.
- Backend: Python 3.12, FastAPI, LangGraph, LangChain chat models,
uv - Frontend: React 18 + TypeScript + Vite, Tailwind v4, lucide-react, custom components
- LLM: 멀티 프로바이더 (Anthropic / OpenAI / Google) —
backend/config/llm.yaml카탈로그 기반
모노레포. backend/ 와 frontend/ 는 IDE에서 각자 자기 폴더만 열어 작업한다.
multi-agent-system/
backend/ ← PyCharm 등으로 이 폴더를 연다
pyproject.toml
uv.lock
.python-version
.env / .env.example
app/ Python 패키지 (`from app.X import ...`)
main.py FastAPI 엔트리
api/ HTTP / SSE 엔드포인트
llm/ LLM 팩토리 + 모델 카탈로그 로더
agent_core/ 에이전트 레지스트리 + 러너 (graph 모듈로 위임)
workflow/ 워크플로우 YAML 스키마 + 레지스트리
graph/ 워크플로우 상태 / 노드 / 컴파일러 (정적·동적 공용)
api/ /chat (SSE) + /graph/{name} (트레이스용)
agents/ 에이전트 플러그인 (config.yaml + prompt.md)
workflows/ 워크플로우 정의 (YAML DAG, leaf 에이전트 조합)
config/
llm.yaml LLM 프로바이더 / 모델 카탈로그
frontend/ ← VSCode 등으로 이 폴더를 연다
package.json
vite.config.ts dev 서버 + /api → :8000 프록시
src/
App.tsx 레이아웃 (사이드바 + 메인)
api/ /health, /chat (POST + SSE) 클라이언트
hooks/ useAgents, useChat
components/ Sidebar / TopBar / MessageList / Composer 등
cd backend
# 의존성 설치 (.venv 자동 생성)
uv sync
# API 키 설정 — .env 파일 생성
cat > .env <<'EOF'
GOOGLE_API_KEY=...
# ANTHROPIC_API_KEY=...
# OPENAI_API_KEY=...
EOF
# 개발 서버
uv run uvicorn app.main:app --reload백엔드 단독 검증:
http://localhost:8000/health— 등록된 모델 / 에이전트 목록http://localhost:8000/docs— Swagger UI 에서/chat호출 테스트
별도 터미널에서 (백엔드는 계속 켜진 상태):
cd frontend
npm install
npm run devhttp://localhost:5173 에서 콘솔 UI. 프록시가 /api/* → http://localhost:8000/* 로 보내므로 CORS 설정 불필요.
빌드 / 타입체크:
npm run typecheck # tsc -b --noEmit
npm run build # 프로덕션 번들 → dist/Server-Sent Events 로 응답 토큰을 스트리밍한다.
요청 바디:
{
"agent": "chat_agent",
"message": "내 이름은 X 야",
"thread_id": "선택, 미지정시 자동 생성"
}이벤트 타입:
thread— 첫 이벤트, 사용된thread_id. 같은 값으로 다음 요청 보내면 이전 대화 컨텍스트 유지token— 모델 출력 청크error— 에러 발생 시{"type": ..., "message": ...}done— 스트림 종료
대화 상태는 SQLite (backend/var/state.db) 에 저장된다. LangGraph AsyncSqliteSaver 가 체크포인트(메시지 히스토리 + 그래프 상태) 를 담당하고, 별도의 threads 메타데이터 테이블이 사이드바 "최근 대화" 목록 (제목, 에이전트, 메시지 수, 갱신 시각) 을 채운다. 서버 재시작해도 스레드가 살아 있으며, 사이드바에서 클릭하면 이전 대화로 그대로 이어 쓸 수 있다.
backend/agents/<agent_name>/ 폴더를 만들고 두 파일만 두면 부팅 시 자동 등록된다:
# backend/agents/<agent_name>/config.yaml
name: <agent_name>
kind: agent # 또는 "supervisor" — 라우팅용 노드
model: gemini-pro # backend/config/llm.yaml 의 키 참조
temperature: 0.7
prompt: prompt.md
description: <한 줄 설명>
# kind: supervisor 일 때만 사용
delegates_to:
- researcher
- writer
- coder# backend/agents/<agent_name>/prompt.md
You are ...레지스트리 / 러너 코드는 건드리지 않는다. kind: supervisor 인 에이전트는 첫 LLM 호출에서 delegates_to 중 하나로 라우팅하고, 선택된 sub-agent 가 사용자에게 답한다. 프런트는 supervisor 만 사이드바에 노출하고, 실제 답변자는 메시지 라벨로 표시한다.
backend/config/mcp.yaml 에 서버 등록 → 에이전트가 mcp_servers: [<name>] 로 화이트리스트.
# backend/config/mcp.yaml
servers:
filesystem:
transport: stdio
command: npx
args: ["-y", "@modelcontextprotocol/server-filesystem", "~/agent-workspace"]
description: 파일 읽기·쓰기·탐색# backend/agents/coder/config.yaml
name: coder
kind: agent
mcp_servers:
- filesystem # ← 이 에이전트가 사용할 서버앱 부팅 시 모든 MCP 서버에 연결해서 도구 목록 한 번 가져오고 캐시. 에이전트 컴파일 시점에 화이트리스트로 필터링해서 ReAct 에이전트 tools 에 주입. 도구 호출/응답은 tool_call / tool_result SSE 이벤트로 프런트에 흘려보내고, 메시지 안에 인라인 카드로 펼쳐볼 수 있게 렌더.
지원 transport: stdio (서브프로세스), sse, streamable_http. 환경변수 + ~ 확장 지원.
backend/workflows/<name>.yaml 파일 하나로 정적 DAG 정의 가능:
name: research_brief
description: <한 줄 설명>
nodes:
- id: research # 노드 식별자 (그래프 안에서만 유효)
agent: researcher # 등록된 leaf 에이전트 이름
- id: refine
agent: writer
edges:
- from: __start__
to: research
- from: research
to: refine
- from: refine
to: __end__부팅 시 자동 등록되어 /chat 의 agent 파라미터로 호출 가능 (워크플로우와 에이전트는 같은 네임스페이스, 워크플로우가 우선). 트레이스 인스펙터 (오른쪽 사이드 패널) 에서 실행 중 활성 노드가 실시간으로 강조됨.
backend/config/llm.yaml의providers:/models:에 항목 추가backend/app/llm/factory.py의build_chat_model()match문에 새case한 개 추가
이 두 곳 외에 LLM 프로바이더를 알아야 하는 코드는 없다.
- Step 0 — 디렉토리 / 컨벤션 / LLM 팩토리 / 에이전트 레지스트리 골격
- Step 1 —
/chatSSE + LangGraph ReAct 단일 에이전트 + 인메모리 체크포인터 - Step 2 — React + Vite 콘솔 UI (에이전트 선택, 토큰 스트리밍, thread 유지, 에러 인라인 표시)
- Step 3 — 에이전트 실행을 그래프 노드 추상으로 리팩터 (정적/동적 공용 인프라)
- Step 4 — 동적 워크플로우 (슈퍼바이저 + 서브에이전트 라우팅, LLM이 다음 단계 결정)
- Step 5 — 정적 워크플로우 (YAML DAG → LangGraph 컴파일러,
backend/workflows/*.yaml) - Step 6 (lite) — 트레이스 인스펙터 (그래프 토폴로지 + 활성 노드 실시간 강조)
- Step 6 (full) — 드래그&드롭 워크플로우 편집기 (필요해지면)
| 트랙 | 상태 | 설명 |
|---|---|---|
| MCP 통합 | ✅ v1 | filesystem MCP 서버 연동, 에이전트별 화이트리스트, 도구 호출/응답 SSE 이벤트, 프런트 inline 카드 렌더 |
| 영속 저장 | ✅ v1 | AsyncSqliteSaver 체크포인터 + threads 메타데이터 테이블, 사이드바 "최근 대화" 클릭 시 리플레이, 삭제 지원 (검색은 후속) |
| 관측성 | ⏳ | 토큰/비용/지연 per-turn, OpenTelemetry → Langfuse/Phoenix |
| 인증/멀티유저 | ⏳ | SSO, 워크스페이스, RBAC (이때 Spring Boot BFF 도입 검토) |
| UX 폴리시 | ⏳ | 다크모드, syntax highlighting, 메시지 편집/재실행, 모바일 |
| 워크플로우 라이브러리 | ⏳ | 워크플로우 저장/공유/복제, 템플릿, 버전관리 |