Skip to content

Amazon Bedrock Knowledge Base + OpenSearch: metadata filter works in console but returns 0 results via Python SDK (retrieve)

0

Service: Amazon Bedrock - Knowledge Bases (with Amazon OpenSearch Service as vector store) Region: us-east-1

Problem summary

I’m using a Bedrock Knowledge Base backed by an Amazon OpenSearch managed cluster as the vector store. When I test a metadata filter in the Bedrock console (Test knowledge base → Filters → program: CAH (using 'in' operator works, but '=' doesn't), I get valid retrieval results.

When I call the same knowledge base programmatically via the SDK (bedrock-agent-runtime.retrieve) with the same query and filter, I consistently get 0 retrievalResults.

So: console filter works somehow with 'in' operator (I have tested with other available filters, and it doesn't work), SDK filter returns 0 for the same KB, same query, same metadata key/value.

Environment / configuration Knowledge Base configured with:

  1. Storage: OpenSearch managed cluster (not Serverless)
  2. Vector index name: dnv_kb_chunks
  3. Vector field: sentence_vector (type knn_vector in OpenSearch, dimension 1024)
  4. Text field: text_chunk (type text in OpenSearch)
  5. Metadata field: metadata (type text in OpenSearch)

Documents are pre-chunked .md files in S3 with sidecar metadata in the format:

{

"metadataAttributes": {

"program_family": "ABC",

"program": "CAH",
"edition": "25-1",
"effective_date": "2025-09-08",
"domain_code": "QM",
"chapter_code": "QM.1",
"scope": "int",
"page_start": 17,
"page_end": 17,
"page_range": "p017-017",
"chapter_context": "Domain: QM — QUALITY MANAGEMENT SYSTEM; Chapter: QM.1 — RESPONSIBILITY AND ACCOUNTABILITY",
"chunk_id": "QM.1_INT_C24BFBE0",
"chapter_title": "RESPONSIBILITY AND ACCOUNTABILITY"

} }

I even tried with the below metadata structure too

{

"metadataAttributes": {


    "chapter_context": {
        "value": {
            "type": "STRING",
            "stringValue": "Domain: AS — ANESTHESIA SERVICES; Chapter: AS.1 — ORGANIZATION"
        },
        "includeForEmbedding": true
    },
    "program": {
        "value": {
            "type": "STRING",
            "stringValue": "CAH"
        },
        "includeForEmbedding": false
    },
    "edition": {
        "value": {
            "type": "STRING",
            "stringValue": "25-1"
        },
        "includeForEmbedding": false
    },
    "effective_date": {
        "value": {
            "type": "STRING",
            "stringValue": "2025-09-08"
        },
        "includeForEmbedding": false
    },
    "domain_code": {
        "value": {
            "type": "STRING",
            "stringValue": "AS"
        },
        "includeForEmbedding": false
    },
    "chapter_code": {
        "value": {
            "type": "STRING",
            "stringValue": "AS.1"
        },
        "includeForEmbedding": false
    },
    "scope": {
        "value": {
            "type": "STRING",
            "stringValue": "int"
        },
        "includeForEmbedding": false
    },
    "page_range": {
        "value": {
            "type": "STRING",
            "stringValue": "p120-121"
        },
        "includeForEmbedding": false
    },
    "chapter_title": {
        "value": {
            "type": "STRING",
            "stringValue": "ORGANIZATION"
        },
        "includeForEmbedding": false
    },
    "chunk_id": {
        "value": {
            "type": "STRING",
            "stringValue": "AS.1_INT_D6308646"
        },
        "includeForEmbedding": false
    },
    "source_file": {
        "value": {
            "type": "STRING",
            "stringValue": "s3://medlaunch-kb-chunks/test_delete/NIAHO_CAH_25-1_AS_1_INT_p120-121_k01.md"
        },
        "includeForEmbedding": false
    }
}

}

Sidecar files follow the pattern: <chunk-file>.md.metadata.json in the same S3 prefix as the .md file.

Sync status in the KB console shows as successful, with non-zero documents.

Evidence that metadata is present If I call retrieve without any filter, I get retrieval results and the SDK returns metadata like:

--- result 1 ---

{

'page_range': 'p017-017',

'domain_code': 'QM',

'x-amz-bedrock-kb-data-source-id': 'H5VNTPI6M3',

'program_family': 'XYZ',

'edition': '25-1',

'chapter_title': 'RESPONSIBILITY AND ACCOUNTABILITY',

'program': 'CAH',

'chunk_id': 'QM.1_INT_C24BFBE0',

'x-amz-bedrock-kb-chunk-id': 'c8909b7d-b8c5-417e-9789-edb03a143ff0',

'chapter_code': 'QM.1',

'x-amz-bedrock-kb-source-uri': 's3://.../NIAHO_CAH_25-1_QM_1_INT_p017-017_k02.md',

'chapter_context': 'Domain: QM — QUALITY MANAGEMENT SYSTEM; Chapter: QM.1 — RESPONSIBILITY AND ACCOUNTABILITY',

'page_end': 17.0,

'scope': 'int',

'page_start': 17.0,

'effective_date': '2025-09-08'

}

So from the KB’s perspective, there is clearly a metadata attribute: "program": "CAH"

Console behavior

In the Bedrock Console → Knowledge bases → <kb-id> → Test knowledge base: Query: What does QM.1 say?

Filter: key program, operator =, value CAH (doesn't work, no results)

Filter: key program, operator 'in', value CAH (works)

SDK behavior (problem)

I’m using the Python SDK with bedrock-agent-runtime client. Unfiltered call (works, shows metadata above):

resp = agent_client.retrieve(

knowledgeBaseId="<kb-id>",


retrievalQuery={"text": "What does QM.1 say?"},


retrievalConfiguration={


    "vectorSearchConfiguration": {


        "numberOfResults": 10,


        "overrideSearchType": "HYBRID",


    }


},

)

for r in resp.get("retrievalResults", []):

print(r.get("metadata"))

This returns multiple results with program: "CAH" in metadata, as shown earlier

Filtered call (returns 0 results):

metadata_filter = {

"equals": {


    "key": "program",


    "value": "CAH"


}

}

resp = agent_client.retrieve(

knowledgeBaseId="<kb-id>",


retrievalQuery={"text": "What does QM.1 say?"},


retrievalConfiguration={


    "vectorSearchConfiguration": {


        "numberOfResults": 50,          # deliberately high


        "overrideSearchType": "HYBRID",


        "filter": metadata_filter


    }


},

)

print(len(resp.get("retrievalResults", []))) # always 0

This call does not throw a ValidationException (the filter shape is accepted). retrievalResults is always an empty list for this SDK call.

I also tested with:

metadata_filter = { "in": { "key": "program", "values": ["CAH"] } }

Same behavior: the SDK returns 0 results, while console filter returns records.

What I need help with From my side:

a. Metadata attributes are definitely present (program: "CAH").

b. Console filter program = CAH returns results.

c. SDK retrieve with equals / in on program = CAH returns 0, even with numberOfResults = 50 and the same query text

This feels like either:

a. A discrepancy between how the console and SDK apply filters for Knowledge Bases, or

b. A bug in the bedrock-agent-runtime.retrieve implementation of metadata filtering when using a managed OpenSearch vector store.

Could you:

a. Confirm the expected JSON shape for filter in KnowledgeBaseVectorSearchConfiguration for equals and in, given the metadata structure above?

b. Let me know if there are any known issues or limitations around metadata filtering with Bedrock KB + managed OpenSearch (vs OpenSearch Serverless)?

Thanks in advance for helping reconcile this console vs SDK filter behavior.

2 Answers
0

Hi Deeba, thanks for posting your question! The detail helped me easily reproduce the issue.

I set up a test script to reproduce this with my own Bedrock Knowledge Base and Amazon OpenSearch Service (managed, not serverless) and the difference in behavior between the SDK and the AWS Management Console for both the 'in' and '=' operators and the field types you specified in your configuration.

I've identified two issues causing your filters to return 0 results:

Issue 1: Incorrect Field Type in OpenSearch

Your configuration shows:

Metadata field: metadata (type text in OpenSearch)

Problem: Bedrock's metadata filters require exact matching, which only works on keyword type fields. OpenSearch text fields are tokenized/analyzed for full-text search, breaking exact match filtering. This is why both console and SDK equals operators fail.

Fix: Recreate your OpenSearch index with metadata fields configured as type keyword. When you let Bedrock auto-create the index, it does this correctly. Alternatively, manually create an index with proper mappings where filterable metadata fields are type keyword, not text.

Issue 2: Incorrect Syntax for 'in' Operator

Your code shows:

metadata_filter = {"in": {"key": "program", "values": ["CAH"]}}

Problem: The in operator uses value (singular), not values (plural). The API will reject this with a parameter validation error.

Fix: Change to:

metadata_filter = {"in": {"key": "program", "value": ["CAH"]}}  # "value" not "values"

Validation

I tested both issues with a working Knowledge Base using OpenSearch Managed Cluster:

  • ✅ With keyword fields and correct syntax: Both equals and in operators returned 50 results via SDK
  • ❌ With values (plural): API correctly rejects with "Unknown parameter" error

Documentation:

Fix both issues and your filters will work correctly in both console and SDK. I hope this helps. If it does not, let me know and I am happy to troubleshoot further!

AWS
EXPERT

answered 10 months ago

0

Hello, thank you for reaching out. I'll address the two main questions you've raised.

[Q1. Confirm the expected JSON shape for filter in KnowledgeBaseVectorSearchConfiguration for equals and in, given the metadata structure above]

Let me confirm the correct KnowledgeBaseVectorSearchConfiguration filter JSON format for your metadata structure:

  • equals operator (single value matching) :
retrieval_configuration = {
    "vectorSearchConfiguration": {
        "numberOfResults": 50,
        "overrideSearchType": "HYBRID",
        "filter": {
            "equals": {
                "key": "program",
                "value": "CAH"
            }
        }
    }
}
  • in operator (multiple value matching) :
retrieval_configuration = {
    "vectorSearchConfiguration": {
        "numberOfResults": 50,
        "overrideSearchType": "HYBRID",
        "filter": {
            "in": {
                "key": "program",
                "values": ["CAH"]
            }
        }
    }
}

The JSON structure you used is completely correct in terms of format. However, to definitively verify the proper format and troubleshoot any differences, I recommend comparing the actual API calls using CloudTrail. This will reveal any differences in how the console and SDK are constructing the API requests.

The issue is very likely not with the filter structure itself, but rather with the field type mapping in your OpenSearch index.

For more details, please refer to documentation[1] and [2].

[Q2. Are there known differences in filter behavior between console and SDK, or any limitations?]

A2. Yes, there are several known differences and limitations.

a. Field Type Dependency (Most Critical in your case)

  • For metadata filtering to work, the fields you want to filter on must be mapped as keyword type
  • Fields mapped as text type are tokenized during storage, making exact matching (equals, in) impossible

The Bedrock SDK internally uses OpenSearch term queries, which only work correctly with keyword types. This is the root cause of your issue: your metadata field is currently text type. For more details, please refer to documentation[3] and [4].

b. Manual Index Management Required

  • Bedrock does not automatically create optimal mappings for managed OpenSearch
  • You must explicitly specify metadata field types when creating the index
  • If an index is created with incorrect mappings, re-indexing is required

c. Console vs SDK Behavior Discrepancy (the issue you're experiencing)

  • The Bedrock console may use internal query transformations or fallback logic
  • The SDK calls OpenSearch APIs more directly, so field type issues surface immediately

If you have additional questions or need help with specific configurations, please open a support case and we'll be happy to assist.

Thank you.

Reference [1] Bedrock Agent Runtime - https://docs.aws.amazon.com/bedrock/latest/userguide/knowledge-base.html [2] Configure and customize queries and response generation - Amazon Bedro... - https://docs.aws.amazon.com/bedrock/latest/userguide/kb-test-config.html [3] Mappings - OpenSearch DocumentationMappings | OpenSearch Documentation - https://docs.opensearch.org/latest/mappings/ [4] Keyword - OpenSearch DocumentationKeyword | OpenSearch DocumentationLi... - https://docs.opensearch.org/latest/mappings/supported-field-types/keyword/

answered 10 months ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.