<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sarath Kumar Kallayil Sreedharan</title>
    <description>The latest articles on DEV Community by Sarath Kumar Kallayil Sreedharan (@kallayilsreedharansk).</description>
    <link>https://dev.to/kallayilsreedharansk</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4094660%2Fa13db418-3b44-4751-90d7-62e967c57a01.PNG</url>
      <title>DEV Community: Sarath Kumar Kallayil Sreedharan</title>
      <link>https://dev.to/kallayilsreedharansk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kallayilsreedharansk"/>
    <language>en</language>
    <item>
      <title>When AI Meets the Message Queue: Building Intelligent Routing with Amazon Bedrock and SQS</title>
      <dc:creator>Sarath Kumar Kallayil Sreedharan</dc:creator>
      <pubDate>Tue, 25 Aug 2026 19:07:14 +0000</pubDate>
      <link>https://dev.to/kallayilsreedharansk/when-ai-meets-the-message-queue-building-intelligent-routing-with-amazon-bedrock-and-sqs-ahc</link>
      <guid>https://dev.to/kallayilsreedharansk/when-ai-meets-the-message-queue-building-intelligent-routing-with-amazon-bedrock-and-sqs-ahc</guid>
      <description>&lt;p&gt;This is Part 1 of a series on adding AI-assisted decision-making to event-driven messaging systems. The architecture grew out of my ACM Summer Tech Talk on intelligent message routing and prioritization, and this article introduces the open-source reference implementation used throughout the series.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem with static routing logic
&lt;/h2&gt;

&lt;p&gt;Most event-driven systems make the same handful of decisions repeatedly using deterministic rules.&lt;/p&gt;

&lt;p&gt;That's often the right design — until those decisions start depending on context that changes faster than the rules do.&lt;/p&gt;

&lt;p&gt;A message shows up. Some code decides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which processing path it belongs in&lt;/li&gt;
&lt;li&gt;How urgently it needs to be processed&lt;/li&gt;
&lt;li&gt;What to do if processing fails&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Traditionally, those decisions are implemented with fixed logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SQS → Consumer/Lambda → Fixed Logic → Process/Retry → DLQ
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That logic might be a collection of if/elif statements, lookup tables, message attributes, or routing policies based on conditions known when the system was designed.&lt;/p&gt;

&lt;p&gt;And for many workloads, that's exactly what you want.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If a decision can be expressed reliably with a few deterministic rules, an AI model probably shouldn't be involved.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The challenge appears when decisions depend on broader and continuously changing context.&lt;/p&gt;

&lt;p&gt;What does "high priority" mean when a downstream dependency is degraded? Should two failures with completely different causes receive the same retry treatment? Should a message continue down its normal processing path when another approved processor is healthier?&lt;/p&gt;

&lt;p&gt;Static rules can handle these scenarios, but as the number of contextual signals grows, the decision tree can become increasingly complex to maintain.&lt;/p&gt;

&lt;p&gt;That's where AI-assisted decision-making becomes interesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where contextual decision-making can help
&lt;/h2&gt;

&lt;p&gt;There are three areas I wanted to explore.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Routing.&lt;/strong&gt; Traditional routing often maps known message types to predetermined destinations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Message Type A → Processor A
Message Type B → Processor B
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But the appropriate processing path may depend on more than the message type. Message characteristics, downstream availability, workload conditions, or other operational context may also matter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prioritization.&lt;/strong&gt; Priority is frequently encoded as a fixed message attribute or determined using predefined business rules. But urgency can sometimes depend on context. A message that is routine under normal operating conditions may deserve different treatment when the system is experiencing an incident, backlog, or downstream degradation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Retry behavior.&lt;/strong&gt; Failures are also not identical. A transient downstream timeout and a permanently invalid request should not necessarily receive the same retry strategy. Repeatedly retrying a request that is unlikely to succeed can waste resources, while retrying too slowly after a transient failure can unnecessarily increase recovery time.&lt;/p&gt;

&lt;p&gt;The question becomes: can we use additional context to make better recommendations while preserving deterministic control over what the system actually does?&lt;/p&gt;

&lt;h2&gt;
  
  
  An AI-assisted approach
&lt;/h2&gt;

&lt;p&gt;The architecture I explored does not replace deterministic rules with AI. Instead, it introduces AI as a decision-support layer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SQS
 ↓
Lambda / Consumer
 ↓
Context Builder
 ↓
Amazon Bedrock
 ↓
AI Recommendation
 ↓
Policy Guardrails
 ↓
Action
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One important distinction: Amazon Bedrock does not poll SQS or control the queue. In a Lambda-based implementation, the SQS event source mapping handles polling and invokes the Lambda consumer. The application builds the relevant context and invokes the model. The model participates in the decision, not the queue mechanics.&lt;/p&gt;

&lt;p&gt;A decision request might contain information such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"service_interruption"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message_age_seconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"attempt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"queue_backlog"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"downstream_health"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"degraded"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"workload_tier"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"critical"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The decision layer can return a structured recommendation such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"priority"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"HIGH"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"route"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PROCESSOR_B"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"retry_delay_seconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.93&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The application does not blindly execute that response. It validates the recommendation against deterministic policy first.&lt;/p&gt;

&lt;h2&gt;
  
  
  The principle that makes this practical
&lt;/h2&gt;

&lt;p&gt;The entire pattern can be summarized in one sentence:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;AI recommends. Policy decides. The messaging platform executes.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That separation is important. The model never receives unrestricted operational authority. Its recommendation passes through deterministic guardrails controlling things such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allowed routing destinations&lt;/li&gt;
&lt;li&gt;Valid priority levels&lt;/li&gt;
&lt;li&gt;Maximum retry attempts&lt;/li&gt;
&lt;li&gt;Bounded retry delays&lt;/li&gt;
&lt;li&gt;Minimum confidence thresholds&lt;/li&gt;
&lt;li&gt;Workload-specific restrictions&lt;/li&gt;
&lt;li&gt;Fallback behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a recommendation violates policy, the application rejects it. If the model isn't available, the application falls back. If the response isn't valid, the application falls back. If the confidence indicator is below the configured threshold, the application falls back.&lt;/p&gt;

&lt;p&gt;That's not a limitation bolted on as an afterthought. It's the design.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pattern 1: Content-aware routing
&lt;/h2&gt;

&lt;p&gt;Suppose the normal routing logic looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Message Type A → Processor A
Message Type B → Processor B
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now imagine that routing depends on additional context:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Message characteristics
        +
Processing requirements
        +
Downstream health
        +
Operational conditions
        ↓
   Routing Decision
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of expanding a static decision tree indefinitely, the consumer can provide that context to the AI decision layer. The model might recommend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"route"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PROCESSOR_B"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.94&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But the recommendation still goes through policy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;route&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ALLOWED_ROUTES&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DEFAULT_ROUTE&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;route&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bedrock recommends &lt;code&gt;PROCESSOR_B&lt;/code&gt;. The application determines whether &lt;code&gt;PROCESSOR_B&lt;/code&gt; is permitted. The messaging layer executes the validated routing decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pattern 2: AI-assisted priority scoring
&lt;/h2&gt;

&lt;p&gt;Consider two messages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Message A&lt;/strong&gt; — Type: Account update. Age: 2 seconds. Workload tier: Standard. Queue backlog: Low.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Message B&lt;/strong&gt; — Type: Service interruption. Age: 45 seconds. Workload tier: Critical. Queue backlog: High. Downstream risk: Elevated.&lt;/p&gt;

&lt;p&gt;A fixed priority rule might only examine the message type. A context-aware decision layer can consider multiple signals and recommend an urgency level:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"priority"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"HIGH"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"reason"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Critical workload with elevated downstream risk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.95&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The application validates that recommendation and selects the appropriate processing path.&lt;/p&gt;

&lt;p&gt;Priority itself is not implemented through an SQS visibility timeout. Visibility timeout controls how long a received message remains hidden from other consumers while it is being processed. In the reference implementation, different processing paths can have their own operational queue configuration, but queue selection represents prioritization; visibility timeout is a separate reliability configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pattern 3: Adaptive retry and backoff
&lt;/h2&gt;

&lt;p&gt;Retry behavior becomes particularly interesting when additional failure context is available. An adaptive decision can consider error category, previous attempts, downstream health, queue backlog, message urgency, and historical failure context.&lt;/p&gt;

&lt;p&gt;It might recommend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"retry"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"retry_delay_seconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;180&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.89&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"retry"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"route"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"FALLBACK_PROCESSOR"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.94&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model is recommending a retry strategy. Deterministic policy still enforces maximum attempts, allowed retry intervals, maximum delay, approved fallback destinations, and DLQ behavior.&lt;/p&gt;

&lt;p&gt;The AI layer therefore does not replace SQS reliability mechanisms. It adds contextual decision support around them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Confidence is a gate, not authority
&lt;/h2&gt;

&lt;p&gt;The model response also includes a structured confidence indicator. That value should not be interpreted as a statistically calibrated probability of correctness unless you've specifically built and validated it that way.&lt;/p&gt;

&lt;p&gt;In this pattern, it serves a simpler purpose: it's one input into the application's acceptance policy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;confidence&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;MIN_CONFIDENCE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;use_deterministic_fallback&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;route&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ALLOWED_ROUTES&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;use_default_route&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;execute_validated_decision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the reference implementation, responses below &lt;code&gt;MIN_CONFIDENCE&lt;/code&gt; are rejected in favor of deterministic behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happens when Bedrock is unavailable?
&lt;/h2&gt;

&lt;p&gt;The system should never become:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Bedrock unavailable
        ↓
Messaging stops
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If Bedrock is unavailable, times out, returns malformed output, or produces a recommendation that doesn't satisfy policy, the application falls back to deterministic processing. The queue continues operating. The consumer continues processing. Existing retry and DLQ mechanisms remain available.&lt;/p&gt;

&lt;p&gt;AI should enhance the system, not become a new single point of failure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Should every message invoke an AI model?
&lt;/h2&gt;

&lt;p&gt;Probably not.&lt;/p&gt;

&lt;p&gt;Model invocation introduces additional considerations: latency, cost, throughput, quotas, availability, and operational complexity. A practical architecture can use AI selectively. Simple decisions stay deterministic. AI is reserved for situations where additional context provides enough value to justify the model invocation.&lt;/p&gt;

&lt;h2&gt;
  
  
  A working reference implementation
&lt;/h2&gt;

&lt;p&gt;I built this architecture as an AWS SAM reference application: &lt;a href="https://github.com/kallayilsreedharansk/ai-message-queue-patterns" rel="noopener noreferrer"&gt;&lt;strong&gt;ai-message-queue-patterns&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It uses Amazon SQS, AWS Lambda, and Amazon Bedrock, and combines three related patterns into one message-processing pipeline.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pattern&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Content-Aware Routing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Bedrock evaluates message context and recommends a downstream destination; deterministic policy validates the recommendation before routing.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AI-Assisted Priority Scoring&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Evaluates message context and recommends an urgency level used to select the appropriate processing path.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Adaptive Retry &amp;amp; Backoff&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;On failure, classifies the failure context and recommends a retry strategy; deterministic policy enforces attempt limits, delay bounds, and DLQ behavior.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A few implementation choices are particularly important.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deterministic mode.&lt;/strong&gt; Setting &lt;code&gt;USE_BEDROCK=false&lt;/code&gt; allows the pipeline to operate using deterministic fallback logic without depending on model access. The messaging system doesn't have to depend on AI in order to function.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Confidence gating.&lt;/strong&gt; The implementation uses a configurable threshold: &lt;code&gt;MIN_CONFIDENCE=0.7&lt;/code&gt;. Recommendations below that threshold are rejected in favor of deterministic fallback. The threshold isn't proof that a recommendation is correct; it's an application policy controlling when the system is willing to consider the model's output.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Independent patterns.&lt;/strong&gt; The Router, Priority Scorer, and Retry Handler are separate components. That means adopting this architecture doesn't require committing to every pattern at once.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lambda isn't required.&lt;/strong&gt; Although the reference implementation uses Lambda, the architecture isn't Lambda-specific. A consumer could run on AWS Lambda, Amazon EC2, Amazon ECS, Amazon EKS, or another application runtime. The architectural principle remains unchanged: the application invokes the AI decision engine. The AI model does not replace the messaging infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bigger pattern
&lt;/h2&gt;

&lt;p&gt;Traditional automation often looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Event → Rule → Action
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;AI-assisted automation introduces another possibility:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Event → Context → AI Recommendation → Policy → Action
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adding AI doesn't eliminate deterministic engineering. If anything, it makes deterministic engineering more important.&lt;/p&gt;

&lt;p&gt;Once a probabilistic component becomes part of a production decision path, the boundaries around that component need to become explicit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is the model allowed to recommend?&lt;/li&gt;
&lt;li&gt;What is it never allowed to decide?&lt;/li&gt;
&lt;li&gt;What happens when it's wrong?&lt;/li&gt;
&lt;li&gt;What happens when it's unavailable?&lt;/li&gt;
&lt;li&gt;When should we avoid invoking it altogether?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For message-driven systems, routing, prioritization, and retry are three interesting places to explore contextual AI-assisted decision-making. But the architectural principle stays deliberately simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI recommends. Policy decides. The messaging platform executes.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;This article covered the architecture and the reasoning behind it. Part 2 will go deeper into policy guardrails, confidence thresholds, deterministic fallback, malformed model responses, and failure modes. After that, I'll walk through the implementation itself using the open-source repository.&lt;/p&gt;

&lt;p&gt;If you want to explore the code now: 👉 &lt;a href="https://github.com/kallayilsreedharansk/ai-message-queue-patterns" rel="noopener noreferrer"&gt;AI-Assisted Message Queue Patterns on GitHub&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;The examples in this article are architectural patterns and reference implementations intended for experimentation and learning. Production systems should evaluate model behavior, latency, cost, security, failure modes, and workload-specific requirements before introducing AI-assisted decision-making into critical processing paths.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>aws</category>
      <category>serverless</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
