검색 결과 콘텐츠 블록은 적절한 소스 출처와 함께 자연스러운 인용을 가능하게 하여 웹 검색 품질의 인용을 사용자 정의 애플리케이션에 제공합니다. 이 기능은 Claude가 소스를 정확하게 인용해야 하는 RAG(Retrieval-Augmented Generation) 애플리케이션에서 특히 강력합니다.

검색 결과 기능은 다음 모델에서 사용할 수 있습니다:

  • Claude 3.5 Haiku (claude-3-5-haiku-20241022)
  • Claude 3.5 Sonnet (claude-3-5-sonnet-20241022)
  • Claude 3.7 Sonnet (claude-3-7-sonnet-20250219)
  • Claude Opus 4.1 (claude-opus-4-1-20250805)
  • Claude Opus 4 (claude-opus-4-20250514)
  • Claude Sonnet 4 (claude-sonnet-4-20250514)

주요 이점

  • 자연스러운 인용 - 모든 콘텐츠에 대해 웹 검색과 동일한 인용 품질을 달성
  • 유연한 통합 - 동적 RAG를 위한 도구 반환에서 사용하거나 미리 가져온 데이터를 위한 최상위 콘텐츠로 사용
  • 적절한 소스 출처 - 각 결과에는 명확한 출처를 위한 소스 및 제목 정보가 포함됨
  • 문서 우회 방법 불필요 - 문서 기반 우회 방법의 필요성을 제거
  • 일관된 인용 형식 - Claude의 웹 검색 기능의 인용 품질 및 형식과 일치

작동 방식

검색 결과는 두 가지 방법으로 제공할 수 있습니다:

  1. 도구 호출에서 - 사용자 정의 도구가 검색 결과를 반환하여 동적 RAG 애플리케이션을 가능하게 함
  2. 최상위 콘텐츠로 - 미리 가져오거나 캐시된 콘텐츠를 위해 사용자 메시지에서 직접 검색 결과를 제공

두 경우 모두 Claude는 적절한 소스 출처와 함께 검색 결과의 정보를 자동으로 인용할 수 있습니다.

검색 결과 스키마

검색 결과는 다음 구조를 사용합니다:

{
  "type": "search_result",
  "source": "https://example.com/article",  // 필수: 소스 URL 또는 식별자
  "title": "Article Title",                  // 필수: 결과의 제목
  "content": [ // 필수: 텍스트 블록 배열
    {
      "type": "text",
      "text": "검색 결과의 실제 콘텐츠..."
    }
  ],
  "citations": {                             // 선택사항: 인용 구성
    "enabled": true                          // 이 결과에 대한 인용 활성화/비활성화
  }
}

필수 필드

필드타입설명
typestring"search_result"여야 함
sourcestring콘텐츠의 소스 URL 또는 식별자
titlestring검색 결과의 설명적 제목
contentarray실제 콘텐츠를 포함하는 텍스트 블록 배열

선택적 필드

필드타입설명
citationsobjectenabled 불린 필드가 있는 인용 구성
cache_controlobject캐시 제어 설정 (예: {"type": "ephemeral"})

content 배열의 각 항목은 다음을 포함하는 텍스트 블록이어야 합니다:

  • type: "text"여야 함
  • text: 실제 텍스트 콘텐츠 (비어있지 않은 문자열)

방법 1: 도구 호출에서 검색 결과

가장 강력한 사용 사례는 사용자 정의 도구에서 검색 결과를 반환하는 것입니다. 이는 도구가 관련 콘텐츠를 가져와서 자동 인용과 함께 반환하는 동적 RAG 애플리케이션을 가능하게 합니다.

예제: 지식 베이스 도구

from anthropic import Anthropic
from anthropic.types import (
    MessageParam,
    TextBlockParam,
    SearchResultBlockParam,
    ToolResultBlockParam
)

client = Anthropic()

# 지식 베이스 검색 도구 정의
knowledge_base_tool = {
    "name": "search_knowledge_base",
    "description": "회사 지식 베이스에서 정보를 검색합니다",
    "input_schema": {
        "type": "object",
        "properties": {
            "query": {
                "type": "string",
                "description": "검색 쿼리"
            }
        },
        "required": ["query"]
    }
}

# 도구 호출을 처리하는 함수
def search_knowledge_base(query):
    # 여기에 검색 로직
    # 올바른 형식으로 검색 결과를 반환
    return [
        SearchResultBlockParam(
            type="search_result",
            source="https://docs.company.com/product-guide",
            title="제품 구성 가이드",
            content=[
                TextBlockParam(
                    type="text",
                    text="제품을 구성하려면 설정 > 구성으로 이동하세요. 기본 타임아웃은 30초이지만, 필요에 따라 10-120초 사이에서 조정할 수 있습니다."
                )
            ],
            citations={"enabled": True}
        ),
        SearchResultBlockParam(
            type="search_result",
            source="https://docs.company.com/troubleshooting",
            title="문제 해결 가이드",
            content=[
                TextBlockParam(
                    type="text",
                    text="타임아웃 오류가 발생하면 먼저 구성 설정을 확인하세요. 일반적인 원인으로는 네트워크 지연과 잘못된 타임아웃 값이 있습니다."
                )
            ],
            citations={"enabled": True}
        )
    ]

# 도구와 함께 메시지 생성
response = client.messages.create(
    model="claude-sonnet-4-20250514",  # 지원되는 모든 모델에서 작동
    max_tokens=1024,
    tools=[knowledge_base_tool],
    messages=[
        MessageParam(
            role="user",
            content="타임아웃 설정을 어떻게 구성하나요?"
        )
    ]
)

# Claude가 도구를 호출할 때 검색 결과 제공
if response.content[0].type == "tool_use":
    tool_result = search_knowledge_base(response.content[0].input["query"])
    
    # 도구 결과를 다시 보내기
    final_response = client.messages.create(
        model="claude-sonnet-4-20250514",  # 지원되는 모든 모델에서 작동
        max_tokens=1024,
        messages=[
            MessageParam(role="user", content="타임아웃 설정을 어떻게 구성하나요?"),
            MessageParam(role="assistant", content=response.content),
            MessageParam(
                role="user",
                content=[
                    ToolResultBlockParam(
                        type="tool_result",
                        tool_use_id=response.content[0].id,
                        content=tool_result  # 검색 결과가 여기에 들어감
                    )
                ]
            )
        ]
    )

방법 2: 최상위 콘텐츠로서의 검색 결과

사용자 메시지에서 직접 검색 결과를 제공할 수도 있습니다. 이는 다음과 같은 경우에 유용합니다:

  • 검색 인프라에서 미리 가져온 콘텐츠
  • 이전 쿼리에서 캐시된 검색 결과
  • 외부 검색 서비스의 콘텐츠
  • 테스트 및 개발

예제: 직접 검색 결과

from anthropic import Anthropic
from anthropic.types import (
    MessageParam,
    TextBlockParam,
    SearchResultBlockParam
)

client = Anthropic()

# 사용자 메시지에서 직접 검색 결과 제공
response = client.messages.create(
    model="claude-opus-4-1-20250805",
    max_tokens=1024,
    messages=[
        MessageParam(
            role="user",
            content=[
                SearchResultBlockParam(
                    type="search_result",
                    source="https://docs.company.com/api-reference",
                    title="API 참조 - 인증",
                    content=[
                        TextBlockParam(
                            type="text",
                            text="모든 API 요청은 Authorization 헤더에 API 키를 포함해야 합니다. 키는 대시보드에서 생성할 수 있습니다. 속도 제한: 표준 등급은 시간당 1000개 요청, 프리미엄은 10000개입니다."
                        )
                    ],
                    citations={"enabled": True}
                ),
                SearchResultBlockParam(
                    type="search_result",
                    source="https://docs.company.com/quickstart",
                    title="시작하기 가이드",
                    content=[
                        TextBlockParam(
                            type="text",
                            text="시작하려면: 1) 계정에 가입, 2) 대시보드에서 API 키 생성, 3) pip install company-sdk를 사용하여 SDK 설치, 4) API 키로 클라이언트 초기화."
                        )
                    ],
                    citations={"enabled": True}
                ),
                TextBlockParam(
                    type="text",
                    text="이 검색 결과를 바탕으로 API 요청을 어떻게 인증하고 속도 제한은 무엇인가요?"
                )
            ]
        )
    ]
)

print(response.model_dump_json(indent=2))

인용이 포함된 Claude의 응답

검색 결과가 어떻게 제공되든 관계없이 Claude는 검색 결과의 정보를 사용할 때 자동으로 인용을 포함합니다:

{
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "API 요청을 인증하려면 Authorization 헤더에 API 키를 포함해야 합니다",
      "citations": [
        {
          "type": "search_result_location",
          "source": "https://docs.company.com/api-reference",
          "title": "API 참조 - 인증",
          "cited_text": "모든 API 요청은 Authorization 헤더에 API 키를 포함해야 합니다",
          "search_result_index": 0,
          "start_block_index": 0,
          "end_block_index": 0
        }
      ]
    },
    {
      "type": "text",
      "text": ". 대시보드에서 API 키를 생성할 수 있습니다",
      "citations": [
        {
          "type": "search_result_location",
          "source": "https://docs.company.com/api-reference",
          "title": "API 참조 - 인증",
          "cited_text": "키는 대시보드에서 생성할 수 있습니다",
          "search_result_index": 0,
          "start_block_index": 0,
          "end_block_index": 0
        }
      ]
    },
    {
      "type": "text",
      "text": ". 속도 제한은 표준 등급의 경우 시간당 1,000개 요청이고 프리미엄 등급의 경우 시간당 10,000개 요청입니다.",
      "citations": [
        {
          "type": "search_result_location",
          "source": "https://docs.company.com/api-reference",
          "title": "API 참조 - 인증",
          "cited_text": "속도 제한: 표준 등급은 시간당 1000개 요청, 프리미엄은 10000개",
          "search_result_index": 0,
          "start_block_index":