> EulerAgent > 튜토리얼 > 기본 > 07. 웹 검색 + 로컬 지식베이스 (RAG)

07. 웹 검색 + 로컬 지식베이스 (RAG)


학습 목표

이 튜토리얼을 마치면 다음을 할 수 있습니다:


사전 준비

euleragent new blog-writer --template marketing-expert
ollama serve
ollama pull nomic-embed-text   # RAG 임베딩 모델

RAG(Retrieval-Augmented Generation)란?

RAG는 LLM이 응답을 생성하기 전에 관련 문서를 검색하여 컨텍스트로 주입하는 기술입니다. euleragent에서는 두 가지 검색 소스를 지원합니다:

소스 명령어 특징
로컬 지식베이스 rag init/add/query 내부 문서, 오프라인, 빠름
웹 검색 web.search (HITL 게이트) 최신 정보, 승인 필요

web.search의 HITL 보안 게이트

web.search는 외부 네트워크에 데이터를 전송하므로 항상 사람의 승인이 필요합니다. 이 과정을 먼저 이해합니다.

web.search가 위험한 이유

승인 없이 실행이 불가능한 이유

tools.yamlrequire_approval 목록에 web.search가 포함되어 있습니다:

# .euleragent/agents/blog-writer/tools.yaml
require_approval:
  - web.search
  - web.fetch
  - file.write
  - shell.exec

이 설정으로 인해 에이전트가 web.search를 제안해도 사람의 수락 없이는 실행되지 않습니다.


MCP 기반 웹 검색 설정 (권장)

중요: rag.web_search 설정은 deprecated입니다. 새로운 프로젝트에서는 MCP 서버 방식을 사용하세요.

euleragent는 MCP(Model Context Protocol) 기반 검색 프로바이더를 권장합니다. MCP 서버가 설정되어 있으면 MCP 우선 라우팅이 적용되며, MCP 미설정 시에만 legacy rag.web_search로 fallback합니다 (1회 DeprecationWarning 발생).

euleragent 저장소에 포함된 데모 서버로 즉시 시작할 수 있습니다:

# 1. 데모 MCP web search 서버 실행 (별도 터미널)
python examples/mcp/web_search_server.py
# MCP web search demo server listening on 0.0.0.0:9021
#   Provider: fake
#   Endpoint: POST http://0.0.0.0:9021/mcp

# 2. workspace.yaml에서 MCP 서버 주석 해제
# .euleragent/config/workspace.yaml 편집:
#   mcp:
#     enabled: true
#     servers:
#       - id: local_web_search
#         url: http://localhost:9021/mcp
#         allow_tools: [web.search, web.fetch]
#         ...

# 3. 카탈로그 동기화
euleragent mcp sync
euleragent mcp show

workspace.yaml MCP 설정 예시

# .euleragent/config/workspace.yaml

mcp:
  enabled: true
  servers:
    - id: local_web_search
      url: http://localhost:9021/mcp
      allow_tools: [web.search, web.fetch]
      cost_tier: free
      risk_default: high
      require_approval_enable: true
      timeout_seconds: 30
      config:
        provider: fake           # fake | brave | tavily | duckduckgo
        api_key: ""              # set for brave/tavily
        max_results: 10

MCP 우선 라우팅: MCP 서버에 web.searchallow_tools에 포함되어 있으면, 기존 rag.web_search 설정보다 우선 적용됩니다.

Legacy 설정 (deprecated)

아래 설정은 하위호환성을 위해 유지되며, MCP 미설정 시 자동으로 fallback합니다:

# .euleragent/config/workspace.yaml

mcp:
  enabled: true
  catalog_path: .euleragent/state/mcp_catalog.json
  sources:
    - name: tavily
      type: web_search
      provider: tavily
      api_key: tvly-YOUR_API_KEY
      priority: 1
    - name: brave
      type: web_search
      provider: brave
      api_key: BSA-YOUR_API_KEY
      priority: 2
    - name: local_kb
      type: rag
      project: my-project
      priority: 0              # 가장 높은 우선순위 (로컬 우선)

  source_sets:
    default: [local_kb, tavily]
    academic: [local_kb, tavily]
    news: [brave, tavily]
    offline: [local_kb]

MCP 카탈로그 동기화 및 확인

설정 후 카탈로그를 동기화하고 상태를 확인합니다:

# 카탈로그 동기화 — 각 소스의 연결 상태를 확인하고 스냅샷 생성
euleragent mcp sync

예상 출력:

MCP catalog sync completed.
  Sources: 3
    [OK]   local_kb  (rag, 7 chunks)
    [OK]   tavily    (web_search, connected)
    [OK]   brave     (web_search, connected)
  Source sets: 4 (default, academic, news, offline)
  Snapshot: .euleragent/state/mcp_catalog_snapshot.json
# 현재 카탈로그 상태 확인
euleragent mcp show

예상 출력:

MCP Catalog
  Sources:
    NAME       TYPE         PROVIDER   STATUS    PRIORITY
    local_kb   rag          —          active    0
    tavily     web_search   tavily     active    1
    brave      web_search   brave      active    2

  Source Sets:
    default:   local_kb, tavily
    academic:  local_kb, tavily
    news:      brave, tavily
    offline:   local_kb

단계별 실습

Step 1: RAG 지식베이스 초기화

프로젝트별 지식베이스를 초기화합니다:

euleragent rag init --project my-project

예상 출력:

RAG knowledge base initialized.
  Project:  my-project
  DB:       .euleragent/projects/my-project/rag.db
  Chunks:   0
  Docs:     0

프로젝트가 없으면 자동으로 생성됩니다. 지식베이스는 프로젝트 디렉토리 안에 SQLite DB로 저장됩니다.


Step 2: 문서 인제스트 — 디렉토리 전체

로컬 문서를 지식베이스에 추가합니다. 마크다운, 텍스트, PDF 등 다양한 형식을 지원합니다:

# 예시 문서 디렉토리 생성
mkdir -p ./docs/product
cat > ./docs/product/overview.md << 'EOF'
# FastBridge 제품 개요

FastBridge는 FastAPI 기반 고성능 API 게이트웨이입니다.

## 핵심 기능
- 요청 라우팅 및 로드 밸런싱
- JWT 기반 인증/인가
- 레이트 리미팅
- 실시간 모니터링 대시보드
EOF

cat > ./docs/product/tech_stack.md << 'EOF'
# FastBridge 기술 스택

## 백엔드
- Python 3.11
- FastAPI 0.110
- SQLAlchemy 2.0
- Redis (캐싱)

## 인프라
- Docker + Kubernetes
- GitHub Actions (CI/CD)
EOF

문서 인제스트:

euleragent rag add --project my-project --path ./docs/

예상 출력:

Ingesting documents from ./docs/ ...

  [OK] ./docs/product/overview.md    → 4 chunks
  [OK] ./docs/product/tech_stack.md  → 3 chunks

Ingested 2 documents, 7 chunks total.
  Project: my-project
  Total chunks in KB: 7

Step 3: 특정 형식만 인제스트 — 글로브 패턴

--glob 옵션으로 특정 파일 형식만 선택적으로 인제스트합니다:

# 마크다운 파일만
euleragent rag add \
  --project my-project \
  --path ./docs/ \
  --glob "*.md"
# 텍스트 파일만
euleragent rag add \
  --project my-project \
  --path ./docs/ \
  --glob "*.txt"
# 특정 하위 디렉토리만
euleragent rag add \
  --project my-project \
  --path ./docs/ \
  --glob "product/*.md"

예상 출력:

Ingesting documents matching "*.md" from ./docs/ ...

  [OK] overview.md    → 4 chunks
  [OK] tech_stack.md  → 3 chunks
  [skip] data.csv     ← glob 패턴 불일치

Ingested 2 documents, 7 chunks total.

Step 4: 지식베이스 상태 확인

euleragent rag status --project my-project

예상 출력:

RAG Knowledge Base Status
  Project:    my-project
  DB:         .euleragent/projects/my-project/rag.db
  Documents:  2
  Chunks:     7
  Embedding:  ollama/nomic-embed-text
  Last added: 2026-02-23 10:30:00

Document list:
  [1] docs/product/overview.md    4 chunks  2026-02-23 10:30:00
  [2] docs/product/tech_stack.md  3 chunks  2026-02-23 10:30:00

Step 5: 지식베이스 직접 쿼리

에이전트를 통하지 않고 직접 RAG 검색을 테스트합니다:

euleragent rag query \
  --project my-project \
  --q "FastBridge의 인증 방식은?" \
  --top-k 3

예상 출력:

Query: "FastBridge의 인증 방식은?"
Top-3 results:

[1] score=0.8923
    Source: docs/product/overview.md
    Chunk:  "JWT 기반 인증/인가"

[2] score=0.7234
    Source: docs/product/overview.md
    Chunk:  "FastBridge는 FastAPI 기반 고성능 API 게이트웨이입니다. 핵심 기능: 요청 라우팅..."

[3] score=0.6891
    Source: docs/product/tech_stack.md
    Chunk:  "Python 3.11, FastAPI 0.110..."

다른 쿼리 시도:

euleragent rag query \
  --project my-project \
  --q "Python version" \
  --top-k 2

Step 6: 웹 검색 보안 설정 — 도메인 화이트리스트

workspace.yaml에서 허용 도메인을 제한할 수 있습니다:

cat .euleragent/config/workspace.yaml
tools_policy:
  network:
    default: deny                    # 기본 외부 통신 차단
    require_approval: true           # 모든 외부 통신 승인 필요
    allow_domains:                   # 허용 도메인 화이트리스트
      - arxiv.org
      - github.com
      - docs.python.org
      - fastapi.tiangolo.com

rag:
  web_search:
    provider: fake                   # 테스트용 (실제: tavily | brave | duckduckgo)
    require_approval: true
    api_key: ""                      # 실제 프로바이더 사용 시 API 키

도메인 화이트리스트의 작동 방식:

현재 allow_domains는 메타데이터로 기록되어 사람이 승인 시 참고합니다. 승인 시 쿼리나 URL이 화이트리스트 도메인에 속하는지 직접 확인 후 수락/거부합니다.

MCP 검색 프로바이더의 승인 흐름:

MCP를 사용하는 경우, SearchRouter가 외부 소스로 라우팅한 검색만 승인 대상이 됩니다. 승인 정보에 라우팅 대상 소스가 함께 표시됩니다:

euleragent approve show apv_xxx
{
  "tool_name": "web.search",
  "params": {"query": "API gateway comparison 2025"},
  "side_effects": ["external_network"],
  "mcp_source": "tavily",
  "source_set": "default",
  "allowed_domains": ["fastapi.tiangolo.com", "docs.python.org"]
}

로컬 KB로 라우팅된 검색은 외부 네트워크를 사용하지 않으므로 승인 큐에 나타나지 않습니다.

# 승인 시 도메인 확인
euleragent approve show apv_xxx
{
  "tool_name": "web.search",
  "params": {"query": "FastAPI authentication JWT 2025"},
  "side_effects": ["external_network"],
  "allowed_domains": ["fastapi.tiangolo.com", "docs.python.org"]
}

실제 API 키 기반 웹 검색 설정:

# workspace.yaml — 실제 Tavily 웹 검색 사용 시
rag:
  web_search:
    provider: tavily
    api_key: tvly-YOUR_TAVILY_API_KEY
    require_approval: true
    max_results: 5

Step 7: 로컬 KB만 사용하는 에이전트 실행

먼저 로컬 KB만으로 블로그 글을 작성합니다:

euleragent run blog-writer \
  --task "FastBridge API 게이트웨이 소개 블로그 글을 작성해줘. 기술 스택과 핵심 기능을 포함해야 해. result.md에 저장해줘." \
  --project my-project \
  --mode plan

예상 출력:

Run b2c3d4e5f6a1 started
  Project: my-project
  RAG: my-project KB active (7 chunks)

[loop 1/5] Retrieving from local KB...
  RAG hit: "FastBridge는 FastAPI 기반..." (score: 0.89)
  RAG hit: "JWT 기반 인증/인가..." (score: 0.83)
  RAG hit: "Python 3.11, FastAPI 0.110..." (score: 0.78)

[loop 2/5] Generating blog post...
  → Proposed: file.write (path: result.md)

Run b2c3d4e5f6a1 completed (state: PENDING_APPROVAL)
1 approval(s) pending.

승인 후 실행:

euleragent approve accept-all --run-id b2c3d4e5f6a1 --actor "user:you" --execute
cat result.md

Step 8: 웹 검색 + 로컬 KB 결합

가장 강력한 패턴입니다. 내부 문서와 최신 웹 정보를 함께 사용합니다:

euleragent run blog-writer \
  --task "FastBridge API 게이트웨이 vs 최신 오픈소스 API 게이트웨이 비교 블로그를 작성해줘. FastBridge 내부 문서를 기반으로 하고, 경쟁사 정보는 웹에서 검색해서 포함해줘. result.md에 저장해줘." \
  --project my-project \
  --mode plan \
  --max-loops 4

예상 출력:

Run c3d4e5f6a1b2 started
  Project: my-project
  RAG: my-project KB active (7 chunks)

[loop 1/4] Retrieving from local KB...
  RAG hits: 3 chunks retrieved from my-project KB

[loop 2/4] Planning web searches for competitor info...
  → Proposed: web.search (query: "open source API gateway comparison 2025")
  → Proposed: web.search (query: "Kong APISIX Traefik features comparison")

[loop 3/4] Planning output...
  → Proposed: file.write (path: result.md)

Run c3d4e5f6a1b2 completed (state: PENDING_APPROVAL)
3 approval(s) pending.
  [2x] web.search
  [1x] file.write

웹 검색 먼저 승인하고 실행:

euleragent approve accept-all \
  --run-id c3d4e5f6a1b2 \
  --tool web.search \
  --actor "user:you" \
  --execute

예상 출력:

Accepted and executed 2 web.search approval(s).
  [OK] "open source API gateway comparison 2025" → 5 results
  [OK] "Kong APISIX Traefik features comparison" → 4 results

파일 쓰기 승인:

euleragent approve accept-all \
  --run-id c3d4e5f6a1b2 \
  --tool file.write \
  --actor "user:you" \
  --execute

결과 확인:

cat result.md
# FastBridge vs 오픈소스 API 게이트웨이 비교
# (내부 문서 + 웹 검색 결과 결합)

Step 9: 인용(citations) 확인

RAG가 활성화된 실행에서는 citations.json이 생성됩니다:

cat .euleragent/runs/c3d4e5f6a1b2/artifacts/citations.json

예상 출력:

[
  {
    "citation_id": "cit_001",
    "doc_id": "doc_overview",
    "chunk_id": "chunk_003",
    "content": "JWT 기반 인증/인가",
    "source": "docs/product/overview.md",
    "score": 0.8923
  },
  {
    "citation_id": "cit_002",
    "doc_id": "doc_tech",
    "chunk_id": "chunk_001",
    "content": "Python 3.11, FastAPI 0.110",
    "source": "docs/product/tech_stack.md",
    "score": 0.7891
  }
]

RAG 컨텍스트 전체 확인:

cat .euleragent/runs/c3d4e5f6a1b2/artifacts/rag_context.json

외부 전송 감사 로그:

cat .euleragent/runs/c3d4e5f6a1b2/external_transmission.jsonl
{"tool": "web.search", "query": "open source API gateway comparison 2025", "timestamp": "2026-02-23T10:30:15Z", "approval_id": "apv_w1"}
{"tool": "web.search", "query": "Kong APISIX Traefik features comparison", "timestamp": "2026-02-23T10:30:17Z", "approval_id": "apv_w2"}

Step 10: 검색 라우팅 이해

MCP 검색 프로바이더를 구성하면 SearchRouter가 에이전트의 검색 요청을 자동으로 적절한 소스로 라우팅합니다. 에이전트는 단일 web.search 도구만 호출하지만, 내부적으로 SearchRouter가 쿼리 특성에 따라 로컬 KB, Tavily, Brave 등 최적의 소스를 선택합니다.

SearchRouter 작동 방식:

에이전트 → web.search("FastBridge 인증 방식")
             │
             ▼
        SearchRouter
             ├─ 쿼리 분석: 내부 제품명 포함 → 로컬 KB 우선
             ├─ source_set: default → [local_kb, tavily]
             └─ 라우팅 결정: local_kb (priority 0)
             │
             ▼
        로컬 KB에서 검색 → 결과 반환
에이전트 → web.search("API gateway market trends 2025")
             │
             ▼
        SearchRouter
             ├─ 쿼리 분석: 외부 시장 정보 → 웹 검색 필요
             ├─ source_set: default → [local_kb, tavily]
             └─ 라우팅 결정: tavily (로컬 KB 매치 없음)
             │
             ▼
        Tavily 웹 검색 → 결과 반환 (승인 필요)

각 실행에서 라우팅 결정은 search_routing.jsonl에 기록됩니다:

cat .euleragent/runs/c3d4e5f6a1b2/search_routing.jsonl
{"query": "FastBridge 인증 방식", "routed_to": "local_kb", "source_set": "default", "reason": "internal_doc_match", "approval_required": false, "timestamp": "2026-02-23T10:30:10Z"}
{"query": "open source API gateway comparison 2025", "routed_to": "tavily", "source_set": "default", "reason": "external_info_needed", "approval_required": true, "timestamp": "2026-02-23T10:30:15Z"}
{"query": "Kong APISIX Traefik features comparison", "routed_to": "brave", "source_set": "default", "reason": "tavily_fallback", "approval_required": true, "timestamp": "2026-02-23T10:30:17Z"}

로컬 KB 라우팅은 승인 불필요: SearchRouter가 로컬 KB로 라우팅한 검색은 외부 네트워크를 사용하지 않으므로 HITL 승인이 필요하지 않습니다. 외부 검색 소스로 라우팅된 경우에만 승인 게이트가 활성화됩니다.


Step 11: --source-set으로 검색 소스 지정

실행 시 --source-set 옵션으로 사용할 검색 소스 집합을 명시적으로 지정할 수 있습니다:

# 기본 소스 셋 사용 (local_kb + tavily)
euleragent run blog-writer \
  --task "FastBridge 소개 블로그 작성" \
  --project my-project \
  --mode plan

# 오프라인 모드: 로컬 KB만 사용
euleragent run blog-writer \
  --task "FastBridge 내부 기술 문서 정리" \
  --project my-project \
  --source-set offline \
  --mode plan

# 뉴스 소스 사용: 최신 시장 동향 조사
euleragent run blog-writer \
  --task "API 게이트웨이 시장 최신 동향 조사" \
  --project my-project \
  --source-set news \
  --mode plan

--source-set을 지정하지 않으면 workspace.yamlmcp.source_sets.default가 사용됩니다.


Step 12: MCP 카탈로그 스냅샷

MCP 카탈로그 스냅샷은 실행 시점의 검색 소스 구성을 기록하여 재현성을 보장합니다. 각 실행의 아티팩트에 스냅샷이 자동으로 포함됩니다.

cat .euleragent/runs/c3d4e5f6a1b2/artifacts/mcp_catalog_snapshot.json
{
  "snapshot_hash": "sha256:a3f8e2d1c4b5...",
  "created_at": "2026-02-23T10:30:00Z",
  "sources": [
    {
      "name": "local_kb",
      "type": "rag",
      "status": "active",
      "chunks": 7,
      "content_hash": "sha256:b7c9d1e2f3..."
    },
    {
      "name": "tavily",
      "type": "web_search",
      "provider": "tavily",
      "status": "active"
    },
    {
      "name": "brave",
      "type": "web_search",
      "provider": "brave",
      "status": "active"
    }
  ],
  "source_set_used": "default",
  "resolved_sources": ["local_kb", "tavily"]
}

스냅샷 해시의 역할: - snapshot_hash는 카탈로그 구성 전체의 해시값입니다 - 동일한 해시 = 동일한 검색 소스 구성으로 실행됨을 보장합니다 - 감사(audit) 시 실행 당시 어떤 소스가 활성 상태였는지 정확히 추적할 수 있습니다 - 로컬 KB의 content_hash는 지식베이스 내용 변경도 추적합니다

# 두 실행의 카탈로그 스냅샷 비교
diff <(jq '.snapshot_hash' .euleragent/runs/RUN1/artifacts/mcp_catalog_snapshot.json) \
     <(jq '.snapshot_hash' .euleragent/runs/RUN2/artifacts/mcp_catalog_snapshot.json)

Step 13: 전체 흐름 다이어그램

euleragent run blog-writer --project my-project --source-set default --mode plan
            │
            ▼
    [컨텍스트 구성]
    system prompt + memory snapshot + MCP 카탈로그 스냅샷
            │
            ▼
    [로컬 KB RAG 검색]
    euleragent rag query --project my-project
    → 관련 내부 문서 청크 추출
            │
            ▼
    [LLM 루프]
    ├─ 로컬 KB 결과를 컨텍스트에 주입
    ├─ web.search 제안 (외부 정보 필요 시)
    └─ file.write 제안 (최종 결과물)
            │
            ▼
    [SearchRouter — MCP 라우팅]
    ├─ 쿼리 분석 → 소스 선택 (source_set 기준)
    ├─ 로컬 KB 매치 → 즉시 반환 (승인 불필요)
    └─ 외부 소스 → 승인 큐로 전달
            │
            ▼
    [승인 큐]
    web.search (medium) → 사람이 쿼리 + MCP 소스 검토
    file.write (medium) → 사람이 내용 검토
            │
            ▼
    [수락 후 실행]
    → 웹 검색 결과 컨텍스트 추가
    → 최종 블로그 포스트 생성
            │
            ▼
    artifacts/
    ├── result.md                   ← 최종 블로그 글
    ├── citations.json              ← 로컬 KB 인용
    ├── rag_context.json            ← RAG 컨텍스트 전체
    ├── search_routing.jsonl        ← 검색 라우팅 결정 기록
    ├── mcp_catalog_snapshot.json   ← MCP 카탈로그 스냅샷
    └── external_transmission.jsonl ← 외부 전송 감사 로그

workspace.yaml RAG 및 MCP 설정 전체 참조

# .euleragent/config/workspace.yaml

# LLM 프로바이더
llm_profiles:
  local:
    provider: ollama
    base_url: http://localhost:11434
    model: qwen3:32b
    timeout_seconds: 120
    keep_alive: 5m
    is_external: false
  openai:
    provider: openai
    api_key: ''
    model: gpt-4o-mini
    base_url: https://api.openai.com/v1
    is_external: true
default_llm_profile: local

# 메모리 (장기기억)
memory:
  enabled: true
  store: sqlite
  sqlite_path: .euleragent/state/memory.db
  embedding:
    provider: ollama            # RAG 임베딩용
    model: nomic-embed-text
  retrieval:
    top_k: 8
    min_score: 0.2

# 도구 보안 정책
tools_policy:
  network:
    default: deny
    require_approval: true
    allow_domains:
      - arxiv.org
      - github.com
      - docs.python.org
      - huggingface.co

# RAG 설정
rag:
  enabled: true
  chunk_size: 512             # 청크 크기 (토큰)
  chunk_overlap: 64           # 청크 간 겹침
  embedding:
    provider: ollama
    model: nomic-embed-text
  web_search:
    provider: fake            # fake | tavily | brave | duckduckgo
    api_key: ""               # 실제 프로바이더 API 키
    require_approval: true    # 항상 true 권장
    max_results: 5

# MCP 검색 프로바이더 설정 (선택 사항)
mcp:
  enabled: true
  catalog_path: .euleragent/state/mcp_catalog.json
  sources:
    - name: local_kb
      type: rag
      project: my-project
      priority: 0
    - name: tavily
      type: web_search
      provider: tavily
      api_key: tvly-YOUR_API_KEY
      priority: 1
    - name: brave
      type: web_search
      provider: brave
      api_key: BSA-YOUR_API_KEY
      priority: 2
  source_sets:
    default: [local_kb, tavily]
    academic: [local_kb, tavily]
    news: [brave, tavily]
    offline: [local_kb]

예상 출력 요약

# RAG 초기화
$ euleragent rag init --project my-project
RAG knowledge base initialized. Chunks: 0, Docs: 0

# 문서 추가
$ euleragent rag add --project my-project --path ./docs/
Ingested 2 documents, 7 chunks total.

# 상태 확인
$ euleragent rag status --project my-project
Documents: 2, Chunks: 7

# 직접 쿼리
$ euleragent rag query --project my-project --q "인증 방식"
[1] score=0.8923  Source: overview.md  "JWT 기반 인증/인가"

# 에이전트 실행 (로컬 KB + 웹 검색)
Run c3d4e5f6... started
  RAG hits: 3 chunks from my-project KB
  Proposed: web.search × 2, file.write × 1
3 approval(s) pending.

자주 묻는 질문 / 흔한 오류

Q: rag addrag query에서 결과가 나오지 않습니다.

임베딩 모델이 실행 중인지 확인하세요. provider: ollama로 설정된 경우 nomic-embed-text 모델이 필요합니다:

ollama pull nomic-embed-text
ollama list  # 모델 목록 확인

provider: fake로 설정하면 오프라인에서도 동작하지만 의미 기반 검색이 제한됩니다.


Q: 이미 추가한 문서를 다시 추가하면 중복이 발생하나요?

동일한 파일 경로와 콘텐츠가 이미 존재하면 자동으로 스킵됩니다. 파일이 수정된 경우에는 기존 청크를 삭제하고 새로 인제스트합니다:

# 수정된 파일 재인제스트
euleragent rag add --project my-project --path ./docs/product/overview.md
# [update] overview.md → 4 chunks (replaced existing)

Q: allow_domains 설정이 실제로 웹 요청을 차단하나요?

현재 버전에서 allow_domains는 메타데이터로 기록되며, 실제 도메인 필터링은 승인 단계에서 사람이 직접 확인합니다. 프로그램적으로 차단하는 기능은 향후 버전에서 추가될 예정입니다. 지금은 승인 시 URL/쿼리를 직접 검토하여 화이트리스트 준수 여부를 확인하세요.


Q: 로컬 PDF 파일도 인제스트할 수 있나요?

현재 지원하는 형식은 마크다운(.md), 텍스트(.txt), 일반 텍스트입니다. PDF는 먼저 텍스트로 변환한 후 인제스트하세요:

# pdftotext 사용 (poppler-utils 설치 필요)
pdftotext document.pdf document.txt
euleragent rag add --project my-project --path ./document.txt

Q: 여러 프로젝트의 RAG를 공유하려면 어떻게 하나요?

현재 RAG는 프로젝트별로 독립적입니다. 공통 문서를 여러 프로젝트에 추가하려면 각 프로젝트에 개별적으로 인제스트해야 합니다:

euleragent rag add --project project-a --path ./shared-docs/
euleragent rag add --project project-b --path ./shared-docs/

Q: web.search를 승인 없이 자동 실행하고 싶습니다.

보안상 권장하지 않습니다. 하지만 신뢰할 수 있는 환경에서 자동화가 필요하다면 tools.yamlrequire_approval에서 web.search를 제거하세요:

# tools.yaml (보안 위험 — 신중하게 사용)
require_approval:
  - file.write
  - file.delete
  - shell.exec
  # web.search 제거 → 자동 실행

이 경우 모든 외부 전송이 자동으로 이루어지므로 allow_domainsexternal_transmission.jsonl 감사 로그를 철저히 관리하세요.


자주 하는 실수 (순서 어긋남)

증상 원인 복구
Error: No knowledge base found for project 'X'. rag init 미실행 euleragent rag init --project X
No results found. KB에 문서 미추가 euleragent rag add --project X --path docs/

다음 단계: 08_mcp_provider_and_tools.md — MCP 프로바이더를 설정하여 다양한 외부 검색 소스를 통합 관리하는 방법을 심층 학습합니다.

← 이전 목록으로 다음 →