검색 결과 콘텐츠 블록은 현재 베타 버전입니다. 이 기능을 활성화하려면 search-results-2025-06-09 베타 헤더를 사용하세요.

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

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

  • 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 (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": "기사 제목",                  // 필수: 결과의 제목
  "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.beta import (
    BetaMessageParam,
    BetaTextBlockParam,
    BetaSearchResultBlockParam,
    BetaToolResultBlockParam
)

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 [
        BetaSearchResultBlockParam(
            type="search_result",
            source="https://docs.company.com/product-guide",
            title="제품 구성 가이드",
            content=[
                BetaTextBlockParam(
                    type="text",
                    text="제품을 구성하려면 설정 > 구성으로 이동하세요. 기본 타임아웃은 30초이지만 필요에 따라 10-120초 사이에서 조정할 수 있습니다."
                )
            ],
            citations={"enabled": True}
        ),
        BetaSearchResultBlockParam(
            type="search_result",
            source="https://docs.company.com/troubleshooting",
            title="문제 해결 가이드",
            content=[
                BetaTextBlockParam(
                    type="text",
                    text="타임아웃 오류가 발생하면 먼저 구성 설정을 확인하세요. 일반적인 원인으로는 네트워크 지연 및 잘못된 타임아웃 값이 있습니다."
                )
            ],
            citations={"enabled": True}
        )
    ]

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

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

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

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

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

예시: 직접 검색 결과

from anthropic import Anthropic
from anthropic.types.beta import (
    BetaMessageParam,
    BetaTextBlockParam,
    BetaSearchResultBlockParam
)

client = Anthropic()

# 사용자 메시지에서 직접 검색 결과 제공
response = client.beta.messages.create(
    model="claude-opus-4-20250514",
    max_tokens=1024,
    betas=["search-results-2025-06-09"],
    messages=[
        BetaMessageParam(
            role="user",
            content=[
                BetaSearchResultBlockParam(
                    type="search_result",
                    source="https://docs.company.com/api-reference",
                    title="API 참조 - 인증",
                    content=[
                        BetaTextBlockParam(
                            type="text",
                            text="모든 API 요청은 Authorization 헤더에 API 키를 포함해야 합니다. 키는 대시보드에서 생성할 수 있습니다. 속도 제한: 표준 티어의 경우 시간당 1000개 요청, 프리미엄의 경우 10000개."
                        )
                    ],
                    citations={"enabled": True}
                ),
                BetaSearchResultBlockParam(
                    type="search_result",
                    source="https://docs.company.com/quickstart",
                    title="시작하기 가이드",
                    content=[
                        BetaTextBlockParam(
                            type="text",
                            text="시작하려면: 1) 계정에 가입, 2) 대시보드에서 API 키 생성, 3) pip install company-sdk를 사용하여 SDK 설치, 4) API 키로 클라이언트 초기화."
                        )
                    ],
                    citations={"enabled": True}
                ),
                BetaTextBlockParam(
                    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": 0,
          "end_block_index": 0
        }
      ]
    }
  ]
}

인용 필드

각 인용에는 다음이 포함됩니다:

필드타입설명
typestring검색 결과 인용의 경우 항상 "search_result_location"
sourcestring원본 검색 결과의 소스
titlestring 또는 null원본 검색 결과의 제목
cited_textstring인용되는 정확한 텍스트
search_result_indexinteger검색 결과의 인덱스 (0부터 시작)
start_block_indexinteger콘텐츠 배열에서의 시작 위치
end_block_indexinteger콘텐츠 배열에서의 끝 위치

참고: search_result_index는 검색 결과가 제공된 방식(도구 호출 또는 최상위 콘텐츠)에 관계없이 검색 결과 콘텐츠 블록의 인덱스(0부터 시작)를 나타냅니다.

여러 콘텐츠 블록

검색 결과는 content 배열에 여러 텍스트 블록을 포함할 수 있습니다:

{
  "type": "search_result",
  "source": "https://docs.company.com/api-guide",
  "title": "API 문서",
  "content": [
    {
      "type": "text",
      "text": "인증: 모든 API 요청에는 API 키가 필요합니다."
    },
    {
      "type": "text",
      "text": "속도 제한: API는 키당 시간당 1000개의 요청을 허용합니다."
    },
    {
      "type": "text",
      "text": "오류 처리: API는 표준 HTTP 상태 코드를 반환합니다."
    }
  ]
}

Claude는 start_block_indexend_block_index 필드를 사용하여 특정 블록을 인용할 수 있습니다.

고급 사용법

두 방법 모두 결합

동일한 대화에서 도구 기반 및 최상위 검색 결과를 모두 사용할 수 있습니다:

# 최상위 검색 결과가 있는 첫 번째 메시지
messages = [
    BetaMessageParam(
        role="user",
        content=[
            BetaSearchResultBlockParam(
                type="search_result",
                source="https://docs.company.com/overview",
                title="제품 개요",
                content=[
                    BetaTextBlockParam(type="text", text="우리 제품은 팀이 협업하는 데 도움이 됩니다...")
                ],
                citations={"enabled": True}
            ),
            BetaTextBlockParam(
                type="text",
                text="이 제품에 대해 알려주고 가격 정보를 검색해 주세요"
            )
        ]
    )
]

# Claude가 응답하고 가격을 검색하기 위해 도구를 호출할 수 있음
# 그런 다음 더 많은 검색 결과와 함께 도구 결과를 제공

다른 콘텐츠 유형과 결합

두 방법 모두 검색 결과를 다른 콘텐츠와 혼합하는 것을 지원합니다:

# 도구 결과에서
tool_result = [
    BetaSearchResultBlockParam(
        type="search_result",
        source="https://docs.company.com/guide",
        title="사용자 가이드",
        content=[BetaTextBlockParam(type="text", text="구성 세부사항...")],
        citations={"enabled": True}
    ),
    BetaTextBlockParam(
        type="text",
        text="추가 컨텍스트: 이는 버전 2.0 이상에 적용됩니다."
    )
]

# 최상위 콘텐츠에서
user_content = [
    BetaSearchResultBlockParam(
        type="search_result",
        source="https://research.com/paper",
        title="연구 논문",
        content=[BetaTextBlockParam(type="text", text="주요 발견사항...")],
        citations={"enabled": True}
    ),
    {
        "type": "image",
        "source": {"type": "url", "url": "https://example.com/chart.png"}
    },
    BetaTextBlockParam(
        type="text",
        text="차트가 연구 발견사항과 어떻게 관련이 있나요?"
    )
]

캐시 제어

더 나은 성능을 위해 캐시 제어를 추가하세요:

{
  "type": "search_result",
  "source": "https://docs.company.com/guide",
  "title": "사용자 가이드",
  "content": [{"type": "text", "text": "..."}],
  "cache_control": {
    "type": "ephemeral"
  }
}

인용 제어

기본적으로 검색 결과에 대한 인용은 비활성화되어 있습니다. citations 구성을 명시적으로 설정하여 인용을 활성화할 수 있습니다:

{
  "type": "search_result",
  "source": "https://docs.company.com/guide",
  "title": "사용자 가이드",
  "content": [{"type": "text", "text": "중요한 문서..."}],
  "citations": {
    "enabled": true  // 이 결과에 대한 인용 활성화
  }
}

citations.enabledtrue로 설정되면 Claude는 검색 결과의 정보를 사용할 때 인용 참조를 포함합니다. 이는 다음을 가능하게 합니다:

  • 사용자 정의 RAG 애플리케이션을 위한 자연스러운 인용
  • 독점 지식 베이스와 인터페이스할 때 소스 속성
  • 검색 결과를 반환하는 모든 사용자 정의 도구에 대한 웹 검색 품질의 인용

citations 필드가 생략되면 기본적으로 인용이 비활성화됩니다.

인용은 전부 아니면 전무입니다: 요청의 모든 검색 결과에 인용이 활성화되어 있거나 모두 비활성화되어 있어야 합니다. 다른 인용 설정을 가진 검색 결과를 혼합하면 오류가 발생합니다. 일부 소스에 대해 인용을 비활성화해야 하는 경우 해당 요청의 모든 검색 결과에 대해 인용을 비활성화해야 합니다.

모범 사례

도구 기반 검색(방법 1)

  • 동적 콘텐츠: 실시간 검색 및 동적 RAG 애플리케이션에 사용
  • 오류 처리: 검색이 실패할 때 적절한 메시지 반환
  • 결과 제한: 컨텍스트 오버플로를 방지하기 위해 가장 관련성 높은 결과만 반환

최상위 검색(방법 2)

  • 미리 가져온 콘텐츠: 이미 검색 결과가 있을 때 사용
  • 배치 처리: 여러 검색 결과를 한 번에 처리하는 데 이상적
  • 테스트: 알려진 콘텐츠로 인용 동작을 테스트하는 데 좋음

일반적인 모범 사례

  1. 결과를 효과적으로 구조화

    • 명확하고 영구적인 소스 URL 사용
    • 설명적인 제목 제공
    • 긴 콘텐츠를 논리적인 텍스트 블록으로 분할
  2. 일관성 유지

    • 애플리케이션 전체에서 일관된 소스 형식 사용
    • 제목이 콘텐츠를 정확하게 반영하도록 보장
    • 형식을 일관되게 유지
  3. 오류를 우아하게 처리

    def search_with_fallback(query):
        try:
            results = perform_search(query)
            if not results:
                return {"type": "text", "text": "결과를 찾을 수 없습니다."}
            return format_as_search_results(results)
        except Exception as e:
            return {"type": "text", "text": f"검색 오류: {str(e)}"}
    

제한사항

  • 검색 결과 콘텐츠 블록은 베타 헤더에서만 사용 가능
  • 검색 결과 내에서는 텍스트 콘텐츠만 지원됨 (이미지나 기타 미디어 없음)
  • content 배열은 최소 하나의 텍스트 블록을 포함해야 함