1. Prerequisites
- Model access enabled in the Bedrock console for an embedding model (for example Amazon Titan Text Embeddings V2 or Cohere Embed) and a generation model (for example Claude or Amazon Nova).
- An S3 bucket with the source documents (PDF, DOCX, HTML, TXT, MD and others), in the same region.
- Optional metadata files next to each document:
report.pdf.metadata.jsonwith{"metadataAttributes": {"department": "finance", "year": 2026}}.
2. Choose a vector store
| Store | Notes |
|---|---|
| OpenSearch Serverless (quick create) | The easiest; minimum OCU charges apply even when idle |
| Aurora PostgreSQL with pgvector | Good if you already run Aurora; you manage the schema |
| Amazon S3 Vectors | Low-cost storage for large, less latency-sensitive collections |
| Others (Pinecone, Redis Enterprise, MongoDB Atlas, Neptune Analytics for GraphRAG) | Bring your own |
3. Create the knowledge base (console)
- Bedrock → Knowledge Bases → Create → Knowledge base with vector store.
- IAM: let Bedrock create a service role (it needs
s3:GetObjecton the bucket,bedrock:InvokeModelfor the embedding model, and access to the vector store). - Data source: S3 URI. Choose a chunking strategy:
- Default (about 300 tokens), fixed size (set tokens and overlap), hierarchical (parent/child), semantic, or none (pre-chunked files).
- Optional parsing with a foundation model for complex PDFs (tables and figures) at extra cost.
- Embedding model and vector store (quick create, or an existing one).
- Create, then Sync the data source.
4. Sync with the CLI
aws bedrock-agent start-ingestion-job --knowledge-base-id KB12345 --data-source-id DS12345
aws bedrock-agent list-ingestion-jobs --knowledge-base-id KB12345 --data-source-id DS12345 \
--query 'ingestionJobSummaries[0].[status,statistics]'
Syncs are incremental: new, changed and deleted files are processed. Schedule a sync (EventBridge Scheduler → Lambda, or a Step Functions task) after document updates.
5. Query
import boto3
rt = boto3.client("bedrock-agent-runtime", region_name="ap-south-1")
resp = rt.retrieve_and_generate(
input={"text": "What is the travel reimbursement limit for 2026?"},
retrieveAndGenerateConfiguration={
"type": "KNOWLEDGE_BASE",
"knowledgeBaseConfiguration": {
"knowledgeBaseId": "KB12345",
"modelArn": "arn:aws:bedrock:ap-south-1::foundation-model/<generation-model-id>",
"retrievalConfiguration": {"vectorSearchConfiguration": {
"numberOfResults": 6,
"filter": {"equals": {"key": "department", "value": "finance"}}}}}})
print(resp["output"]["text"])
for c in resp["citations"]:
for ref in c["retrievedReferences"]:
print(ref["location"]["s3Location"]["uri"])
Use retrieve alone if you want to build the prompt yourself. Many models need an inference profile ARN instead of a foundation-model ARN, so check the model's page.
6. Operations
- Access control: Knowledge Bases don't enforce per-user document permissions by themselves. Use metadata filters (department, ACL group) applied from the signed-in user's identity, or separate knowledge bases.
- Guardrails: attach a Bedrock Guardrail to
retrieve_and_generatefor content and PII filtering. - Monitoring: CloudWatch metrics for ingestion jobs and invocation logging for model calls. Track failed documents in the ingestion statistics.
- Cost: embedding tokens at ingestion, vector store charges, and generation tokens per query.
7. Standalone vs HA
A knowledge base is a regional managed service, so there's nothing to cluster yourself. For region-level DR, keep the S3 data replicated and the knowledge base defined in IaC (CloudFormation or Terraform) so you can recreate and sync it in another region (see the vector index DR post).
Tip
Start with hierarchical chunking for long policy-style documents. Search runs on small child chunks, but the model gets the larger parent chunk, which usually improves answers without extra tuning.