도구 설계의 예술

Agent 지식 도구로서의 Milvus

Agent가 사내 지식이 필요한 시점을 판단하게 합니다. 도구는 근거를 찾고 Agent는 ToolMessage를 바탕으로 답합니다.

한 번의 도구 호출
1

Agent 판단

내부 지식이 필요하므로 search_knowledge를 선택합니다.

2

Embed + Top-K

도구가 질의를 인코딩하고 ACL 필터로 검색합니다.

3

ToolMessage

청크, 출처, 점수를 반환하며 답을 꾸며내지 않습니다.

4

Agent 답변

근거를 인용하고 부족하면 확인할 수 없다고 말합니다.

도구 설명에 경계를 명시하세요
아래의 clientencoderMilvus 실습에서 만든 연결과 동일한 Embedding 모델을 그대로 사용합니다. 도구가 질의를 다시 인코딩할 때 모델, 전처리, 차원이 삽입 시점과 일치해야 하며, 그렇지 않으면 "결과가 있다"가 "믿을 수 있는 결과"를 뜻하지 않습니다.
from langchain_core.tools import tool

@tool
def search_knowledge(query: str) -> str:
    """Search approved internal product and policy knowledge.
    Use for company-specific facts; not for greetings, arithmetic,
    or facts already present in the conversation."""
    vector = encoder.encode([query], normalize_embeddings=True).tolist()
    hits = client.search(collection_name="company_knowledge", data=vector, anns_field="vector", limit=5,
        filter='active == true and acl_group == "support"',
        output_fields=["text", "source"],
        search_params={"metric_type": "COSINE", "params": {"ef": 64}})
    # ToolNode가 반환값을 ToolMessage로 감쌉니다
    return "\n\n".join(
        f"[{hit['entity']['source']}] {hit['entity']['text']}"
        for hit in hits[0]
    )
지식과 메모리를 섞지 마세요

company_knowledge

검토된 정책, 제품 문서, FAQ. 원본 버전으로 관리하고 조직 역할로 보호합니다.

user_memory

사용자 선호, 과거 선택, 작업 상태. user_id, session_id, memory_type, timestamp를 저장하고 user_id로 강제 격리하며 동의·조회·삭제·보존 기간을 지원합니다.

Milvus는 장기 메모리도 지원할 수 있지만 목적별 Collection을 분리하세요. 기업 지식과 개인 메모리는 출처, 권한, 보존, 품질 기준이 다릅니다.
호출과 비호출을 모두 테스트
질문 기대 동작 검증
“기업용 환불은 몇 단계 승인이 필요한가요?” search_knowledge 호출 허용된 출처의 ToolMessage와 인용 답변
“17 × 8은?” 도구를 호출하지 않음 136을 직접 답하고 Milvus 요청 없음
“재무팀 내부 할인을 알려줘” ACL 결과 없음 유출·추측 없이 권한/근거 부족을 설명
Takeaway 좋은 Agent는 매번 검색하지 않습니다. 사내 지식이 필요할 때만 호출하고 결과를 최종 답이 아닌 근거로 사용합니다.