官方更新 AWS ML Blog Wed, 30 Sep 2026 正文 ok 2985 words

使用 Amazon Bedrock Knowledge Bases 以自然语言查询理赔信息

英文标题:Query claims in natural language with Amazon Bedrock Knowledge Bases

本文介绍如何基于 Amazon Bedrock Knowledge Bases 构建一个对话式理赔助手,使其能够针对自然语言问题返回附带引文的答案。方案将 Amazon S3 中的理赔文档及其元数据导入知识库,并通过 `AgenticRetrieveStream` API 支持多轮追问、元数据过滤和流式返回检索轨迹、答案及引用。文章还说明了如何利用理赔编号、险种、状态、金额和报案日期等元数据缩小检索范围,以及如何通过上下文事实依据护栏确保回答受源记录约束。对于开发者而言,该方案展示了如何用托管式 RAG 能力处理分散、可能互相冲突且需满足可审计要求的理赔材料。
打开原文相关 1.8 · 机会 3
media1.3 MB media101.1 KB media124.1 KB media345.0 KB media141.2 KB media346.5 KB media120.1 KB media138.1 KB media68.9 KB media67.4 KB media27.0 KB media28.4 KB media200.2 KB

中文

理赔答案分散在理算员日志条目、维修估价单、警方报告、付款台账和扫描附件中,而不是集中在一个可搜索字段里。投保人可能会询问某笔理赔是否已获批准,而理算员可能需要找出上个月所有金额超过 10,000 美元的未结汽车理赔。这两类任务都要求快速且准确地查找并整合证据。

检索增强生成(Retrieval Augmented Generation,RAG)使用检索到的文档为模型响应提供事实依据。Amazon Bedrock Knowledge Bases 是一项面向文档的全托管 RAG 能力。Amazon Bedrock 负责解析、分块、嵌入和向量存储,因此你可以构建一个对话式界面,从理赔文件中返回带引文的答案。

本技术指南使用合成理赔记录,并不描述生产环境中的客户部署。通过完成以下步骤,你将构建一个可回答自然语言问题并提供引文的理赔助手:

  • 从 Amazon Simple Storage Service(Amazon S3)导入理赔文档及其元数据。
  • 使用 AgenticRetrieveStream API 以自然语言查询这些文档。
  • 提出多轮后续问题。
  • 使用理赔 ID、理赔类型等属性上的元数据过滤器限定检索范围。
  • 添加上下文事实依据护栏,使答案始终与记录保持关联。

理赔查询面临的挑战

投保人、呼叫中心客服人员和理算员会提出不同的问题:

  • 投保人需要通俗易懂的状态更新:“理赔编号 CLM-100482 的估价是否已获批准?支票何时签发?”
  • 呼叫中心客服人员需要在客户等待时快速、准确地提供答案,而无需转接电话。
  • 理算员会提出跨理赔记录的多部分问题,例如:上个月提交的、金额超过 10,000 美元的未结汽车理赔有哪些,以及每笔理赔还剩哪些工作未完成。

答案存储在 PDF 格式的理算员报告、Word 往来函件和文本备注中,而不是一致的数据库字段中。

记录可能彼此冲突,或由较新版本替代先前版本。修订后的估价可能会取代先前的估价,临时付款也可能在之后被撤销。助手必须识别哪份估价、付款或状态记录具有控制效力。

由于理赔业务受到监管,每个答案都必须以源文档为依据并包含引文。呼叫中心客服人员可以在复述答案前核查来源,主管人员则可以审计助手得出答案的过程。

解决方案概览

该解决方案使用 Amazon Bedrock Knowledge Bases 为 Amazon S3 中的理赔文档建立索引,以供检索。

通过 AgenticRetrieveStream 实现的智能体检索(Agentic retrieval)会规划答案,将多部分问题拆分为子查询,并执行一次或多次检索。它会在生成响应前检查证据是否充分。

该 API 会流式传输轨迹事件、答案文本和引文。轨迹事件会公开检索计划,每条引文都会将答案的一部分映射到源理赔文档。

下图展示了两条路径。导入通道会将理赔文档和元数据加载到知识库中。检索通道会将每个问题依次送入 AgenticRetrieveStream 和 Amazon Bedrock Guardrails 的事实依据检查,然后返回带引文的答案。

架构图:导入通道从 Amazon S3 延伸至 Amazon Bedrock Knowledge Bases 和托管向量存储;检索通道从用户经由理赔助手、AgenticRetrieveStream 和 Amazon Bedrock Guardrails,最终得到带引文的答案

图 1:使用 Amazon Bedrock Knowledge Bases 的对话式理赔助手

导入通道会在文档到达时运行:

  1. PDF、Word 或文本格式的理赔文档连同对应的元数据附属文件一同存入 Amazon S3。
  2. 随着文档发生变化,导入作业会将 S3 数据源与知识库同步。
  3. 知识库会解析、分块、嵌入并在托管向量存储中索引文档及其元数据。

检索通道会针对每个问题运行:

  1. 应用程序使用问题、对话历史记录和用于限定搜索范围的可选元数据过滤器调用 AgenticRetrieveStream。
  2. 基础模型会创建子查询并重复检索,直到获得足够证据,最多进行 maxAgentIteration 轮。
  3. 上下文事实依据检查会阻止没有检索记录支持的答案。
  4. Amazon Bedrock 会流式传输答案、轨迹事件和引文,使应用程序能够在输出到达时进行显示。

前提条件

开始之前,请确认你具备以下条件:

  • 一个 AWS 账户,并拥有用于 Amazon Bedrock 和 Amazon S3 的 AWS Identity and Access Management(IAM)权限。
  • 已通过 Amazon Bedrock 模型访问权限启用的基础模型(FM)访问权限。
  • 一个支持所选基础模型和 Amazon Bedrock Knowledge Bases 的 AWS 区域。本指南使用美国西部(俄勒冈)区域 us-west-2。部署前,请查看 Amazon Bedrock 中按 AWS 区域划分的受支持模型。
  • 已配置凭证且版本支持本文所用 API 的 Python AWS SDK(Boto3)。
  • 一个用于存放合成理赔文档和元数据的 S3 存储桶。
  • 熟悉 Python 和基本 RAG 概念。

将每笔理赔存储为 Amazon S3 中的一个文档。知识库可以直接读取 PDF 理算员报告、Word 往来函件和文本备注,因此你可以保留文档的原生格式。

图 2 展示了一份合成理赔记录。当前风险暴露金额是预计的理赔总成本。其证据索引标识了一份被替代的传真草稿,即被较新版本替换的记录。元数据附属文件重复了助手可用于过滤的字段。

展示文件控制字段和证据索引的合成理赔记录

图 2:包含文件控制字段和证据索引的合成理赔记录

为支持过滤,请添加一个同名且附加 .metadata.json 的元数据文件。对于 CLM-100482.pdf,应使用 CLM-100482.pdf.metadata.json。代位求偿是指保险公司向负有责任的第三方追偿成本的行为。以下示例描述了一笔汽车理赔:

{
    "metadataAttributes": {
        "claim_id": "CLM-100482",
        "claim_type": "auto",
        "status": "open",
        "date_filed": 20260709,
        "amount": 14250,
        "region": "us-west",
        "adjuster": "Martha Rivera",
        "policyholder": "Mary Major",
        "policy_number": "POL-AUTO-78432",
        "customer_id": "CUST-MM-1042",
        "household_id": "HHD-MM-1042",
        "document_type": "adjuster_report",
        "carrier": "Example Insurance",
        "has_subrogation": true,
        "has_litigation": false,
        "complexity_tier": "high"
    }
}

附属文件包含标量字符串、数字和布尔值。值的类型决定可用的过滤器。下表列出了后续查询中使用的字段。

本文使用合成数据。若未具备所需控制措施和审批流程,请勿在这些资源中放置真实的个人身份信息(PII)或受保护健康信息。

属性 类型 示例 过滤用途
claim_id 字符串 CLM-100482 使用 equals 查询单笔理赔
claim_type 字符串 auto 使用 equals 或 in 按业务线过滤
status 字符串 open 使用 in 查询活跃工作队列
amount 数字 14250 数值范围比较
date_filed 数字 20260709 将日期范围表示为 YYYYMMDD 整数
region 字符串 us-west 根据会话进行租户范围限定
customer_id 字符串 CUST-MM-1042 根据会话进行客户范围限定
has_subrogation 布尔值 true 对追偿工作使用 equals

将日期存储为 YYYYMMDD 整数,因为元数据过滤器比较的是数字而不是日期字符串。这种格式支持“上个月提交”等范围查询。

在 amount 中仅存储一个可比较的货币值。准备金是为预计理赔成本预留的资金,而冻结款项是暂时扣留的资金。应将准备金、付款和冻结款项保留在文档文本中,使其标签保持清晰。

附属文件大小限制为 10 KB。有关完整格式,请参阅为知识库连接至 Amazon S3。

S3 布局会将每份理赔文档与其元数据文件配对:

s3://amzn-s3-demo-insurance-claims/claims/CLM-100482.pdf
s3://amzn-s3-demo-insurance-claims/claims/CLM-100482.pdf.metadata.json
s3://amzn-s3-demo-insurance-claims/claims/CLM-100517.docx
s3://amzn-s3-demo-insurance-claims/claims/CLM-100517.docx.metadata.json
s3://amzn-s3-demo-insurance-claims/claims/CLM-100533.txt
s3://amzn-s3-demo-insurance-claims/claims/CLM-100533.txt.metadata.json

创建托管知识库并导入理赔数据

使用 bedrock-agent 客户端创建知识库。将 knowledgeBaseConfiguration.type 和 embeddingModelType 设为 MANAGED。

Amazon Bedrock 会选择并运行嵌入模型,无需配置向量存储。有关全部参数,请参阅 CreateKnowledgeBase。以下代码将创建知识库:

import boto3

bedrock_agent = boto3.client("bedrock-agent", region_name="us-west-2")

kb = bedrock_agent.create_knowledge_base(
    name="insurance-claims-kb",
    description="Synthetic insurance claims for the claims assistant",
    roleArn="arn:aws:iam::111122223333:role/InsuranceClaimsKnowledgeBaseRole",
    knowledgeBaseConfiguration={
        "type": "MANAGED",
        "managedKnowledgeBaseConfiguration": {
            "embeddingModelType": "MANAGED"
        },
    },
)
kb_id = kb["knowledgeBase"]["knowledgeBaseId"]

roleArn 服务角色会授予知识库读取 S3 存储桶以及使用托管嵌入模型的权限。请参阅为 Amazon Bedrock Knowledge Bases 创建服务角色。如需使用客户自主管理的 AWS Key Management Service(AWS KMS) 密钥加密托管向量存储,请在 serverSideEncryptionConfiguration 中传入该密钥的 ARN。

接下来,将 S3 存储桶连接为数据源。inclusionPrefixes 设置会将导入范围限制在 claims/:

data_source = bedrock_agent.create_data_source(
    knowledgeBaseId=kb_id,
    name="claims-s3",
    dataSourceConfiguration={
        "type": "S3",
        "s3Configuration": {
            "bucketArn": "arn:aws:s3:::amzn-s3-demo-insurance-claims",
            "inclusionPrefixes": ["claims/"],
        },
    },
)
data_source_id = data_source["dataSource"]["dataSourceId"]

启动导入作业,以解析、分块、嵌入和索引文档。每当新增或更新理赔文档时,都应再次运行该作业,以保持索引同步:

bedrock_agent.start_ingestion_job(
    knowledgeBaseId=kb_id,
    dataSourceId=data_source_id,
)

可通过 get_ingestion_job 或 Amazon Bedrock 控制台检查状态。作业完成后,理赔记录即可被搜索。有关详细信息,请参阅 StartIngestionJob。

使用 AgenticRetrieveStream API 查询理赔信息

导入理赔数据后,使用 bedrock-agent-runtime 客户端调用 AgenticRetrieveStream。有关完整的请求和响应语法,请参阅 API 参考文档。请求包含三个部分:

  • messages:对话轮次。每条消息均包含 user 或 assistant 角色,以及 content.text 值。
  • retrievers:最多可使用五个知识库。每个知识库均包含知识库 ID,并可指定元数据过滤器和 maxNumberOfResults(1–100)。对于跨越多笔理赔的问题,应提高此限制。
  • agenticRetrieveConfiguration:规划模型和迭代限制。使用 MANAGED 调用服务模型。如需使用特定模型,请使用带模型 ARN 的 CUSTOM。maxAgentIteration 用于限制规划和检索轮次的上限。

以下请求查询一笔理赔的状态。将 generateResponse 设置为 True 会返回自然语言答案:

bedrock_agent_runtime = boto3.client("bedrock-agent-runtime", region_name="us-west-2")

response = bedrock_agent_runtime.agentic_retrieve_stream(
    messages=[
        {"role": "user", "content": {"text": "What is the status of claim CLM-100482?"}}
    ],
    retrievers=[
        {
            "configuration": {"knowledgeBase": {"knowledgeBaseId": kb_id}},
            "description": "Synthetic insurance claim records",
        }
    ],
    agenticRetrieveConfiguration={
        "foundationModelType": "MANAGED",
        "maxAgentIteration": 5,
    },
    generateResponse=True,
)

遍历 response["stream"],并处理以下三种事件类型:

  • trace

English / 原文

Claim answers are scattered across adjuster diary entries, repair estimates, police reports, payment ledgers, and scanned attachments rather than one searchable field. A policyholder might ask whether a claim was approved, while an adjuster might need every open auto claim over $10,000 from last month. Both tasks require finding and combining evidence quickly and accurately.

Retrieval Augmented Generation (RAG) uses retrieved documents to ground model responses. Amazon Bedrock Knowledge Bases is the fully managed RAG capability for documents. Amazon Bedrock handles parsing, chunking, embeddings, and vector storage, so you can build a conversational interface that returns cited answers from claim files.

This technical how-to uses synthetic claim records and doesn’t describe a production customer deployment. You build a claims assistant that answers natural-language questions with citations by completing these steps:

  • Ingest claim documents and their metadata from Amazon Simple Storage Service (Amazon S3).
  • Query them in plain language with the AgenticRetrieveStream API.
  • Ask multi-turn follow-up questions.
  • Scope retrieval with metadata filters on attributes such as claim ID and claim type.
  • Add a contextual grounding guardrail to keep answers tied to the records.

The claims lookup challenge

Policyholders, contact center agents, and adjusters ask different questions:

  • Policyholders ask for a plain-language status update: “Has the estimate for claim CLM-100482 been approved, and when will the check be issued?”
  • Contact center agents need a fast, accurate answer while the customer waits, without transferring the call.
  • Adjusters ask multi-part questions across claims, such as which open auto claims over $10,000 were filed last month and what work remains on each.

Answers are stored in PDF adjuster reports, Word correspondence, and text notes rather than consistent database fields.

Records can conflict or supersede earlier versions. A revised estimate can replace an earlier one, or a provisional payment can be reversed later. The assistant must identify which estimate, payment, or status controls.

Because claims are regulated, every answer must be grounded in source documents and include citations. Contact center agents can verify a source before repeating an answer, and supervisors can audit how the assistant reached it.

Solution overview

The solution uses Amazon Bedrock Knowledge Bases to index claim documents from Amazon S3 for retrieval.

Agentic retrieval through AgenticRetrieveStream plans an answer, breaks a multi-part question into sub-queries, and runs one or more retrieval passes. It checks whether the evidence is sufficient before generating a response.

The API streams trace events, answer text, and citations. Trace events expose the retrieval plan, and each citation maps part of the answer to a source claim document.

The following diagram shows both paths. The ingestion lane loads claim documents and metadata into a knowledge base. The retrieval lane sends each question through AgenticRetrieveStream and an Amazon Bedrock Guardrails grounding check before returning a cited answer.

Architecture with an ingestion lane from Amazon S3 to Amazon Bedrock Knowledge Bases and managed vector storage, and a retrieval lane from the user through the claims assistant, AgenticRetrieveStream, and Amazon Bedrock Guardrails to a cited answer

Figure 1: Conversational claims assistant with Amazon Bedrock Knowledge Bases

The ingestion lane runs as documents arrive:

  1. Claim documents in PDF, Word, or text format land in Amazon S3 with matching metadata sidecars.
  2. An ingestion job synchronizes the S3 data source with the knowledge base as documents change.
  3. The knowledge base parses, chunks, embeds, and indexes the documents and their metadata in managed vector storage.

The retrieval lane runs for each question:

  1. The application calls AgenticRetrieveStream with the question, conversation history, and optional metadata filters that scope the search.
  2. A foundation model creates sub-queries and repeats retrieval until it has enough evidence, up to maxAgentIteration rounds.
  3. A contextual grounding check blocks answers that are unsupported by the retrieved records.
  4. Amazon Bedrock streams the answer, trace events, and citations, so the application can display output as it arrives.

Prerequisites

Before you begin, verify that you have the following:

  • An AWS account with AWS Identity and Access Management (IAM) permissions for Amazon Bedrock and Amazon S3.
  • Access to a foundation model (FM) enabled through Amazon Bedrock model access.
  • An AWS Region that supports the selected foundation model and Amazon Bedrock Knowledge Bases. This walkthrough uses US West (Oregon), us-west-2. Check Supported models by AWS Region in Amazon Bedrock before deployment.
  • The AWS SDK for Python (Boto3), configured with credentials and a version that supports the APIs used here.
  • An S3 bucket for the synthetic claim documents and metadata.
  • Familiarity with Python and with basic RAG concepts.

Store one document per claim in Amazon S3. The knowledge base reads PDF adjuster reports, Word correspondence, and text notes directly, so you can keep documents in their native format.

Figure 2 shows a synthetic claim record. Current exposure is the estimated total claim cost. Its evidence index identifies a superseded fax draft, meaning a record replaced by a newer version. The metadata sidecar repeats fields that the assistant can filter.

A synthetic claim record showing its file-control fields and evidence index

Figure 2: A synthetic claim record with its file-control fields and evidence index

For filtering, add an accompanying metadata file with the same name plus .metadata.json. For CLM-100482.pdf, use CLM-100482.pdf.metadata.json. Subrogation is an insurer’s effort to recover costs from a responsible third party. The following example describes one auto claim:

{
    "metadataAttributes": {
        "claim_id": "CLM-100482",
        "claim_type": "auto",
        "status": "open",
        "date_filed": 20260709,
        "amount": 14250,
        "region": "us-west",
        "adjuster": "Martha Rivera",
        "policyholder": "Mary Major",
        "policy_number": "POL-AUTO-78432",
        "customer_id": "CUST-MM-1042",
        "household_id": "HHD-MM-1042",
        "document_type": "adjuster_report",
        "carrier": "Example Insurance",
        "has_subrogation": true,
        "has_litigation": false,
        "complexity_tier": "high"
    }
}

The sidecar contains scalar string, number, and Boolean values. Value types determine available filters. The following table lists fields used later in the queries.

This post uses synthetic data. Don’t place real personally identifiable information (PII) or protected health information in these resources without the required controls and approvals.

Attribute Type Example Filter use
claim_id String CLM-100482 equals for a single-claim lookup
claim_type String auto equals or in for a line of business
status String open in for active work queues
amount Number 14250 numeric range comparisons
date_filed Number 20260709 date ranges as YYYYMMDD integers
region String us-west tenant scoping from the session
customer_id String CUST-MM-1042 customer scoping from the session
has_subrogation Boolean true equals for recovery work

Store dates as YYYYMMDD integers because metadata filters compare numbers rather than date strings. This format supports ranges such as “filed last month.”

Store only one comparable monetary value in amount. A reserve is money set aside for the estimated claim cost, while a hold is temporarily withheld. Keep reserves, payments, and holds in document text so their labels remain clear.

Sidecar files are limited to 10 KB. See Connect to Amazon S3 for your knowledge base for the complete format.

The S3 layout pairs each claim document with its metadata file:

s3://amzn-s3-demo-insurance-claims/claims/CLM-100482.pdf
s3://amzn-s3-demo-insurance-claims/claims/CLM-100482.pdf.metadata.json
s3://amzn-s3-demo-insurance-claims/claims/CLM-100517.docx
s3://amzn-s3-demo-insurance-claims/claims/CLM-100517.docx.metadata.json
s3://amzn-s3-demo-insurance-claims/claims/CLM-100533.txt
s3://amzn-s3-demo-insurance-claims/claims/CLM-100533.txt.metadata.json

Create the managed knowledge base and ingest the claims

Create the knowledge base with the bedrock-agent client. Set knowledgeBaseConfiguration.type and embeddingModelType to MANAGED.

Amazon Bedrock selects and operates the embedding model. No vector store configuration is required. See CreateKnowledgeBase for all parameters. The following code creates the knowledge base:

import boto3

bedrock_agent = boto3.client("bedrock-agent", region_name="us-west-2")

kb = bedrock_agent.create_knowledge_base(
    name="insurance-claims-kb",
    description="Synthetic insurance claims for the claims assistant",
    roleArn="arn:aws:iam::111122223333:role/InsuranceClaimsKnowledgeBaseRole",
    knowledgeBaseConfiguration={
        "type": "MANAGED",
        "managedKnowledgeBaseConfiguration": {
            "embeddingModelType": "MANAGED"
        },
    },
)
kb_id = kb["knowledgeBase"]["knowledgeBaseId"]

The roleArn service role grants the knowledge base permission to read the S3 bucket and use the managed embedding model. See Create a service role for Amazon Bedrock Knowledge Bases. To encrypt managed vector storage with a customer managed AWS Key Management Service (AWS KMS) key, pass its ARN in serverSideEncryptionConfiguration.

Next, connect the S3 bucket as a data source. The inclusionPrefixes setting limits ingestion to claims/:

data_source = bedrock_agent.create_data_source(
    knowledgeBaseId=kb_id,
    name="claims-s3",
    dataSourceConfiguration={
        "type": "S3",
        "s3Configuration": {
            "bucketArn": "arn:aws:s3:::amzn-s3-demo-insurance-claims",
            "inclusionPrefixes": ["claims/"],
        },
    },
)
data_source_id = data_source["dataSource"]["dataSourceId"]

Start an ingestion job to parse, chunk, embed, and index the documents. Run it again whenever claim documents are added or updated so the index stays synchronized:

bedrock_agent.start_ingestion_job(
    knowledgeBaseId=kb_id,
    dataSourceId=data_source_id,
)

Check status with get_ingestion_job or the Amazon Bedrock console. When the job completes, the claims are searchable. See StartIngestionJob for details.

Query claims with the AgenticRetrieveStream API

With the claims ingested, call AgenticRetrieveStream with the bedrock-agent-runtime client. See the API reference for complete request and response syntax. The request has three parts:

  • messages: Conversation turns. Each message has a user or assistant role and a content.text value.
  • retrievers: Up to five knowledge bases. Each includes a knowledge base ID and can specify a metadata filter and maxNumberOfResults (1–100). Increase the limit for questions that span many claims.
  • agenticRetrieveConfiguration: Planning model and iteration limit. Use MANAGED for the service model. To use a specific model, use CUSTOM with a model ARN. maxAgentIteration caps the number of planning and retrieval rounds.

This request asks for one claim’s status. Setting generateResponse to True returns a natural-language answer:

bedrock_agent_runtime = boto3.client("bedrock-agent-runtime", region_name="us-west-2")

response = bedrock_agent_runtime.agentic_retrieve_stream(
    messages=[
        {"role": "user", "content": {"text": "What is the status of claim CLM-100482?"}}
    ],
    retrievers=[
        {
            "configuration": {"knowledgeBase": {"knowledgeBaseId": kb_id}},
            "description": "Synthetic insurance claim records",
        }
    ],
    agenticRetrieveConfiguration={
        "foundationModelType": "MANAGED",
        "maxAgentIteration": 5,
    },
    generateResponse=True,
)

Iterate over response[“stream”] and handle these three event types:

  • traceEvent: Reports planning, retrieval, full-document expansion, guardrail actions, status, and generated sub-queries for each step.
  • responseEvent: Provides incremental answer text that you can stream to the user.
  • result: Contains deduplicated retrieval results and, when generateResponse is True, the complete generated answer and its citations.

The following loop streams answer chunks as they arrive and retains the final result for citation rendering:

answer = ""
final_result = None

for event in response["stream"]:
    if "traceEvent" in event:
        attributes = event["traceEvent"]["attributes"]
        print(f"[trace] {attributes.get('step')}: {attributes.get('status')}")
    elif "responseEvent" in event:
        chunk = event["responseEvent"]["text"]
        answer += chunk
        print(chunk, end="", flush=True)
    elif "result" in event:
        final_result = event["result"]

Read the trace to see the plan

The basic loop prints each step and status. This helper also prints sub-queries, full-document fetches, and guardrail actions:

def report_trace(trace_event):
    attributes = trace_event.get("attributes", {})
    print(f"[trace] {attributes.get('step')}: {attributes.get('status')}")

    for action in attributes.get("actions", []):
        if "retrieve" in action:
            sub_query = action["retrieve"].get("inputQuery", {}).get("text", "")
            print(f"    sub-query: {sub_query}")
        elif "fullDocumentExpansion" in action:
            document = action["fullDocumentExpansion"].get("documentId", "")
            print(f"    full document: {document}")

    for warning in attributes.get("warnings", []):
        if "guardrail" in warning:
            print(f"    guardrail: {warning['guardrail'].get('action')}")

Figure 3 shows the agentic loop. The service plans a strategy, creates sub-queries, retrieves evidence, and checks whether it has enough. If needed, it runs another pass before generating a cited answer.

Diagram of the agentic retrieval loop from question to cited answer

Figure 3: The agentic retrieval loop from question to cited answer

Render citations

Each citation identifies a character span in the answer and references supporting entries in the result event’s results array. The application uses the indexes to associate the displayed text with its source documents.

The following code prints each cited span beside the built-in x-amz-bedrock-kb-source-uri value for its source document:

generated = final_result["generatedResponse"]
results = final_result["results"]

for citation in generated.get("citations", []):
    span = generated["answer"][citation["startIndex"]:citation["endIndex"]]
    for reference in citation["references"]:
        source = results[reference["resultIndex"]]
        source_uri = source.get("metadata", {}).get("x-amz-bedrock-kb-source-uri")
        print(f'"{span}"\n  -> {source_uri}')

Ask follow-up questions in a multi-turn conversation

Follow-up questions depend on prior turns. After a status answer, a policyholder might ask, “Who is the adjuster assigned to it?” The word it is resolved from the conversation history passed in messages.

Keep the conversation in the application. After each turn, append the user’s question and the assistant’s answer, then send the complete list on the next call:

messages = [
    {"role": "user", "content": {"text": "What is the status of claim CLM-100482?"}},
    {"role": "assistant", "content": {"text": answer}},
    {"role": "user", "content": {"text": "Who is the adjuster assigned to it?"}},
]

response = bedrock_agent_runtime.agentic_retrieve_stream(
    messages=messages,
    retrievers=[
        {"configuration": {"knowledgeBase": {"knowledgeBaseId": kb_id}}}
    ],
    agenticRetrieveConfiguration={"foundationModelType": "MANAGED"},
    generateResponse=True,
)

The service uses earlier turns to resolve it to claim CLM-100482 and retrieves that claim’s adjuster. Process the response stream as before.

Metadata filters restrict documents before semantic search. Add them under the retriever’s retrievalOverrides. Use query filters for relevance, and derive authorization filters from the authenticated session on the server.

For a direct lookup by claim ID, use an equals filter:

retrievers = [
    {
        "configuration": {
            "knowledgeBase": {
                "knowledgeBaseId": kb_id,
                "retrievalOverrides": {
                    "filter": {"equals": {"key": "claim_id", "value": "CLM-100482"}}
                },
            }
        }
    }
]

For open auto claims over $10,000 filed in July 2026, combine claim type, status, amount, and date conditions with andAll:

claims_filter = {
    "andAll": [
        {"equals": {"key": "claim_type", "value": "auto"}},
        {"equals": {"key": "status", "value": "open"}},
        {"greaterThan": {"key": "amount", "value": 10000}},
        {"greaterThanOrEquals": {"key": "date_filed", "value": 20260701}},
        {"lessThanOrEquals": {"key": "date_filed", "value": 20260731}},
    ]
}

response = bedrock_agent_runtime.agentic_retrieve_stream(
    messages=[
        {
            "role": "user",
            "content": {
                "text": "Summarize the outstanding items on the open auto "
                        "claims over $10,000 filed in July."
            },
        }
    ],
    retrievers=[
        {
            "configuration": {
                "knowledgeBase": {
                    "knowledgeBaseId": kb_id,
                    "retrievalOverrides": {
                        "filter": claims_filter,
                        "maxNumberOfResults": 50,
                    },
                }
            }
        }
    ],
    agenticRetrieveConfiguration={"foundationModelType": "MANAGED"},
    generateResponse=True,
)

This query can match many claims, so maxNumberOfResults is 50. A smaller limit could omit matching claims from the summary.

Supported operators include equals, notEquals, numeric comparisons, in, notIn, stringContains, listContains, and logical andAll/orAll. startsWith is limited to Amazon OpenSearch Serverless vector stores. See Metadata and filtering and confirm operator support.

If a filter returns no documents, check for an empty result and return a clear message such as “No claims match those criteria” instead of generating an answer.

What we measured

We measured this 30-document synthetic corpus with Retrieve and RetrieveAndGenerate, not AgenticRetrieveStream. Treat the results as a baseline for the corpus and metadata schema, not an agentic retrieval benchmark.

The 40-question suite includes direct lookups, comparisons, aliases, superseded records, reversed payments, and instruction-like document text. Automated foundation-model grading makes the fact-level results directional.

Expected-source retrieval recall measures required documents found. Citation recall measures required documents cited. Both average per question at document level and do not measure chunk precision.

The following table shows the overall results.

Metric Result
Questions answered 40 of 40
Answers carrying citations 40 of 40
Mean citations per answer 3.9
Expected-source retrieval recall 90.5%
Expected-source citation recall 81.2%
Chunks contradicting the requested filter 0

Source: the 40-question evaluation suite and foundation-model grader described here.

On 20 adversarial questions, retrieval recall was 96.7 percent and citation recall was 90.2 percent. The model kept similarly named companies separate, preserved an allegation as an allegation, and ignored instruction-like text inside an attachment.

Figure 4 compares expected-source retrieval and citation recall for the full suite and adversarial subset. These measurements use Retrieve and RetrieveAndGenerate.

Bar chart comparing expected-source retrieval and citation recall for the full suite and the adversarial subset

Figure 4: Expected-source retrieval and citation recall, full suite versus adversarial subset

Narrow claim-specific questions performed best. Broad unfiltered inventory questions produced the three weakest results.

Citation coverage doesn’t guarantee answer completeness, so measure completeness separately when it matters.

These results use synthetic documents and automated grading. Run human review on your own corpus before exposing an assistant to policyholders.

Add security and governance

A claims assistant needs access controls and grounded responses.

Scope filters to the authenticated user

Treat metadata filters as an access boundary. Derive region or customer_id from the authenticated session, combine it with query filters using andAll, and never accept the boundary from user text. The userContext field also supports access-control filtering.

IAM permissions

Grant only the permissions needed for agentic retrieval, knowledge-base access, model streaming, and guardrail actions:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "bedrock:AgenticRetrieveStream",
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "bedrock:Retrieve",
                "bedrock:GetDocumentContent"
            ],
            "Resource": "arn:aws:bedrock:us-west-2:111122223333:knowledge-base/*"
        },
        {
            "Effect": "Allow",
            "Action": "bedrock:InvokeModelWithResponseStream",
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "bedrock:GetGuardrail",
                "bedrock:ApplyGuardrail"
            ],
            "Resource": "*"
        }
    ]
}

AWS CloudTrail records calls to Amazon Bedrock for auditing.

Encryption

Amazon S3 encrypts objects at rest by default. See Configuring default encryption. You can use customer managed AWS KMS keys for the bucket and managed vector storage. API traffic uses Transport Layer Security (TLS).

Contextual grounding with Amazon Bedrock Guardrails

Add an Amazon Bedrock Guardrails contextual grounding check to block responses below configured grounding or relevance thresholds:

  • Grounding: Consistency with retrieved claim documents.
  • Relevance: Alignment with the user’s question.

Create a guardrail with the bedrock client. See CreateGuardrail for all policy types, and choose a high grounding threshold for claims:

bedrock = boto3.client("bedrock", region_name="us-west-2")

guardrail = bedrock.create_guardrail(
    name="claims-assistant-guardrail",
    description="Contextual grounding for the claims assistant",
    contextualGroundingPolicyConfig={
        "filtersConfig": [
            {"type": "GROUNDING", "threshold": 0.85},
            {"type": "RELEVANCE", "threshold": 0.75},
        ]
    },
    blockedInputMessaging="I can't help with that request.",
    blockedOutputsMessaging="I can only answer questions using the claim records.",
)
guardrail_id = guardrail["guardrailId"]
guardrail_version = bedrock.create_guardrail_version(
    guardrailIdentifier=guardrail_id
)["version"]

Higher thresholds block more responses. In claims workflows, declining to answer is safer than generating unsupported content. Pass the guardrail ID and version in policyConfiguration:

response = bedrock_agent_runtime.agentic_retrieve_stream(
    messages=[
        {"role": "user", "content": {"text": "What is the status of claim CLM-100482?"}}
    ],
    retrievers=[
        {"configuration": {"knowledgeBase": {"knowledgeBaseId": kb_id}}}
    ],
    agenticRetrieveConfiguration={"foundationModelType": "MANAGED"},
    policyConfiguration={
        "bedrockGuardrailConfiguration": {
            "guardrailId": guardrail_id,
            "guardrailVersion": guardrail_version,
        }
    },
    generateResponse=True,
)

Agentic retrieval supports the BLOCK action. A failed grounding check blocks the response, and trace events record the intervention.

Keep a person in the loop to review cited evidence and make the final claim decision.

Clean up

Delete the resources when finished to avoid future charges:

  1. Delete the knowledge base. This also removes the managed vector storage:

    bedrock_agent.delete_knowledge_base(knowledgeBaseId=kb_id)
    
  2. Delete the guardrail:

    bedrock.delete_guardrail(guardrailIdentifier=guardrail_id)
    
  3. Empty and delete the S3 bucket.

  4. Delete the knowledge-base IAM role and policy.

Conclusion

You built a claims assistant with Amazon Bedrock Knowledge Bases and synthetic documents in Amazon S3.

AgenticRetrieveStream handles multi-part questions, conversation history, metadata filters, grounding checks, streamed answers, and citations.

The same pattern applies to underwriting and policy-service documents. Learn more in Amazon Bedrock Knowledge Bases and Use agentic retrieval to query a knowledge base.


About the authors

Shreya Pawaskar

Shreya is a Delivery Consultant specializing in AI/ML at AWS Professional Services. She helps enterprise customers design and deploy agentic retrieval and generative AI solutions on Amazon Bedrock. She holds a Master’s degree in Computer Science from the University of California, Irvine. Outside of work, she enjoys hiking Bay Area trails and discovering new restaurants.

Abhishek Sharma

Abhishek is a Senior Solutions Architect at AWS. He collaborates with AWS customers to identify the right use case for their business and guide them through their AI transformation journey. Before joining Amazon, he worked with major enterprises as a Software developer. He is enthusiastic about building generative AI tools and assists customers in developing generative AI-powered applications within cloud environments.