Agent는 MCP뿐 아니라 Skill을 활용하여 다양한 기능을 편리하게 구현할 수 있습니다. 여기에서는 LangGraph에서 Agent Skill을 활용하는 방법을 설명합니다.
Web UI는 FastAPI + React이며, Agent는 같은 프로세스의 LangGraph로 실행합니다. (agentic-work는 UI와 AgentCore Runtime을 분리하지만, 이 저장소는 UI·Agent를 application/에 함께 두어 로컬 테스트에 최적화되어 있습니다.)
| 구분 | 경로 | 역할 |
|---|---|---|
| Web UI | application/server.py, application/web/ |
Task·Chat·Skill/MCP 설정, SSE 스트리밍 |
| Agent | application/chat.py → langgraph_agent.py |
LangGraph ReAct + MCP + Skills |
| 설정 | application/config.json, mcp.list, skills.list |
모델·MCP·Skill 기본값 |
Browser (React :8501)
│ REST + SSE (/api/...)
▼
FastAPI (application/server.py)
│ chat.run_agent(...)
▼
LangGraph (langgraph_agent) + MCP + Skills + Bedrock
# 프론트 빌드 후 FastAPI (포트 8501)
./run_local.sh
# 또는
cd application/web && npm install && npm run build && cd ../..
pip install -r requirements.txt
uvicorn application.server:app --host 0.0.0.0 --port 8501브라우저: http://localhost:8501
- 최초 접속 시 User ID를 입력하면 쿠키로 세션이 유지됩니다.
application/config.json에 region, S3, Knowledge Base, Memory 등이 필요합니다. (installer.py로 생성 가능)- Agent는 AgentCore Runtime이 아니라 로컬 LangGraph로 동작합니다.
프론트만 수정할 때:
cd application/web && npm run dev # Vite :5173, /api → :8501 프록시
# 다른 터미널
uvicorn application.server:app --host 0.0.0.0 --port 8501flowchart TB
subgraph UI["Web UI FastAPI + React"]
SPA["web/ React SPA"]
API["server.py / api/*"]
TS[task_store SQLite]
end
subgraph Agent["application/ Agent"]
RA["chat.run_agent"]
RLA["run_langgraph_agent"]
SG["langgraph_agent StateGraph"]
CM[call_model]
TN[ToolNode]
end
subgraph Skills["Skills"]
SM[skill.py SkillManager]
SK["skills/*/SKILL.md"]
GSI[get_skill_instructions]
end
subgraph MCP["MCP"]
CFG[mcp_config.py]
SRV["mcp_server_* / remote gateway"]
CLI[MCPAdapter]
end
subgraph AWS["AWS"]
BR[Bedrock Runtime]
S3[(S3)]
KB[Knowledge Base]
MEM[AgentCore Memory]
end
SPA --> API
API --> TS
API -->|SSE| RA
RA --> RLA
RLA --> SG
SG --> CM
CM --> TN
TN --> CM
CM --> BR
RLA --> CLI
CLI --> SRV
CFG --> SRV
RLA --> GSI
GSI --> SM
SM --> SK
TN --> S3
SRV --> KB
SRV --> MEM
| 기능 | 모듈 | 설명 |
|---|---|---|
| Chat (SSE) | api/routes_chat.py → chat.run_agent |
Task별 스트리밍 대화 |
| Agent | langgraph_agent + MCP/Skills |
ReAct 루프, checkpoint |
| 이미지 | build_human_message_with_files |
멀티모달 HumanMessage로 이미지 전달 |
| RAG 업로드 | api/routes_rag.py |
사용자별 S3 업로드 + metadata + Knowledge Base sync (RAG) |
| Memory | Sidebar Memory 토글 + MCP memory |
AgentCore Memory 저장/조회 |
| 레이어 | 스택 |
|---|---|
| Backend | FastAPI, uvicorn (application.server:app, port 8501) |
| Frontend | React 19 + TypeScript + Vite (application/web/) |
| 영속화 | SQLite application/data/tasks.db (로컬) |
| Auth | HttpOnly 쿠키 agent_user_id |
| Method | Path | 설명 |
|---|---|---|
| GET/POST/DELETE | /api/session |
사용자 세션 쿠키 |
| GET/PATCH | /api/config |
모델·Skill·MCP 목록/기본값 |
| CRUD | /api/tasks |
Task 생성·수정·삭제 |
| POST | /api/tasks/{id}/chat |
SSE 채팅 스트림 |
| POST | /api/files/upload |
이미지 S3 업로드 |
| POST | /api/rag/upload |
RAG 문서 업로드·동기화 |
| GET | /api/health |
헬스체크 |
사이드바 / Config에서 Task마다 다음을 고릅니다.
- Model — Bedrock / Mantle 모델 표시명
- Skills —
application/skills.list기반 체크리스트 - MCP servers —
application/mcp.list기반 체크리스트 - Memory — 켜면 대화 저장 +
memoryMCP 자동 연결 - Guardrail — 설정된 경우 Bedrock Guardrail 적용
기본 Skill/MCP는 config.json의 default_skills, default_mcp_servers에 저장되며 Web UI에서 변경할 수 있습니다.
application/
├── server.py # FastAPI 진입점 + SPA 서빙
├── runtime_mode.py # local: chat.run_agent
├── chat.py # LLM, create_agent, run_langgraph_agent
├── langgraph_agent.py # StateGraph + builtin tools
├── skill.py / skills/ # SKILL.md 기반 스킬
├── mcp_config.py / mcp_server_*.py
├── task_store.py # tasks.db
├── api/ # routes_auth, chat, config, files, rag, tasks
├── web/ # React SPA (src/, dist/)
├── mcp.list / skills.list
└── config.json # (gitignore) AWS·KB·S3·API keys
Agent Skills은 AI agent에게 특정 작업 수행 방법을 가르치는 재사용 가능한 지침 패키지입니다. discovery → activation → execution 순으로 context를 관리합니다.
시스템 프롬프트에는 스킬의 이름과 설명만 XML로 넣고, 상세 지침은 agent가 get_skill_instructions로 필요할 때만 로드합니다.
<available_skills>
<skill>
<name>pdf</name>
<description>PDF 파일 읽기/병합/분할/OCR/폼 처리 등</description>
</skill>
</available_skills>skills/
├── pdf/
│ ├── SKILL.md
│ └── assets/
├── pptx/
│ └── SKILL.md
└── skill-creator/
└── SKILL.md
| 스킬 예 | 설명 |
|---|---|
| pdf / docx / xlsx / pptx | 문서 생성·편집 |
| myslide | AWS 테마 프레젠테이션 |
| skill-creator | 새 스킬 설계·패키징 |
| memory-manager | MEMORY.md 기반 워크스페이스 메모리 |
| retrieve | Knowledge Base RAG |
| graphify | 지식 그래프 구축·질의 |
동작은 skill.py의 SkillManager가 담당합니다. Web UI Task에서 고른 skill 목록이 build_skill_prompt() → 시스템 프롬프트로 전달됩니다.
요청 흐름:
- Web UI
POST /api/tasks/{id}/chat(SSE) runtime_mode.run_agent→chat.run_agent- 이미지 첨부가 있으면
build_human_message_with_files로 멀티모달HumanMessage구성 create_agent— builtin tools + 선택 MCP + skill toolslanggraph_agent.buildChatAgentWithHistory— checkpoint로 Task별 대화 유지astream(stream_mode="messages")→ notification queue → SSE (token/tool/done)
Builtin tools 예: execute_code, write_file, read_file, bash, upload_file_to_s3, get_current_time, get_skill_instructions
선택 MCP는 mcp_config.load_selected_config → stdio 또는 AgentCore Gateway(websearch, SigV4)로 연결됩니다. 목록은 application/mcp.list를 참고하세요.
커스텀 서버는 MCP Python SDK **2.1.1+**의 MCPServer(mcp.server.mcpserver)로 구현되어 있고, Agent 쪽 클라이언트는 langchain.mcp.MCPAdapter입니다 (langchain[mcp]>=1.4.0, mcp>=2.1.1).
대표적인 MCP:
- Tavily — 웹 검색
- RAG / knowledge base — Bedrock Knowledge Base
- web_fetch — URL → markdown
- Notion / Slack / memory 등
- Skill: korea-weather (기상청 동네예보)
Gateway 기반 웹검색은 websearch.md를 참조하세요.
장기 기억은 Amazon Bedrock AgentCore Memory를 사용합니다.
Web UI에서:
- Task의 Memory 토글을 켭니다 →
memory_enabled=true, 필요 시 MCPmemory자동 추가 - 대화 종료 후
save_to_memory로 short-term event 기록 → strategy가 long-term 추출 - Agent는 MCP
recall_memory(retrieve / list / get)로 조회만 수행
관련 코드: mcp_server_memory.py, mcp_memory.py, agentcore_memory.py
워크스페이스 Markdown 메모리(MEMORY.md, memory/*.md)는 memory-manager 스킬과 함께 사용할 수 있습니다.
Knowledge Base RAG는 업로드(Web UI / application) 와 검색(MCP kb-retriever / kb_retriever) 으로 나뉩니다.
| 역할 | 경로 | 설명 |
|---|---|---|
| 업로드 API | routes_rag.py | /api/rag/upload — 세션 user_id로 업로드 |
| 업로드 오케스트레이션 | rag_service.py | S3 적재 + sidecar metadata + KB sync |
| S3 유틸 | utils.py | docs/{projectName}/{user_id}/{file_name} 키로 업로드 |
| 검색 MCP | mcp_server_retrieve.py, mcp_retrieve.py | Bedrock Retrieve + metadata filter |
| MCP 등록 | mcp_config.py (kb-retriever → kb_retriever) |
AGENTCORE_USER_ID는 chat.create_agent()에서 주입 |
관련 AWS 문서:
- Connect to Amazon S3 for your knowledge base —
.metadata.jsonsidecar - Configure and customize queries and response generation — metadata filtering operators
- RetrievalFilter — API 필터 스키마
로그인 user_id(예: Google 이메일 user@example.com)가 그대로 사용됩니다.
- 문서:
s3://{bucket}/docs/{projectName}/{user_id}/{file_name} - metadata sidecar:
s3://{bucket}/docs/{projectName}/{user_id}/{file_name}.metadata.json
Knowledge Base data source는 docs/{projectName}/ 접두사만 ingestion합니다. 이메일에는 /가 없으므로 S3 폴더명과 metadata owner, 검색 필터의 user_id 포맷이 동일합니다. 업로드 후 Knowledge Base data source sync(StartIngestionJob)를 시작합니다.
Bedrock Knowledge Base는 문서와 같은 경로에 {원본파일명}.metadata.json을 두면, ingestion 시 metadata attribute를 벡터 스토어에 저장합니다. Retrieve 시 vectorSearchConfiguration.filter로 이 속성을 필터링할 수 있습니다.
지원 타입: STRING, NUMBER, BOOLEAN, STRING_LIST
주요 연산자 예:
| 연산자 | 용도 |
|---|---|
equals / notEquals |
값 일치 / 불일치 (notEquals는 키가 없는 문서도 포함) |
listContains |
STRING_LIST에 특정 값이 멤버로 포함되는지 |
greaterThan 등 |
숫자 비교 |
andAll / orAll |
조건 조합 |
includeForEmbedding: false이면 metadata는 필터 전용이고 임베딩에는 들어가지 않습니다. true이면 key-value가 chunk 텍스트에 이어져 임베딩에 반영됩니다.
중요: .metadata.json이 없는 문서는 해당 attribute가 false로 기본 세팅되지 않고 속성 부재(absent) 로 취급됩니다.
equals: is_confidential = false→ 속성 없는 문서는 제외notEquals: is_confidential = true→false인 문서 및 속성이 없는 문서 포함
업로드 시 rag_service.build_kb_metadata_document()이 아래 sidecar를 생성합니다. 모든 attribute의 includeForEmbedding은 false입니다.
{
"metadataAttributes": {
"owner": {
"value": {
"type": "STRING_LIST",
"stringListValue": ["user@example.com"]
},
"includeForEmbedding": false
},
"team": {
"value": { "type": "STRING", "stringValue": "mycompany" },
"includeForEmbedding": false
},
"created_time": {
"value": { "type": "NUMBER", "numberValue": 1754120285 },
"includeForEmbedding": false
},
"is_confidential": {
"value": { "type": "BOOLEAN", "booleanValue": false },
"includeForEmbedding": false
}
}
}| 필드 | 타입 | 기본값 | 비고 |
|---|---|---|---|
owner |
STRING_LIST |
업로드한 user_id 1명 |
여러 owner 등록 가능 |
team |
STRING |
mycompany |
|
created_time |
NUMBER |
Unix epoch(초) | greaterThan / lessThan 범위 필터 가능 |
is_confidential |
BOOLEAN |
false |
공유/비기밀 문서 구분용 |
실제 Vector Store에 들어간 데이터는 아래와 같습니다. owner, team, created_time, is_confidential이 meta로 등록됩니다.
mcp_retrieve.retrieve()는 MCP 프로세스 env의 AGENTCORE_USER_ID를 읽고, 없으면 검색을 거부합니다.
chat.create_agent()가 memory와 같이 kb_retriever에도 AGENTCORE_USER_ID를 주입합니다.
현재 기본 필터는 본인 문서만:
{
"listContains": {
"key": "owner",
"value": "user@example.com"
}
}is_confidential이 false이거나 metadata가 없어 속성이 없는 문서까지 검색하려면 equals false가 아니라 notEquals true를 사용합니다.
{
"notEquals": {
"key": "is_confidential",
"value": true
}
}의미:
is_confidential == false→ 포함is_confidential속성 없음 (구버전/수동 업로드) → 포함is_confidential == true→ 제외
owner 스코프와 함께 쓰려면 andAll로 조합합니다.
{
"andAll": [
{
"listContains": {
"key": "owner",
"value": "user@example.com"
}
},
{
"notEquals": {
"key": "is_confidential",
"value": true
}
}
]
}대화·코퍼스에서 엔티티·관계를 추출해 사용자별 지식 그래프를 만들고, Web UI의 Knowledge Graph 모달에서 탐색합니다. 파이프라인·용어 상세는 graph/README.md를 참고하세요.
추출 결과(graph.json)는 HTML로 렌더되며, 그래프 화면 컨트롤에서 시각화 패턴을 고를 수 있습니다. 선택값은 사용자 settings.json의 graph_pattern에 저장되고, 재추출 없이 HTML만 다시 생성합니다.
하이브리드 문서검색: application/config.json의 hybrid_graph_search가 "enable"이면 Titan 임베딩 vector search로 시작 노드를 보강합니다(graph/lib/embeddings.py, out/node_embeddings.json). 그 외 값이면 lexical(label/본문)만 사용합니다.
| 패턴 | 메뉴 이름 | 파일 | 특징 |
|---|---|---|---|
| pattern1 | Force Atlas | pattern1_html.py | forceAtlas2Based 레이아웃. 커뮤니티 색의 큰 노드·그림자, 컬러 곡선 엣지·화살표·관계 라벨. 허브 중심 탐색에 적합. |
| pattern2 | Neo4j Explore | pattern2_html.py | 어두운 캔버스, 작은 점 노드, 얇은 회색 곡선 엣지, 허브만 라벨. Neo4j Explore/Bloom에 가까운 overview. |
| pattern3 | Holistic View | pattern3_html.py | 어두운 배경의 전체-fit overview. ellipse 노드에 라벨을 많이 표시하고, 회색 방향 엣지에 관계명(예: HAS_TAG) 을 항상 표시. Neo4j Browser holistic view 구성을 어두운 테마로 맞춘 형태입니다. |
공통 UI: 좌상단 문서검색(Enter로 쿼리, 검색창·결과가 하나의 카드), 좌하단 그룹 범례·Browse all(빈 캔버스 클릭으로 범례 토글), 우하단 패턴 전환·전체 보기·레이아웃 재정렬.
구현 디스패치: patterns.py (pattern1 | pattern2 | pattern3).
sudo yum install python3 python3-pip git docker -y # EC2 예
pip install boto3
git clone https://github.com/kyopark2014/agent-skills
cd agent-skills && python3 installer.py제거: python uninstaller.py
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
./run_local.sh
# Docker
# docker build -t agent-skills . && docker run -p 8501:8501 ...컨테이너는 uvicorn application.server:app --host 0.0.0.0 --port 8501로 기동하며, 헬스체크는 GET /api/health입니다.
Web UI와 별도로 봇을 실행할 수 있습니다. 동일하게 chat.run_langgraph_agent를 호출합니다.
cd application
python telegram_bot.py
python discord_bot.pyTelegram Token은 @BotFather에서 발급 후 installer.py / Secrets Manager로 등록합니다.
명령 예:
/start
/model Claude 4.6 Sonnet
/mcp
Skill 생성·실행 예시는 아래와 같습니다.
- anthropics / skills
- Agent Skills
- Notion Skills for Claude
- Claude Code Skills
- Agent Skills for Strands Agents SDK
- Open Agent Skills
- agentic-work — 상용 배포용 FastAPI UI + AgentCore Runtime