Claude Platform Docs
Messages모델 기능

검색 결과

출처 표시가 포함된 검색 결과를 제공하여 RAG 애플리케이션에서 자연스러운 인용을 활성화합니다

검색 결과 콘텐츠 블록을 사용하면 Claude가 웹 검색 결과를 인용하는 것과 동일한 방식으로 여러분의 자체 콘텐츠를 인용할 수 있습니다. 각 인용에는 여러분이 제공한 출처와 제목이 포함됩니다. Claude가 답변의 출처를 여러분의 문서로 표시해야 하는 "Retrieval-Augmented Generation"(검색 증강 생성), 즉 RAG 애플리케이션에서 사용하세요.

Claude Haiku 3을 제외한 모든 활성 모델이 인용이 포함된 검색 결과를 지원합니다. 베타 헤더는 필요하지 않습니다. 검색 결과는 표준 Messages API의 일부입니다.

작동 방식

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

  1. 도구 호출에서: 사용자 정의 도구가 검색 결과를 반환하여 동적 RAG 애플리케이션을 구현할 수 있습니다
  2. 최상위 콘텐츠로: 미리 가져온 콘텐츠나 캐시된 콘텐츠를 위해 사용자 메시지에 검색 결과를 직접 제공합니다

두 경우 모두 인용이 활성화되어 있으면 Claude가 검색 결과를 자동으로 인용합니다. 특별한 프롬프트는 필요하지 않습니다. 질문을 하면 여러분의 콘텐츠를 참고한 텍스트 블록에 인용이 표시됩니다.

검색 결과 스키마

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

{
  "type": "search_result",
  "source": "https://example.com/article", // Required: Source URL or identifier
  "title": "Article Title", // Required: Title of the result
  "content": [
    // Required: Array of text blocks
    {
      "type": "text",
      "text": "The actual content of the search result..."
    }
  ],
  "citations": {
    // Optional: Citation configuration
    "enabled": true // Enable/disable citations for this result
  }
}

필수 필드

필드타입설명
typestring"search_result"여야 합니다
sourcestring콘텐츠의 출처. 안정적인 문자열이면 무엇이든 사용할 수 있습니다: URL 또는 kb://article-1234와 같은 내부 식별자
titlestring검색 결과를 설명하는 제목
contentarray실제 콘텐츠를 담은 텍스트 블록의 배열

선택 필드

필드타입설명
citationsobjectenabled Boolean 필드를 포함한 인용 구성. 인용은 기본적으로 비활성화되어 있으며, 이 페이지의 모든 예제는 "enabled": true를 명시적으로 설정합니다. 요청 내 모든 검색 결과는 동일한 설정을 사용해야 합니다(인용 제어 참조)
cache_controlobject캐시 제어 설정(예: {"type": "ephemeral"})

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

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

검색 결과는 텍스트만 담을 수 있습니다. content 배열 내에서 이미지 및 기타 미디어는 지원되지 않습니다.

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

사용자 정의 도구에서 검색 결과를 반환하면 동적 RAG 애플리케이션을 구현할 수 있습니다. 도구가 런타임에 콘텐츠를 가져오고 Claude가 응답에서 이를 인용합니다. 다음 예제는 tool_choice로 도구 호출을 강제하므로 검색 단계가 매번 실행됩니다.

예제: 지식 베이스 도구

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

client = Anthropic()

# 지식 베이스 검색 도구 정의
knowledge_base_tool = {
    "name": "search_knowledge_base",
    "description": "Search the company knowledge base for information",
    "input_schema": {
        "type": "object",
        "properties": {"query": {"type": "string", "description": "The search query"}},
        "required": ["query"],
    },
}


# 도구 호출을 처리하는 함수
def search_knowledge_base(query):
    # 여기에 검색 로직을 작성하세요
    # 올바른 형식으로 검색 결과를 반환합니다
    return [
        SearchResultBlockParam(
            type="search_result",
            source="https://docs.company.com/product-guide",
            title="Product Configuration Guide",
            content=[
                TextBlockParam(
                    type="text",
                    text="To configure the product, navigate to Settings > Configuration. The default timeout is 30 seconds, but can be adjusted between 10-120 seconds based on your needs.",
                )
            ],
            citations={"enabled": True},
        ),
        SearchResultBlockParam(
            type="search_result",
            source="https://docs.company.com/troubleshooting",
            title="Troubleshooting Guide",
            content=[
                TextBlockParam(
                    type="text",
                    text="If you encounter timeout errors, first check the configuration settings. Common causes include network latency and incorrect timeout values.",
                )
            ],
            citations={"enabled": True},
        ),
    ]


# 사용자의 질문으로 시작하여 대화를 리스트로 구성합니다
messages = [
    MessageParam(role="user", content="How do I configure the timeout settings?")
]

# 도구를 사용하여 메시지를 생성합니다
response = client.messages.create(
    model="claude-opus-5",
    max_tokens=1024,
    tools=[knowledge_base_tool],
    tool_choice={"type": "tool", "name": "search_knowledge_base"},
    messages=messages,
)

# Claude가 도구를 호출하면 검색 결과를 제공합니다.
# tool_use 블록이 항상 첫 번째는 아니므로 반복하여 찾습니다.
tool_use = next((block for block in response.content if block.type == "tool_use"), None)
if tool_use is not None:
    tool_result = search_knowledge_base(tool_use.input["query"])

    # 진행 중인 대화에 Claude의 턴을 추가한 다음 도구 결과를 추가합니다
    messages.append(MessageParam(role="assistant", content=response.content))
    messages.append(
        MessageParam(
            role="user",
            content=[
                ToolResultBlockParam(
                    type="tool_result",
                    tool_use_id=tool_use.id,
                    content=tool_result,  # Search results go here
                )
            ],
        )
    )

    # 도구 결과를 다시 전송합니다
    final_response = client.messages.create(
        model="claude-opus-5",
        max_tokens=1024,
        messages=messages,
    )
    print(final_response)

방법 2: 최상위 콘텐츠로 검색 결과 제공

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

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

예제: 직접 검색 결과

from anthropic.types import MessageParam, TextBlockParam, SearchResultBlockParam

client = Anthropic()

# 사용자 메시지에 검색 결과를 직접 제공합니다
response = client.messages.create(
    model="claude-opus-5-5",
    max_tokens=1024,
    messages=[
        MessageParam(
            role="user",
            content=[
                SearchResultBlockParam(
                    type="search_result",
                    source="https://docs.company.com/api-reference",
                    title="API Reference - Authentication",
                    content=[
                        TextBlockParam(
                            type="text",
                            text="All API requests must include an API key in the Authorization header. Keys can be generated from the dashboard. Rate limits: 1000 requests per hour for standard tier, 10000 for premium.",
                        )
                    ],
                    citations={"enabled": True},
                ),
                SearchResultBlockParam(
                    type="search_result",
                    source="https://docs.company.com/quickstart",
                    title="Getting Started Guide",
                    content=[
                        TextBlockParam(
                            type="text",
                            text="To get started: 1) Sign up for an account, 2) Generate an API key from the dashboard, 3) Install our SDK using pip install company-sdk, 4) Initialize the client with your API key.",
                        )
                    ],
                    citations={"enabled": True},
                ),
                TextBlockParam(
                    type="text",
                    text="Based on these search results, how do I authenticate API requests and what are the rate limits?",
                ),
            ],
        )
    ],
)

print(response)

인용이 포함된 Claude의 응답

검색 결과가 어떤 방식으로 제공되든, Claude는 검색 결과의 정보를 사용할 때 자동으로 인용을 포함합니다:

{
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "All API requests must include an API key in the Authorization header. Keys can be generated from the dashboard.",
      "citations": [
        {
          "type": "search_result_location",
          "cited_text": "All API requests must include an API key in the Authorization header. Keys can be generated from the dashboard. Rate limits: 1000 requests per hour for standard tier, 10000 for premium.",
          "source": "https://docs.company.com/api-reference",
          "title": "API Reference - Authentication",
          "search_result_index": 0,
          "start_block_index": 0,
          "end_block_index": 1
        }
      ]
    },
    {
      "type": "text",
      "text": "\n\nTo set this up from scratch, you'll need to "
    },
    {
      "type": "text",
      "text": "sign up for an account, generate an API key from the dashboard, install the SDK using `pip install company-sdk`, and initialize the client with your API key.",
      "citations": [
        {
          "type": "search_result_location",
          "cited_text": "To get started: 1) Sign up for an account, 2) Generate an API key from the dashboard, 3) Install our SDK using pip install company-sdk, 4) Initialize the client with your API key.",
          "source": "https://docs.company.com/quickstart",
          "title": "Getting Started Guide",
          "search_result_index": 1,
          "start_block_index": 0,
          "end_block_index": 1
        }
      ]
    }
  ]
}

인용 필드

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

필드타입설명
typestring검색 결과 인용의 경우 항상 "search_result_location"
sourcestring원본 검색 결과의 출처
titlestring 또는 null원본 검색 결과의 제목
cited_textstring인용된 블록(들)의 전체 텍스트를 이어 붙인 것. content[start_block_index:end_block_index]의 내용을 결합한 것과 같습니다. 출력 토큰에 포함되지 않습니다.
search_result_indexinteger요청 내 모든 search_result 블록 중 인용된 검색 결과의 0 기반 인덱스로, 나타나는 순서(모든 메시지와 도구 결과에 걸쳐)를 따릅니다.
start_block_indexinteger검색 결과의 content 배열에서 인용된 첫 번째 블록의 0 기반 인덱스.
end_block_indexinteger검색 결과의 content 배열에서 인용된 블록 범위의 배타적(exclusive) 끝 인덱스. 항상 start_block_index보다 큽니다.

블록 인덱스는 검색 결과의 content 배열에서 하나의 슬라이스를 식별하며, cited_text는 해당 슬라이스의 전체 텍스트입니다. 텍스트 블록은 인용 가능한 최소 단위입니다. Claude는 블록 내의 부분 문자열이 아니라 블록 전체를 인용합니다. 더 세밀한 인용을 얻으려면 검색 결과 콘텐츠를 더 작은 블록으로 나누세요(여러 콘텐츠 블록 참조).

여러 콘텐츠 블록

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

{
  "type": "search_result",
  "source": "https://docs.company.com/api-guide",
  "title": "API Documentation",
  "content": [
    {
      "type": "text",
      "text": "Authentication: All API requests require an API key."
    },
    {
      "type": "text",
      "text": "Rate Limits: The API allows 1000 requests per hour per key."
    },
    {
      "type": "text",
      "text": "Error Handling: The API returns standard HTTP status codes."
    }
  ],
  "citations": { "enabled": true }
}

속도 제한 블록을 참조하는 인용은 다음과 같습니다:

{
  "type": "search_result_location",
  "cited_text": "Rate Limits: The API allows 1000 requests per hour per key.",
  "source": "https://docs.company.com/api-guide",
  "title": "API Documentation",
  "search_result_index": 0,
  "start_block_index": 1,
  "end_block_index": 2
}

이 검색 결과가 인용되면 start_block_index와 end_block_index가 인용이 어떤 블록을 포함하는지 식별하고, cited_text에는 정확히 해당 블록들의 텍스트가 담깁니다. 콘텐츠를 더 작고 집중된 블록으로 나누면 Claude에게 더 세밀한 인용 경계를 제공하며, 콘텐츠를 하나의 블록으로 합치면 모든 인용이 전체 텍스트를 반환합니다. 이는 인용 기능의 사용자 정의 콘텐츠 문서에서 사용하는 것과 동일한 모델입니다.

고급 사용법

두 방법 결합하기

같은 대화에서 두 방법을 혼합할 수 있습니다. Claude는 어느 출처에서든 인용하며, search_result_index는 출처에 관계없이 요청 순서대로 모든 search_result 블록을 셉니다.

다음 예제는 전체 대화를 재현합니다. 첫 번째 사용자 메시지에는 미리 가져온 검색 결과가 담겨 있고, 어시스턴트 턴은 지식 베이스 도구를 호출하며, 도구 결과는 두 번째 검색 결과를 반환합니다. Claude의 답변은 두 출처를 모두 인용합니다:

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

client = Anthropic()

knowledge_base_tool = {
    "name": "search_knowledge_base",
    "description": "Search the company knowledge base for information",
    "input_schema": {
        "type": "object",
        "properties": {"query": {"type": "string", "description": "The search query"}},
        "required": ["query"],
    },
}

# 검색 결과를 두 가지 방식으로 모두 제공하는 대화를 재현합니다. 첫 번째
# 사용자 메시지에는 미리 가져온 결과가 담기고, 도구 결과는 또 다른 결과를 반환합니다
response = client.messages.create(
    model="claude-opus-5-5",
    max_tokens=1024,
    tools=[knowledge_base_tool],
    messages=[
        MessageParam(
            role="user",
            content=[
                SearchResultBlockParam(
                    type="search_result",
                    source="https://docs.company.com/overview",
                    title="Product Overview",
                    content=[
                        TextBlockParam(
                            type="text",
                            text="Acme Dashboard is a monitoring tool for distributed systems. It supports real-time alerting and custom metric dashboards.",
                        )
                    ],
                    citations={"enabled": True},
                ),
                TextBlockParam(
                    type="text",
                    text="What does Acme Dashboard do, and what plans is it available on?",
                ),
            ],
        ),
        MessageParam(
            role="assistant",
            content=[
                TextBlockParam(
                    type="text", text="Let me check the pricing information."
                ),
                ToolUseBlockParam(
                    type="tool_use",
                    id="toolu_01A09q90qw90lq917835lq9",
                    name="search_knowledge_base",
                    input={"query": "Acme Dashboard pricing plans"},
                ),
            ],
        ),
        MessageParam(
            role="user",
            content=[
                ToolResultBlockParam(
                    type="tool_result",
                    tool_use_id="toolu_01A09q90qw90lq917835lq9",
                    content=[
                        SearchResultBlockParam(
                            type="search_result",
                            source="https://docs.company.com/pricing",
                            title="Pricing Plans",
                            content=[
                                TextBlockParam(
                                    type="text",
                                    text="Acme Dashboard is available on the Starter plan at $10 per user per month and the Enterprise plan with custom pricing.",
                                )
                            ],
                            citations={"enabled": True},
                        )
                    ],
                )
            ],
        ),
    ],
)

print(response)

응답은 두 출처를 모두 인용합니다. 미리 가져온 결과는 search_result_index: 0이고 도구가 반환한 결과는 search_result_index: 1로, 대화에서 search_result 블록이 나타나는 순서와 일치합니다:

{
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "Here's what I found about Acme Dashboard:\n\n**What it does:** "
    },
    {
      "type": "text",
      "text": "Acme Dashboard is a monitoring tool for distributed systems. It supports real-time alerting and custom metric dashboards.",
      "citations": [
        {
          "type": "search_result_location",
          "cited_text": "Acme Dashboard is a monitoring tool for distributed systems. It supports real-time alerting and custom metric dashboards.",
          "source": "https://docs.company.com/overview",
          "title": "Product Overview",
          "search_result_index": 0,
          "start_block_index": 0,
          "end_block_index": 1
        }
      ]
    },
    {
      "type": "text",
      "text": "\n\n**Available plans:** "
    },
    {
      "type": "text",
      "text": "Acme Dashboard is available on the Starter plan at $10 per user per month and the Enterprise plan with custom pricing.",
      "citations": [
        {
          "type": "search_result_location",
          "cited_text": "Acme Dashboard is available on the Starter plan at $10 per user per month and the Enterprise plan with custom pricing.",
          "source": "https://docs.company.com/pricing",
          "title": "Pricing Plans",
          "search_result_index": 1,
          "start_block_index": 0,
          "end_block_index": 1
        }
      ]
    }
  ]
}

다른 콘텐츠 타입과 혼합하기

사용자 메시지에서 search_result 블록은 다른 어떤 콘텐츠 블록과도 함께 배치할 수 있습니다. 방법 2 예제는 검색 결과를 text 질문과 함께 사용하며, 이미지나 문서 블록도 같은 방식으로 함께 포함할 수 있습니다.

도구 결과는 더 엄격합니다. tool_result 콘텐츠 배열의 블록 중 하나라도 search_result이면 모든 블록이 search_result여야 합니다. 같은 도구 결과에서 검색 결과를 다른 블록 타입과 혼합하면 유효성 검사 오류가 반환됩니다. 도구에서 가져온 검색 결과와 함께 보조 텍스트를 반환하려면, 검색 결과 중 하나의 content 배열 안에 텍스트 블록으로 포함하세요. 그러면 해당 텍스트도 인용 가능해집니다.

캐시 제어

검색 결과 블록에 cache_control을 추가하면 여러 요청에 걸쳐 재사용할 수 있도록 캐시됩니다. 같은 블록에서 citations와 나란히 위치합니다:

{
  "type": "search_result",
  "source": "https://docs.company.com/guide",
  "title": "User Guide",
  "content": [{ "type": "text", "text": "..." }],
  "citations": { "enabled": true },
  "cache_control": { "type": "ephemeral" }
}

캐시 가능한 최소 길이 및 기타 요구 사항은 프롬프트 캐싱을 참조하세요.

인용 제어

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

{
  "type": "search_result",
  "source": "https://docs.company.com/guide",
  "title": "User Guide",
  "content": [{ "type": "text", "text": "Important documentation..." }],
  "citations": {
    "enabled": true // Enable citations for this result
  }
}

citations.enabled가 true로 설정되면 Claude는 검색 결과를 참고한 텍스트 블록에 인용 참조를 첨부합니다.

모범 사례

도구 기반 검색(방법 1)의 경우

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

최상위 검색(방법 2)의 경우

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

일반 모범 사례

  1. 결과를 효과적으로 구조화하세요:

    • 명확하고 영구적인 출처 URL을 사용하세요
    • 설명적인 제목을 제공하세요
    • 긴 콘텐츠를 논리적인 텍스트 블록으로 나누어 Claude에게 더 세밀한 인용 경계를 제공하세요
  2. 일관성을 유지하세요:

    • 애플리케이션 전반에서 일관된 출처 형식을 사용하세요
    • 제목이 콘텐츠를 정확히 반영하도록 하세요
    • 형식을 일관되게 유지하세요
  3. 오류를 우아하게 처리하세요: 검색이 실패하거나 아무것도 반환하지 않을 때, 오류를 발생시키는 대신 결과를 설명하는 일반 텍스트 블록(예: {"type": "text", "text": "No results found."})을 반환하세요. Claude가 사용자에게 빈 결과를 설명하고 대화가 계속됩니다.

제한 사항

  • 검색 결과 콘텐츠 블록은 Claude API, Amazon Bedrock, Google Cloud에서 사용할 수 있습니다.
  • 검색 결과 내에서는 텍스트 콘텐츠만 지원됩니다(이미지나 기타 미디어는 지원되지 않음).
  • search_result 블록은 사용자 메시지(도구 결과 내부 포함)에만 나타날 수 있습니다. 검색 결과가 포함된 어시스턴트 메시지는 거부됩니다.
  • 같은 요청에서 웹 검색 도구가 활성화되어 있으면 모든 search_result 블록에서 인용이 활성화되어야 합니다.

다음 단계

스트리밍 응답에서 거부 중단 사유를 감지하고 처리하며, 거부된 요청을 대체 모델에서 재시도합니다.

Claude의 응답을 여러분의 원본 문서에 근거하도록 합니다. 인용은 각 주장을 뒷받침하는 정확한 구절을 반환하므로, 답변을 검증하고 사용자에게 출처를 표시할 수 있습니다.

인용된 출처, 선택적 동적 필터링, 도메인 제어와 함께 Claude에게 최신 웹 콘텐츠에 대한 접근 권한을 부여합니다.

콘텐츠 블록 타입을 포함한 전체 Messages API 문서를 확인하세요.

cache_control로 검색 결과를 캐시하여 반복 요청 시 비용과 지연 시간을 줄이세요.

Was this page helpful?