Skip to content

Latest commit

 

History

339 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Agent Skills

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 8501

Operation Architecture

flowchart 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
Loading
기능 모듈 설명
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 저장/조회

Web UI

구성

레이어 스택
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

주요 API

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 헬스체크

UI에서 설정하는 항목

사이드바 / Config에서 Task마다 다음을 고릅니다.

  • Model — Bedrock / Mantle 모델 표시명
  • Skills — application/skills.list 기반 체크리스트
  • MCP servers — application/mcp.list 기반 체크리스트
  • Memory — 켜면 대화 저장 + memory MCP 자동 연결
  • Guardrail — 설정된 경우 Bedrock Guardrail 적용

기본 Skill/MCP는 config.json의 default_skills, default_mcp_servers에 저장되며 Web UI에서 변경할 수 있습니다.

디렉터리 (application/)

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

Agent Skills은 AI agent에게 특정 작업 수행 방법을 가르치는 재사용 가능한 지침 패키지입니다. discovery → activation → execution 순으로 context를 관리합니다.

Progressive Disclosure

시스템 프롬프트에는 스킬의 이름과 설명만 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() → 시스템 프롬프트로 전달됩니다.

LangGraph Agent

요청 흐름:

  1. Web UI POST /api/tasks/{id}/chat (SSE)
  2. runtime_mode.run_agent → chat.run_agent
  3. 이미지 첨부가 있으면 build_human_message_with_files로 멀티모달 HumanMessage 구성
  4. create_agent — builtin tools + 선택 MCP + skill tools
  5. langgraph_agent.buildChatAgentWithHistory — checkpoint로 Task별 대화 유지
  6. 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는 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:

Gateway 기반 웹검색은 websearch.md를 참조하세요.

Memory

장기 기억은 Amazon Bedrock AgentCore Memory를 사용합니다.

Web UI에서:

  1. Task의 Memory 토글을 켭니다 → memory_enabled=true, 필요 시 MCP memory 자동 추가
  2. 대화 종료 후 save_to_memory로 short-term event 기록 → strategy가 long-term 추출
  3. Agent는 MCP recall_memory(retrieve / list / get)로 조회만 수행

관련 코드: mcp_server_memory.py, mcp_memory.py, agentcore_memory.py

워크스페이스 Markdown 메모리(MEMORY.md, memory/*.md)는 memory-manager 스킬과 함께 사용할 수 있습니다.

RAG

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 문서:

업로드와 S3 경로

로그인 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)를 시작합니다.

Metadata filtering 소개

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인 문서 및 속성이 없는 문서 포함

현재 적용된 metadata

업로드 시 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로 등록됩니다.

image

현재 적용된 검색 필터

mcp_retrieve.retrieve()는 MCP 프로세스 env의 AGENTCORE_USER_ID를 읽고, 없으면 검색을 거부합니다.
chat.create_agent()가 memory와 같이 kb_retriever에도 AGENTCORE_USER_ID를 주입합니다.

현재 기본 필터는 본인 문서만:

{
  "listContains": {
    "key": "owner",
    "value": "user@example.com"
  }
}

향후 옵션: 비기밀(또는 metadata 없는) 문서

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
      }
    }
  ]
}

Knowledge Graph

대화·코퍼스에서 엔티티·관계를 추출해 사용자별 지식 그래프를 만들고, Web UI의 Knowledge Graph 모달에서 탐색합니다. 파이프라인·용어 상세는 graph/README.md를 참고하세요.

Graph Extraction

추출 결과(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입니다.

Telegram / Discord

Web UI와 별도로 봇을 실행할 수 있습니다. 동일하게 chat.run_langgraph_agent를 호출합니다.

cd application
python telegram_bot.py
python discord_bot.py

Telegram Token은 @BotFather에서 발급 후 installer.py / Secrets Manager로 등록합니다.

명령 예:

/start
/model Claude 4.6 Sonnet
/mcp

실행 결과

Skill 생성·실행 예시는 아래와 같습니다.

image image image image

Reference

About

It shows how to use agent skills based on LangGraph.

Topics

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages