llm-catalog-archive

Change

14d198e

14d198e647c53364e04e253601fe3bf9abf1fed6 · commit on GitHub

aws-blog-feed: changed (578645 bytes, HTTP 200)

raw/aws-blog-feed/response.xml modified

Lines added
+3,504
Lines removed
-3,631
Stored bytes at this commit
578,645
Timestamp
observed
Raw artifact at this commit
raw/aws-blog-feed/response.xml
Recorded headers
observed_at2026-11-03T06:47:08.231Z
origin_datenull
status200
final URLhttps://aws.amazon.com/blogs/machine-learning/feed/
etagnull
last-modifiedTue, 03 Nov 2026 00:36:49 GMT
dateTue, 03 Nov 2026 06:47:08 GMT
agenull
cache-controlnull
cf-cache-statusnull
content-encodingnull
content-lengthnull
@@@ -5,7 +5,7 @@
<atom:link href="https://aws.amazon.com/blogs/machine-learning/feed/" rel="self" type="application/rss+xml"/>
<link>https://aws.amazon.com/blogs/machine-learning/</link>
<description>Official Machine Learning Blog of Amazon Web Services</description>
- <lastBuildDate>Fri, 30 Oct 2026 22:42:24 +0000</lastBuildDate>
+ <lastBuildDate>Mon, 02 Nov 2026 20:28:52 +0000</lastBuildDate>
<language>en-US</language>
<sy:updatePeriod>
hourly </sy:updatePeriod>
@@@ -13,223 +13,313 @@
1 </sy:updateFrequency>
<item>
- <title>Managing Amazon Bedrock costs end to end: A playbook for FinOps and platform teams</title>
- <link>https://aws.amazon.com/blogs/machine-learning/managing-amazon-bedrock-costs-end-to-end-a-playbook-for-finops-and-platform-teams/</link>
+ <title>Prepare web content for Amazon Bedrock Knowledge Bases with Crawl4AI</title>
+ <link>https://aws.amazon.com/blogs/machine-learning/prepare-web-content-for-amazon-bedrock-knowledge-bases-with-crawl4ai/</link>
- <dc:creator><![CDATA[Aswath Ram A Srinivasan]]></dc:creator>
- <pubDate>Fri, 30 Oct 2026 22:42:24 +0000</pubDate>
+ <dc:creator><![CDATA[Daxeshkumar Patel]]></dc:creator>
+ <pubDate>Mon, 02 Nov 2026 17:11:21 +0000</pubDate>
<category><![CDATA[Advanced (300)]]></category>
- <category><![CDATA[Amazon Bedrock]]></category>
+ <category><![CDATA[Amazon Bedrock Knowledge Bases]]></category>
<category><![CDATA[Technical How-to]]></category>
- <guid isPermaLink="false">5542e879e541b56f1c06a9f2c71c7c3f37f6d5e3</guid>
+ <guid isPermaLink="false">43ca16f9eb64c74c6edd06ac90851b607a986aa7</guid>
- <description>This post presents a five-stage operating model for managing Amazon Bedrock cost: attribute every dollar to an owner, make every request observable, enforce budgets, optimize platform defaults, and operate a review cadence. Written for FinOps and platform engineering teams.</descri…
- <content:encoded>&lt;p&gt;Cost management for generative AI is a shared responsibility between the teams that build applications and the teams accountable for cloud spend. Many teams start by comparing per-model token rates and asking application teams to shorten prompts. Those steps help,…
-&lt;p&gt;Agentic workloads make those questions more pressing. A conversational assistant typically issues one model invocation per user turn. An agentic workflow, such as an AI coding assistant that plans a change, reads files, calls tools, and iterates, issues many invocations per task and carries…
-&lt;p&gt;The fix isn’t a cheaper model or a smaller prompt. It’s an operating model: a repeatable loop that attributes every dollar to an owner, makes every request observable, alerts on and enforces budgets before overspend compounds, optimizes the platform defaults that drive most waste, and revie…
-&lt;p&gt;In this post, you learn how to manage &lt;a href="https://aws.amazon.com/bedrock/" target="_blank" rel="noopener"&gt;Amazon Bedrock&lt;/a&gt; cost in five steps. You attribute every dollar to an owner, make every request observable, control spend with budgets and enforcement, optimize the p…
-&lt;h2 id="the-operating-model-in-one-view"&gt;The operating model in one view&lt;/h2&gt;
-&lt;p&gt;Five stages, run as a loop. Attribute: every Amazon Bedrock dollar lands on an identity, team, and application in the billing pipeline. Observe: every request is logged with enough metadata to explain what generated the spend. Enforce: budgets have teeth, with alerts at minimum and hard blo…
+ <description>This post shows how to use Crawl4AI, an open source web crawler, as a content preparation layer for Amazon Bedrock Knowledge Bases, handling JavaScript rendering, selective extraction, and custom metadata enrichment before web content reaches an Amazon S3 data source.</description>
+ <content:encoded>&lt;p&gt;When you build Retrieval Augmented Generation (RAG) applications, answer quality depends on the data that you ingest. &lt;a href="https://aws.amazon.com/bedrock/knowledge-bases/" target="_blank" rel="noopener"&gt;Amazon Bedrock Knowledge Bases&lt;/a&gt; is the ful…
+&lt;p&gt;For web content, start with the &lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/kb-managed-ds-webcrawler.html" target="_blank" rel="noopener"&gt;Amazon Bedrock Web Crawler&lt;/a&gt; data source connector for managed knowledge bases. You give it the seed URLs or sitemaps tha…
+&lt;p&gt;Some sources need more control over what reaches the knowledge base. You might want to index only the main content region of each page, remove navigation and other boilerplate, or attach your own metadata attributes to every document. For that class of source material, you can extend the re…
+&lt;p&gt;In this post, we show you how to choose the appropriate web ingestion path and implement custom preparation for content that needs additional processing. You then start ingestion into a managed knowledge base and validate retrieval quality. The companion &lt;a href="https://github.com/aws-s…
+&lt;p&gt;This is batch ingestion of known web properties, not real-time web access at inference time such as &lt;a href="https://docs.aws.amazon.com/nova/latest/nova2-userguide/web-grounding.html" target="_blank" rel="noopener"&gt;Web Grounding&lt;/a&gt; with Amazon Nova.&lt;/p&gt;
+&lt;h2 id="solution-overview"&gt;Solution overview&lt;/h2&gt;
+&lt;p&gt;Start with the &lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/kb-managed-ds-webcrawler.html" target="_blank" rel="noopener"&gt;Amazon Bedrock Web Crawler&lt;/a&gt; when it can reach and index the pages you need. It respects &lt;code&gt;robots.txt&lt;/code&gt;, and after th…
+&lt;p&gt;Use the Crawl4AI preparation path when public source material needs one or more of the following before ingestion:&lt;/p&gt;
+&lt;ul&gt;
+ &lt;li&gt;&lt;strong&gt;Structured Markdown preparation&lt;/strong&gt;: Use &lt;code&gt;DefaultMarkdownGenerator&lt;/code&gt; with a pruning content filter to reduce navigation and other boilerplate while preserving headings, lists, and tables. Because pruning is heuristic, review representative ou…
+ &lt;li&gt;&lt;strong&gt;Bounded, targeted extraction&lt;/strong&gt;: Extract only the page region that an optional CSS selector matches. Constrain breadth-first traversal by seed origin, page/path/host scope, depth and page caps, and URL patterns.&lt;/li&gt;
+ &lt;li&gt;&lt;strong&gt;Custom metadata&lt;/strong&gt;: Attach source URLs, crawl timestamps, content type, and your own attributes to each document, so that you can filter retrieval results on them.&lt;/li&gt;
+&lt;/ul&gt;
+&lt;p&gt;Because managed and customer-managed knowledge bases both support Amazon S3 data sources, the Crawl4AI path works with either type. This post uses a managed knowledge base and notes where a customer-managed knowledge base differs.&lt;/p&gt;
+&lt;p&gt;The rest of this post follows the companion sample. Treat its architecture and defaults as a starting point, not as requirements of Amazon Bedrock Knowledge Bases.&lt;/p&gt;
+&lt;p&gt;By default, the sample runs the AWS Fargate task in a public subnet, where it reaches your configured websites through an internet gateway. Crawl4AI’s role ends once it has prepared the source documents and metadata sidecars. From ingestion onward, Amazon Bedrock Knowledge Bases handles par…
&lt;div style="width: 810px" class="wp-caption alignnone"&gt;
- &lt;a href="https://d2908q01vomqb2.cloudfront.net/f1f836cb4ea6efb2a0b1b99f41ad8b103eff4b59/2026/10/29/ML-21654-1-1.png" target="_blank" rel="noopener"&gt;&lt;img src="https://d2908q01vomqb2.cloudfront.net/f1f836cb4ea6efb2a0b1b99f41ad8b103eff4b59/2026/10/29/ML-21654-1-1.png" alt="Five-stage Amazon B…
- &lt;p class="wp-caption-text"&gt;Figure 1: The five-stage operating model, run as a continuous loop&lt;/p&gt;
+ &lt;a href="https://d2908q01vomqb2.cloudfront.net/f1f836cb4ea6efb2a0b1b99f41ad8b103eff4b59/2026/10/27/ML-21438-1.png" target="_blank" rel="noopener"&gt;&lt;img src="https://d2908q01vomqb2.cloudfront.net/f1f836cb4ea6efb2a0b1b99f41ad8b103eff4b59/2026/10/27/ML-21438-1.png" alt="Architecture diagram sh…
+ &lt;p class="wp-caption-text"&gt;Figure 1: The Crawl4AI-to-Amazon S3 ingestion path for Amazon Bedrock Knowledge Bases&lt;/p&gt;
&lt;/div&gt;
-&lt;h2 id="stage-1-attribute-every-dollar"&gt;Stage 1: Attribute every dollar&lt;/h2&gt;
-&lt;p&gt;You can’t manage what you can’t attribute, and everything downstream (chargeback, budgets, enforcement, anomaly detection) depends on this stage. The foundation is the granular cost attribution of Amazon Bedrock (see &lt;a href="https://aws.amazon.com/blogs/machine-learning/introducing-gran…
-&lt;p&gt;Setup is four steps:&lt;/p&gt;
+&lt;p&gt;The numbered steps in the diagram map to the following workflow:&lt;/p&gt;
&lt;ol type="1"&gt;
- &lt;li&gt;Turn on IAM principal data in your CUR 2.0 data export.&lt;/li&gt;
- &lt;li&gt;Tag your IAM principals with business dimensions such as team, application, and cost center. For federated access, configure your identity provider to pass session names and tags through OIDC or SAML claims.&lt;/li&gt;
- &lt;li&gt;Activate those tags as cost allocation tags in AWS Billing (console or the &lt;code&gt;UpdateCostAllocationTagsStatus&lt;/code&gt; API).&lt;/li&gt;
- &lt;li&gt;Analyze the tags: they surface in CUR 2.0 with an &lt;code&gt;iamPrincipal/&lt;/code&gt; prefix (for example, &lt;code&gt;iamPrincipal/team&lt;/code&gt;) and appear in &lt;a href="https://aws.amazon.com/aws-cost-management/aws-cost-explorer/" target="_blank" rel="noopener"&gt;AWS Cost Exp…
+ &lt;li&gt;Amazon EventBridge starts the Amazon Elastic Container Service (Amazon ECS) task on AWS Fargate on the configured schedule.&lt;/li&gt;
+ &lt;li&gt;The task crawls the public websites you configured and prepares Markdown with a metadata sidecar for each page.&lt;/li&gt;
+ &lt;li&gt;The task uploads the prepared files to the Amazon S3 bucket that backs the knowledge base data source.&lt;/li&gt;
+ &lt;li&gt;The task starts an Amazon Bedrock Knowledge Bases ingestion job.&lt;/li&gt;
+ &lt;li&gt;Amazon Bedrock Knowledge Bases reads the new and changed objects, parses them, and applies the chunking strategy you selected.&lt;/li&gt;
+ &lt;li&gt;It creates embeddings and indexes them in the knowledge base’s vector store, which Amazon Bedrock manages for a managed knowledge base.&lt;/li&gt;
+ &lt;li&gt;Your generative AI application queries the knowledge base for relevant chunks or for a generated response with citations.&lt;/li&gt;
&lt;/ol&gt;
-&lt;p&gt;This is invoice-grade, per-identity attribution with no custom infrastructure.&lt;/p&gt;
-&lt;h3 id="the-shared-role-problem"&gt;The shared-role problem&lt;/h3&gt;
-&lt;p&gt;The pattern that deserves the most attention is the shared-role problem, because it is where most platforms silently lose attribution. A large language model (LLM) gateway that calls Amazon Bedrock through a single IAM role attributes every dollar to that one role, eliminating per-user visi…
-&lt;p&gt;This needs two roles: a gateway execution role holding &lt;code&gt;sts:AssumeRole&lt;/code&gt; and &lt;code&gt;sts:TagSession&lt;/code&gt; permissions, and the Amazon Bedrock invocation role it assumes. The result is &lt;code&gt;line_item_iam_principal&lt;/code&gt; entries like &lt;code&gt;…
+&lt;p&gt;The task reads its non-secret pipeline configuration from AWS Systems Manager Parameter Store at startup.&lt;/p&gt;
+&lt;p&gt;The workflow processes public pages only and doesn’t implement authenticated sessions. For sites that require sign-in, evaluate the &lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/kb-managed-ds-webcrawler.html" target="_blank" rel="noopener"&gt;Amazon Bedrock Web Crawler au…
+&lt;h2 id="how-the-workflow-works"&gt;How the workflow works&lt;/h2&gt;
+&lt;p&gt;The AWS Cloud Development Kit (AWS CDK) app packages the implementation in a container image during deployment. When the schedule fires, the container runs &lt;code&gt;scripts/container_entrypoint.py&lt;/code&gt; and executes crawl, upload, and ingestion in sequence. The following three ste…
+&lt;h3 id="step-1-crawl-and-extract-content"&gt;Step 1: Crawl and extract content&lt;/h3&gt;
+&lt;p&gt;The crawl step performs bounded crawling and writes a Markdown file with a metadata sidecar for each successfully prepared page. The following excerpt is simplified. The module &lt;code&gt;src/crawl4ai_bedrock_kb/crawl.py&lt;/code&gt; contains the complete seed pacing, URL filtering and sco…
&lt;div class="hide-language"&gt;
- &lt;pre&gt;&lt;code class="language-python"&gt;import boto3
+ &lt;pre&gt;&lt;code class="language-python"&gt;async def crawl_and_prepare(config: PipelineConfig, output_dir: str) -&amp;gt; list[str]:
+ written, seen = [], set()
+ pages_crawled = 0
+ browser_config = BrowserConfig(headless=True, java_script_enabled=True)
-sts = boto3.client("sts")
+ async with AsyncWebCrawler(config=browser_config) as crawler:
+ for seed in config.seed_urls:
+ remaining = config.crawl.max_pages - pages_crawled
+ if remaining &amp;lt;= 0:
+ break
-# One call per user; cache the returned credentials up to 1 hour
-response = sts.assume_role(
- RoleArn="arn:aws:iam::123456789012:role/BedrockRuntimeRole",
- RoleSessionName="gw-alex", # the user, not the gateway
- Tags=[
- {"Key": "team", "Value": "sales-ai"},
- {"Key": "application", "Value": "renewal-agent"},
- {"Key": "costCenter", "Value": "CC-2041"}
- ]
-)&lt;/code&gt;&lt;/pre&gt;
-&lt;/div&gt;
-&lt;h3 id="a-note-on-application-inference-profiles-and-projects"&gt;A note on application inference profiles and Projects&lt;/h3&gt;
-&lt;p&gt;Amazon Bedrock offers two more attribution mechanisms, each suited to a different pattern. &lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-create.html" target="_blank" rel="noopener"&gt;Application inference profiles&lt;/a&gt; are pre-created, per-applica…
-&lt;p&gt;For &lt;code&gt;bedrock-runtime&lt;/code&gt; workloads, we recommend IAM principal attribution through session tags as the primary mechanism. It scales with your identity system, requires no pre-created resources, and covers every model and API operation. Application inference profiles work…
-&lt;h2 id="stage-2-make-every-request-observable"&gt;Stage 2: Make every request observable&lt;/h2&gt;
-&lt;p&gt;CUR tells you who spent. Invocation logs tell you what happened. Amazon Bedrock supports &lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/model-invocation-logging.html" target="_blank" rel="noopener"&gt;model invocation logging&lt;/a&gt; of request data, response data, and m…
-&lt;p&gt;Logging also closes the latency gap: CUR attribution lags roughly 24 hours, but CloudWatch plus OpenTelemetry can power near-real-time dashboards showing per-developer spend within minutes (&lt;a href="https://aws.amazon.com/blogs/mt/analyzing-claude-code-usage-with-cloudwatch-and-opentelem…
-&lt;h3 id="request-metadata-for-workload-level-attribution"&gt;Request metadata for workload-level attribution&lt;/h3&gt;
-&lt;p&gt;Raw logs answer identity-level questions. To answer workload-level questions (which feature, workflow, or tenant generated the tokens), stamp &lt;a href="https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_Converse.html#bedrock-runtime_Converse-request-requestMetadata" targe…
-&lt;p&gt;The following example uses Anthropic Claude Sonnet 5.5 on Amazon Bedrock through the US cross-Region inference profile. For the full list of models, see &lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/models-supported.html" target="_blank" rel="noopener"&gt;Supported founda…
+ strategy = BFSDeepCrawlStrategy(
+ max_depth=config.crawl.max_depth,
+ max_pages=remaining,
+ filter_chain=FilterChain([
+ SeedScopeFilter(seed, config.crawl.scope),
+ # Optional include/exclude URLPatternFilter objects are added here.
+ ]),
+ )
+ run_config = CrawlerRunConfig(
+ deep_crawl_strategy=strategy,
+ markdown_generator=DefaultMarkdownGenerator(
+ content_filter=PruningContentFilter()
+ ),
+ css_selector=config.crawl.css_selector, # Optional page region.
+ check_robots_txt=config.crawl.check_robots_txt,
+ mean_delay=config.crawl.request_delay_seconds,
+ max_range=0,
+ semaphore_count=1,
+ )
+
+ results = await crawler.arun(url=seed, config=run_config)
+ for result in results:
+ if pages_crawled &amp;gt;= config.crawl.max_pages:
+ break
+ pages_crawled += 1
+ requested_url = result.url
+ source_url = getattr(result, "redirected_url", None) or requested_url
+ if not SeedScopeFilter(seed, config.crawl.scope).apply(source_url):
+ continue # Recheck the effective destination after redirects.
+ canonical = _canonical_url(source_url)
+ if canonical in seen:
+ continue
+ seen.add(canonical)
+ if not result.success or not result.markdown:
+ continue
+
+ md_result = result.markdown
+ markdown = (
+ getattr(md_result, "fit_markdown", None)
+ or getattr(md_result, "raw_markdown", None)
+ or (md_result if isinstance(md_result, str) else "")
+ )
+ if not markdown:
+ continue
+
+ # The complete implementation adds title, crawl timestamps, content
+ # type, and configured custom attributes to this metadata.
+ written.extend(
+ _write_document(
+ output_dir,
+ _base_name(source_url),
+ markdown,
+ {"source_url": source_url},
+ )
+ )
+ return written&lt;/code&gt;&lt;/pre&gt;
+&lt;/div&gt;
+&lt;p&gt;Amazon Bedrock Knowledge Bases supports &lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/knowledge-base-ds.html" target="_blank" rel="noopener"&gt;several document formats&lt;/a&gt; for Amazon S3 data sources, including plain text, HTML, Markdown, PDF, and DOCX. The workflow…
+&lt;h3 id="step-2-upload-to-amazon-s3"&gt;Step 2: Upload to Amazon S3&lt;/h3&gt;
+&lt;p&gt;The upload step sends each prepared Markdown document and its matching metadata sidecar to the configured S3 bucket, under the workflow’s &lt;code&gt;s3Prefix&lt;/code&gt;. For &lt;code&gt;page.md&lt;/code&gt;, the sidecar must be named &lt;code&gt;page.md.metadata.json&lt;/code&gt;, the co…
+&lt;p&gt;Each attribute in the sidecar uses the typed format that both managed and customer-managed knowledge bases accept for Amazon S3 data sources. The following abbreviated sidecar, formatted for readability, shows three of the attributes that the workflow writes:&lt;/p&gt;
&lt;div class="hide-language"&gt;
- &lt;pre&gt;&lt;code class="language-python"&gt;response = client.converse(
- modelId="us.anthropic.claude-sonnet-5-5",
- messages=[...],
- requestMetadata={
- "application": "renewal-copilot",
- "workflow": "renewal-risk-summary",
- "tenant": "enterprise-sales",
- "agent": "renewal-agent"
+ &lt;pre&gt;&lt;code class="language-json"&gt;{
+ "metadataAttributes": {
+ "source_url": {
+ "value": {"type": "STRING", "stringValue": "https://www.example.com/services/permits"}
+ },
+ "crawled_at_epoch": {
+ "value": {"type": "NUMBER", "numberValue": 1790640000}
+ },
+ "content_category": {
+ "value": {"type": "STRING", "stringValue": "web"}
}
-)&lt;/code&gt;&lt;/pre&gt;
+ }
+}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
-&lt;p&gt;Amazon Bedrock doesn’t enforce request metadata, and teams drift into inconsistent schemas quickly when every application does its own thing. The platform team should inject mandatory metadata centrally in a shared SDK wrapper or gateway, normalize the key set, and treat metadata coverage a…
-&lt;h3 id="diagnostic-queries"&gt;Diagnostic queries&lt;/h3&gt;
-&lt;p&gt;With logs and metadata in place, CloudWatch Logs Insights answers the standing questions. &lt;em&gt;Who consumes the most tokens&lt;/em&gt;:&lt;/p&gt;
+&lt;p&gt;The pipeline uploads only the paths produced by the current crawl, so stale local files are not sent.&lt;/p&gt;
+&lt;h3 id="step-3-let-amazon-bedrock-knowledge-bases-chunk-embed-and-index"&gt;Step 3: Let Amazon Bedrock Knowledge Bases chunk, embed, and index&lt;/h3&gt;
+&lt;p&gt;After content is in S3, an ingestion job hands each document to the data source’s ingestion pipeline. By default, a managed knowledge base parses each file with its managed parser, which automatically selects a parsing approach for your content. You select the chunking strategy when you con…
+&lt;ul&gt;
+ &lt;li&gt;&lt;strong&gt;Default chunking&lt;/strong&gt; uses fixed-size chunks of 300 tokens with 20 percent overlap.&lt;/li&gt;
+ &lt;li&gt;&lt;strong&gt;Fixed-size chunking&lt;/strong&gt; splits content by a maximum token count and an overlap percentage that you set.&lt;/li&gt;
+ &lt;li&gt;&lt;strong&gt;No chunking&lt;/strong&gt; treats each file as a single chunk, for content that you have already split.&lt;/li&gt;
+&lt;/ul&gt;
+&lt;p&gt;Chunk boundaries and retrieval results depend on the content and the selected strategy, so compare the options with representative pages and evaluation questions. To change strategies later, create a new data source. For more information, see &lt;a href="https://docs.aws.amazon.com/bedrock/…
+&lt;p&gt;The workflow then starts an ingestion job so the knowledge base processes the new documents. The following simplified excerpt from &lt;code&gt;src/crawl4ai_bedrock_kb/ingest.py&lt;/code&gt; shows the call:&lt;/p&gt;
&lt;div class="hide-language"&gt;
- &lt;pre&gt;&lt;code class="language-plaintext"&gt;fields @timestamp, identity.arn as caller, modelId,
-input.inputTokenCount as inTokens,
-output.outputTokenCount as outTokens
-| stats sum(inTokens + outTokens) as totalTokens,
-count(*) as calls
-by caller, modelId
-| sort totalTokens desc
-| limit 25&lt;/code&gt;&lt;/pre&gt;
+ &lt;pre&gt;&lt;code class="language-python"&gt;def start_ingestion_job(config: PipelineConfig) -&amp;gt; str:
+ # Start an Amazon Bedrock knowledge base ingestion job and return its ID.
+ client = boto3.client("bedrock-agent", region_name=config.region)
+ response = client.start_ingestion_job(
+ knowledgeBaseId=config.knowledge_base_id,
+ dataSourceId=config.data_source_id,
+ )
+ return response["ingestionJob"]["ingestionJobId"]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
-&lt;p&gt;The same query grouped by &lt;code&gt;requestMetadata.application&lt;/code&gt; and &lt;code&gt;requestMetadata.workflow&lt;/code&gt; instead of &lt;code&gt;caller&lt;/code&gt; produces the workload-level leaderboard: the view product and engineering teams will ask FinOps for the moment char…
-&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Field paths shown in the preceding query are illustrative. Verify against your invocation log schema, which may vary by model, API operation, and logging configuration.&lt;/p&gt;
-&lt;h2 id="stage-3-enforce-budgets"&gt;Stage 3: Enforce budgets&lt;/h2&gt;
-&lt;p&gt;With attribution and observability in place, enforcement becomes an architecture choice rather than a wish. There are three viable tiers. The right one depends on your spend velocity, your risk tolerance for overspend, and how your tools connect to Amazon Bedrock.&lt;/p&gt;
-&lt;h3 id="tier-1-monitor-and-alert-no-blocking"&gt;Tier 1: Monitor and alert (no blocking)&lt;/h3&gt;
-&lt;p&gt;Amazon Bedrock writes principal identity into the billing pipeline automatically. You put AWS Budgets on top for threshold alerts, with the OpenTelemetry dashboards from Stage 2 closing the 24-hour CUR gap for day-to-day visibility. Nothing to deploy, native AWS billing, and no added latenc…
-&lt;h3 id="tier-2-iam-tag-enforcement-deny-on-breach"&gt;Tier 2: IAM tag enforcement (deny on breach)&lt;/h3&gt;
-&lt;p&gt;An aggregator AWS Lambda function tallies per-user token and dollar counters in Amazon DynamoDB from invocation log data. When a user breaches their threshold, the function adds their identity to a shared IAM deny policy (denying &lt;code&gt;bedrock:*&lt;/code&gt;) until a monthly reset or …
-&lt;h3 id="tier-3-gateway-enforcement-synchronous-block"&gt;Tier 3: Gateway enforcement (synchronous block)&lt;/h3&gt;
-&lt;p&gt;A gateway sits in the inference data path and enforces budgets synchronously, returning HTTP 429 the moment a user or team exceeds their limit. You get sub-second blocking, per-user model allowlists, token rate limits, and centrally enforced routing rules. The trade-off: a component in the …
-&lt;p&gt;For Claude Code and Claude Desktop fleets, the &lt;a href="https://aws.amazon.com/blogs/machine-learning/introducing-claude-apps-gateway-for-aws/" target="_blank" rel="noopener"&gt;Claude apps gateway for AWS&lt;/a&gt; is the official recommendation. It ships inside the CLI binary and runs …
-&lt;h3 id="choosing-a-tier"&gt;Choosing a tier&lt;/h3&gt;
-&lt;p&gt;Two factors dominate.&lt;/p&gt;
-&lt;p&gt;&lt;strong&gt;Connectivity:&lt;/strong&gt; If developers call Amazon Bedrock directly with no proxy, only Tiers 1 and 2 are viable.&lt;/p&gt;
-&lt;p&gt;&lt;strong&gt;Spend velocity:&lt;/strong&gt; If spend is already in the millions per month, build enforcement now. If alerts can hold the line for another quarter, invest in Stages 1 and 2 first and add enforcement when the data demands it.&lt;/p&gt;
-&lt;p&gt;Most organizations should phase it: observe at Tier 1, then step up. Treat all three as bridges, not destinations: the &lt;a href="https://docs.aws.amazon.com/wellarchitected/latest/agentic-ai-lens/agentcost07.html" target="_blank" rel="noopener"&gt;Well-Architected Agentic AI Lens&lt;/a&gt…
-&lt;h2 id="stage-4-optimize-the-defaults"&gt;Stage 4: Optimize the defaults&lt;/h2&gt;
-&lt;p&gt;Most Amazon Bedrock waste is not individual carelessness. It is platform defaults nobody set. The two highest-impact levers are both platform-controlled.&lt;/p&gt;
-&lt;h3 id="model-routing"&gt;Model routing&lt;/h3&gt;
-&lt;p&gt;Not every task needs a frontier model. Routine completions (boilerplate, linting suggestions, small refactors) can run on smaller, cheaper models with quality reserved for complex reasoning, through &lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/intelligent-prompt-routing.…
-&lt;h3 id="prompt-caching"&gt;Prompt caching&lt;/h3&gt;
-&lt;p&gt;Prompt caching rewards stable repeated prefixes. As of October 2026, the published &lt;a href="https://aws.amazon.com/bedrock/pricing/" target="_blank" rel="noopener"&gt;Amazon Bedrock pricing&lt;/a&gt; for Anthropic Claude models in US East (N. Virginia) bills a cache write at 1.25x the ba…
-&lt;p&gt;Candidates surface directly from the invocation logs:&lt;/p&gt;
+&lt;p&gt;The same &lt;code&gt;StartIngestionJob&lt;/code&gt; and &lt;code&gt;GetIngestionJob&lt;/code&gt; calls work for both knowledge base types, and you can also monitor progress on the console.&lt;/p&gt;
+&lt;h2 id="deploy-the-solution"&gt;Deploy the solution&lt;/h2&gt;
+&lt;p&gt;In this section, you deploy the workflow into your AWS account with AWS CDK. Only the knowledge base prerequisites differ between the two knowledge base types. When you’re finished, follow the steps in the Clean up section to remove the resources.&lt;/p&gt;
+&lt;h3 id="prerequisites"&gt;Prerequisites&lt;/h3&gt;
+&lt;p&gt;Before you start, make sure that you have:&lt;/p&gt;
+&lt;ul&gt;
+ &lt;li&gt;An AWS account.&lt;/li&gt;
+ &lt;li&gt;One of the following knowledge bases:
+ &lt;ul&gt;
+ &lt;li&gt;&lt;strong&gt;A managed knowledge base&lt;/strong&gt;, which this post uses, in an AWS Region where &lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/kb-managed-regions.html" target="_blank" rel="noopener"&gt;managed knowledge bases are available&lt;/a&gt;. For instructio…
+ &lt;li&gt;&lt;strong&gt;An existing customer-managed knowledge base.&lt;/strong&gt; To add an Amazon S3 data source, see &lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/s3-data-source-connector.html" target="_blank" rel="noopener"&gt;Connect to Amazon S3 for your knowledge base&l…
+ &lt;/ul&gt; &lt;/li&gt;
+ &lt;li&gt;An Amazon S3 data source in that knowledge base whose status is &lt;code&gt;AVAILABLE&lt;/code&gt;. It can be a new data source or one you already use. It must use the S3 bucket that you configure for this workflow. If the data source filters content by prefix or file pattern, the filters…
+ &lt;li&gt;The knowledge base, the S3 bucket, and the stack you deploy all in one Region.&lt;/li&gt;
+ &lt;li&gt;Authorization to crawl the public websites you configure.&lt;/li&gt;
+ &lt;li&gt;A deployment workstation with Git, Python 3.10 or later, &lt;code&gt;Node.js&lt;/code&gt;, the AWS Command Line Interface (AWS CLI) version 2, the AWS CDK CLI v2, and a running Docker-compatible container engine. The &lt;a href="https://github.com/aws-samples/sample-crawl4ai-bedrock-knowl…
+ &lt;li&gt;AWS credentials configured on the deployment workstation with permission to bootstrap the target environment and deploy the CDK stack.&lt;/li&gt;
+ &lt;li&gt;A bootstrapped CDK environment in the target account and Region. The deployment steps include the bootstrap command.&lt;/li&gt;
+&lt;/ul&gt;
+&lt;p&gt;You need the workstation only to build and deploy. After deployment, the schedule runs the task in AWS.&lt;/p&gt;
+&lt;h3 id="deploy-the-scheduled-workflow"&gt;Deploy the scheduled workflow&lt;/h3&gt;
+&lt;p&gt;Clone the companion repository and install the deployment dependencies:&lt;/p&gt;
&lt;div class="hide-language"&gt;
- &lt;pre&gt;&lt;code class="language-plaintext"&gt;fields requestMetadata.workflow as workflow, modelId,
-input.inputTokenCount as inTokens
-| stats count(*) as calls,
-avg(inTokens) as avgInputTokens,
-sum(inTokens) as totalInputTokens
-by workflow, modelId
-| filter calls &amp;gt; 50 and avgInputTokens &amp;gt; 2000
-| sort totalInputTokens desc
-| limit 25&lt;/code&gt;&lt;/pre&gt;
+ &lt;pre&gt;&lt;code class="language-bash"&gt;git clone https://github.com/aws-samples/sample-crawl4ai-bedrock-knowledge-base.git
+cd sample-crawl4ai-bedrock-knowledge-base/deploy
+python -m venv .venv
+source .venv/bin/activate # Windows PowerShell: .venv\Scripts\Activate.ps1
+python -m pip install -r requirements.txt&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
-&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Field paths shown in the preceding query are illustrative. Verify against your invocation log schema, which may vary by model, API operation, and logging configuration.&lt;/p&gt;
-&lt;h3 id="application-level-optimization"&gt;Application-level optimization&lt;/h3&gt;
-&lt;p&gt;A third class of savings (just-in-time retrieval instead of stuffed context, compaction of long conversations, distilling stable high-volume workflows onto smaller models) belongs to application teams rather than the platform. The platform’s job is to make those savings visible: publish the…
-&lt;h2 id="stage-5-operate-the-loop"&gt;Stage 5: Operate the loop&lt;/h2&gt;
-&lt;p&gt;The first four stages produce data. This one turns it into decisions. The platform team runs a standing health dashboard with four signals:&lt;/p&gt;
+&lt;p&gt;Keep Docker running. Set &lt;code&gt;AWS_DEFAULT_REGION&lt;/code&gt; to your knowledge base’s Region first, because &lt;code&gt;cdk deploy&lt;/code&gt; uses the Region from your environment or AWS profile, not the one in the bootstrap command. Bootstrap the target account and Region once, i…
+&lt;div class="hide-language"&gt;
+ &lt;pre&gt;&lt;code class="language-bash"&gt;export AWS_DEFAULT_REGION=REGION # Windows PowerShell: $env:AWS_DEFAULT_REGION = "REGION"
+cdk bootstrap aws://ACCOUNT_ID/REGION
+
+cdk deploy \
+ -c knowledgeBaseId=ABCDEFGHIJ \
+ -c dataSourceId=KLMNOPQRST \
+ -c s3Bucket=amzn-s3-demo-bucket \
+ -c 'seedUrls=["https://www.example.com/services"]' \
+ -c maxDepth=1 \
+ -c maxPages=25&lt;/code&gt;&lt;/pre&gt;
+&lt;/div&gt;
+&lt;p&gt;Replace every example value, including &lt;code&gt;ACCOUNT_ID&lt;/code&gt;, &lt;code&gt;REGION&lt;/code&gt;, and the four required context keys, with your own. The example values are syntactically valid, so an unedited command deploys a stack that points at a bucket you don’t own. You can a…
+&lt;p&gt;The &lt;code&gt;maxDepth&lt;/code&gt; and &lt;code&gt;maxPages&lt;/code&gt; values limit the first crawl to one link level and 25 pages. Raise them after you review the prepared output. To preview which pages a crawl prepares, you can also run the pipeline locally with &lt;code&gt;--dry-run…
+&lt;p&gt;The sample builds an ARM64 container image by default. If Docker on your x86_64 workstation can’t build ARM64 images, add &lt;code&gt;-c cpuArchitecture=X86_64&lt;/code&gt; to the &lt;code&gt;cdk deploy&lt;/code&gt; command.&lt;/p&gt;
+&lt;p&gt;If your account turns on VPC Block Public Access, the task can’t reach the internet from the default public subnet. To check the mode, run &lt;code&gt;aws ec2 describe-vpc-block-public-access-options&lt;/code&gt;. In ingress-only mode, deploy with &lt;code&gt;-c egressMode=nat&lt;/code&gt;,…
+&lt;p&gt;The stack doesn’t create or change your knowledge base or data source.&lt;/p&gt;
+&lt;p&gt;With the default &lt;code&gt;rate(24 hours)&lt;/code&gt; schedule, the first run starts when the deployment creates the Amazon EventBridge rule. To follow that run, use the command in the &lt;code&gt;TailLogsCommand&lt;/code&gt; output, which &lt;code&gt;cdk deploy&lt;/code&gt; prints when …
+&lt;p&gt;The &lt;a href="https://github.com/aws-samples/sample-crawl4ai-bedrock-knowledge-base/blob/main/deploy/README.md" target="_blank" rel="noopener"&gt;deployment guide&lt;/a&gt; covers the remaining configuration, including crawl boundaries, the schedule, networking, container architecture, mo…
+&lt;h2 id="validate-retrieval-quality"&gt;Validate retrieval quality&lt;/h2&gt;
+&lt;p&gt;After ingestion, test representative questions with &lt;code&gt;Retrieve&lt;/code&gt; before you add generation. A managed knowledge base uses hybrid search. When it uses the default managed embedding model, it also reranks results with its managed reranker. You can narrow results with the …
+&lt;div class="hide-language"&gt;
+ &lt;pre&gt;&lt;code class="language-python"&gt;import time
+
+import boto3
+
+client = boto3.client("bedrock-agent-runtime", region_name="us-east-1")
+week_ago = int(time.time()) - 7 * 24 * 60 * 60
+
+response = client.retrieve(
+ knowledgeBaseId="ABCDEFGHIJ",
+ retrievalQuery={"text": "How do I apply for a building permit?"},
+ retrievalConfiguration={
+ "managedSearchConfiguration": {
+ "numberOfResults": 5,
+ "filter": {
+ "andAll": [
+ {"equals": {"key": "content_category", "value": "web"}},
+ {"greaterThan": {"key": "crawled_at_epoch", "value": week_ago}},
+ ]
+ },
+ }
+ },
+)
+
+for result in response["retrievalResults"]:
+ print(result.get("metadata", {}).get("source_url"), result["content"]["text"][:200])&lt;/code&gt;&lt;/pre&gt;
+&lt;/div&gt;
+&lt;p&gt;The example passes an integer timestamp, which both knowledge base types accept in number filters. A managed knowledge base doesn’t support the &lt;code&gt;startsWith&lt;/code&gt; and &lt;code&gt;stringContains&lt;/code&gt; filters. For a customer-managed knowledge base, pass the same filte…
+&lt;p&gt;Metadata filtering can improve retrieval precision, but it is not an authorization boundary. If different users should see different pages, the Amazon S3 connector for managed knowledge bases supports &lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/kb-managed-ds-s3-acl.html…
+&lt;p&gt;To generate responses from a managed knowledge base, use &lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/kb-test-agentic-retrieve.html" target="_blank" rel="noopener"&gt;agentic retrieval&lt;/a&gt;. The &lt;code&gt;AgenticRetrieveStream&lt;/code&gt; operation returns the re…
+&lt;p&gt;Evaluate retrieval relevance, source-page coverage, and citation quality whenever you change content preparation, chunking, or retrieval settings. For the retrieval settings that you can tune, see &lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/kb-managed-test-config.html" …
+&lt;h2 id="running-it-repeatedly"&gt;Running it repeatedly&lt;/h2&gt;
+&lt;p&gt;Each scheduled event launches one standalone Fargate task. The stack doesn’t prevent overlapping runs, so choose an interval longer than the expected crawl and ingestion duration. A failed run isn’t announced, because the sample adds no retry policy, dead-letter queue, or alarm. An ingestio…
+&lt;p&gt;Each run incurs Fargate charges for the configured task size, which defaults to 2 vCPU and 4 GB. The task keeps running while it polls the ingestion job for up to 30 minutes, so a slow ingestion job extends billable task time. If ingestion takes longer, the task exits with a nonzero code, a…
+&lt;p&gt;Uploads are additive: removing a URL or missing a page during a later crawl doesn’t delete its existing S3 objects. To remove stale content, delete the obsolete document and matching sidecar under the configured prefix, then start ingestion again. If you turn on the document deletion safegu…
+&lt;h2 id="responsible-ai-considerations"&gt;Responsible AI considerations&lt;/h2&gt;
+&lt;p&gt;Retrieved passages become the context that a foundation model uses to generate a response. Apply the following controls before you run this workflow in production:&lt;/p&gt;
&lt;ul&gt;
- &lt;li&gt;&lt;strong&gt;Model mix:&lt;/strong&gt; Which models are called and how often, the direct measure of routing discipline.&lt;/li&gt;
- &lt;li&gt;&lt;strong&gt;Failed request rates:&lt;/strong&gt; Errors, throttles, and timeouts. Each retry adds latency, and a client-side timeout on a request that still completes on the service side can be billed twice, once for the abandoned call and once for the retry.&lt;/li&gt;
- &lt;li&gt;&lt;strong&gt;Cache effectiveness:&lt;/strong&gt; The read-versus-write ratio from Stage 4.&lt;/li&gt;
- &lt;li&gt;&lt;strong&gt;Metadata coverage:&lt;/strong&gt; The percentage of production calls with complete metadata. Every uncovered call is an attribution blind spot that quietly degrades every other number.&lt;/li&gt;
+ &lt;li&gt;&lt;strong&gt;Amazon Bedrock Guardrails&lt;/strong&gt;: Attach a &lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails.html" target="_blank" rel="noopener"&gt;guardrail&lt;/a&gt; to your agentic retrieval or &lt;code&gt;RetrieveAndGenerate&lt;/code&gt; requests to ap…
+ &lt;li&gt;&lt;strong&gt;Contextual grounding checks&lt;/strong&gt;: Turn on the Guardrails &lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails-contextual-grounding-check.html" target="_blank" rel="noopener"&gt;contextual grounding check&lt;/a&gt; to score each response for g…
+ &lt;li&gt;&lt;strong&gt;Treat crawled content as untrusted input&lt;/strong&gt;: Prepared web pages become model context, so text on a public page can attempt prompt injection through retrieval. Don’t rely on guardrails alone to catch it. Restrict seed URLs to sites you trust, and apply the ingesti…
+ &lt;li&gt;&lt;strong&gt;Citations and human review&lt;/strong&gt;: Return citations with every generated response so users can verify claims against the source page. For higher-risk use cases, keep a human reviewer in the loop.&lt;/li&gt;
+&lt;/ul&gt;
+&lt;h2 id="security-and-compliance-considerations"&gt;Security and compliance considerations&lt;/h2&gt;
+&lt;p&gt;Review the following considerations before you run this workflow against production content:&lt;/p&gt;
+&lt;ul&gt;
+ &lt;li&gt;&lt;strong&gt;Use trusted public crawl targets&lt;/strong&gt;: Seed URLs and crawl settings are deployment configuration, and the Fargate task allows outbound access so it can reach public websites. In the sample’s default networking mode, the task runs in a public subnet with a public IP…
+ &lt;li&gt;&lt;strong&gt;Respect crawl directives&lt;/strong&gt;: The workflow turns on Crawl4AI’s &lt;code&gt;robots.txt&lt;/code&gt; check by default, and the CDK path pins it on with no context key to disable it. Verify you have authorization to crawl the target sites, consistent with the &lt;a h…
+ &lt;li&gt;&lt;strong&gt;Rate limiting&lt;/strong&gt;: Configure delays between requests to avoid overwhelming source websites.&lt;/li&gt;
+ &lt;li&gt;&lt;strong&gt;Encryption at rest&lt;/strong&gt;: The stack creates an AWS Key Management Service (AWS KMS) customer managed key with automatic key rotation and encrypts its CloudWatch log groups with it. Amazon S3 encrypts new objects with server-side encryption with Amazon S3 managed key…
+ &lt;li&gt;&lt;strong&gt;Least privilege IAM&lt;/strong&gt;: The CDK stack grants the Fargate task role &lt;code&gt;s3:PutObject&lt;/code&gt; on the configured bucket prefix. It also grants &lt;code&gt;bedrock:StartIngestionJob&lt;/code&gt; and &lt;code&gt;bedrock:GetIngestionJob&lt;/code&gt; on the…
+ &lt;li&gt;&lt;strong&gt;Container and template checks&lt;/strong&gt;: The container runs as a non-root user, and the CDK app runs cdk-nag AWS Solutions checks on every synthesis with resource-scoped suppressions.&lt;/li&gt;
+ &lt;li&gt;&lt;strong&gt;Protect deployment configuration&lt;/strong&gt;: The CDK app stores non-secret pipeline settings in a plaintext Parameter Store &lt;code&gt;String&lt;/code&gt; parameter. Only the parameter name is placed in the task definition. Don’t put passwords, cookies, tokens, or other…
+ &lt;li&gt;&lt;strong&gt;Ingestion pipeline security&lt;/strong&gt;: See &lt;a href="https://aws.amazon.com/blogs/security/securing-the-rag-ingestion-pipeline-filtering-mechanisms/" target="_blank" rel="noopener"&gt;Securing the RAG ingestion pipeline: Filtering mechanisms&lt;/a&gt; for filtering an…
+&lt;/ul&gt;
+&lt;h2 id="clean-up"&gt;Clean up&lt;/h2&gt;
+&lt;p&gt;To avoid ongoing charges, delete the resources created during this walkthrough:&lt;/p&gt;
+&lt;ul&gt;
+ &lt;li&gt;From the repository’s &lt;code&gt;deploy/&lt;/code&gt; directory, run &lt;code&gt;cdk destroy&lt;/code&gt; in the same Region, with the same four required &lt;code&gt;-c&lt;/code&gt; values that you passed to &lt;code&gt;cdk deploy&lt;/code&gt;. The app checks them on every command. This …
+ &lt;li&gt;To remove the ingested web content, delete the prepared objects under &lt;code&gt;s3://&amp;lt;bucket&amp;gt;/&amp;lt;prefix&amp;gt;&lt;/code&gt; and sync the data source again. If the document deletion safeguard is on for a managed knowledge base data source, a sync that would delete mor…
+ &lt;li&gt;Delete the managed knowledge base only if you created it solely for this walkthrough. A managed knowledge base has no separate vector store to delete.&lt;/li&gt;
+ &lt;li&gt;For a customer-managed knowledge base, delete the Amazon S3 data source only if you created it for this walkthrough. Its data deletion policy determines whether Amazon Bedrock also deletes the data source’s vector embeddings from your vector store.&lt;/li&gt;
&lt;/ul&gt;
-&lt;p&gt;When a signal drifts, the remediation is a policy change (routing rules, token limits, metadata enforcement), not an email asking teams to be careful.&lt;/p&gt;
-&lt;h3 id="the-money-loop"&gt;The money loop&lt;/h3&gt;
-&lt;p&gt;FinOps runs the money loop on the same data. When attribution is clean, anomaly detection becomes an investigation stream rather than a panicked all-hands: a spike in a tagged team or application triggers a lookup in the Stage 2 leaderboard, not a war room. Chargeback runs from CUR grouping…
-&lt;h3 id="scorecard"&gt;Scorecard&lt;/h3&gt;
-&lt;p&gt;The following thresholds are starting points, not prescriptions. Calibrate them against your own fleet data and pricing tier before adopting them as policy.&lt;/p&gt;
-&lt;table border="1px" width="100%" cellpadding="10px"&gt;
- &lt;tbody&gt;
- &lt;tr&gt;
- &lt;td&gt;&lt;strong&gt;Dimension&lt;/strong&gt;&lt;/td&gt;

Diff display stops at 400 lines. The line counts above are from the whole diff. 72 lines shown here cut at 300 characters. The raw artifact at this commit is linked above.