An extra 30% off every course until Sunday, October 11.Choose your certification →

Copyright (c) 2026 MindMesh Academy. All rights reserved. This content is proprietary and may not be reproduced or distributed without permission.

4.1.2. Reasoning Patterns: ReAct and Chain-of-Thought

💡 First Principle: The ReAct (Reasoning + Acting) pattern transforms an FM from a single-turn responder into a multi-step problem solver by interleaving thought (explicit reasoning about what to do next) with action (calling a tool) and observation (incorporating the tool's result before the next thought). This loop continues until the model determines it has enough information to answer.

The ReAct loop in detail:
Thought: The user wants the Q3 revenue compared to budget. I need to retrieve the actual 
         revenue figure and the budget figure separately, then compute the variance.

Action: query_financial_db(query="Q3 actual revenue", fiscal_year=2024)

Observation: Q3 actual revenue = $4.2M

Thought: I have the actual. Now I need the budget figure.

Action: query_financial_db(query="Q3 budgeted revenue", fiscal_year=2024)

Observation: Q3 budgeted revenue = $3.8M

Thought: I have both figures. Variance = $4.2M - $3.8M = +$0.4M (+10.5%). 
         I can now answer.

Final Answer: Q3 actual revenue of $4.2M exceeded the $3.8M budget by $400K (+10.5%).

Implementing ReAct with Step Functions (when you need explicit orchestration control):

{
  "Comment": "ReAct reasoning loop",
  "StartAt": "Think",
  "States": {
    "Think": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:::function:invoke-bedrock-reasoning",
      "Next": "Route"
    },
    "Route": {
      "Type": "Choice",
      "Choices": [
        {"Variable": "$.next_action", "StringEquals": "tool_call", "Next": "Act"},
        {"Variable": "$.next_action", "StringEquals": "final_answer", "Next": "Respond"}
      ]
    },
    "Act": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:::function:execute-tool",
      "Next": "Think"
    },
    "Respond": {"Type": "Succeed"}
  }
}

Controlled orchestration: the FM only proposes the next action; your application validates the proposal, decides whether and when to run it, and feeds the result back for the next step. The Converse API's tool use (the model returns a toolUse request, your code runs the tool and sends back a toolResult) and Bedrock Agents' return of control both work this way. A state machine that simply branches on the action the FM chose, like the loop above, still lets the FM decide which tool runs; the control comes from the validation step. Use it when you need full control over which tools run and in what order; a managed agent plans and executes autonomously.

Stopping conditions — critical for production agents: Without stopping conditions, a misbehaving agent can loop indefinitely, calling tools repeatedly and accumulating costs. Always implement:

  • Maximum iteration limit: Hard cap on reasoning steps (e.g., max 10 iterations)
  • Timeout: Lambda timeout propagates through; Step Functions state machine timeout
  • IAM boundaries: The Lambda execution role limits what the agent can touch — a tool that can only read DynamoDB cannot accidentally delete records even if the agent tries
  • Circuit breaker: Detect repeated identical tool calls (infinite loop pattern) and break

⚠️ Exam Trap: A managed agent service runs the reasoning loop for you, but that is no reason to skip loop controls. When you build the loop yourself (a Step Functions state machine or a code-first framework), the stopping conditions are yours to implement: without an iteration cap, a misbehaving agent keeps looping and keeps paying for FM invocations.

Reflection Question: Your Bedrock Agent-powered travel booking system is observed making 40+ tool calls for a simple "book me a flight to NYC" request before timing out. What are the three most likely causes of excessive reasoning steps, and how would you diagnose each?

See how it connects
Alvin Varughese
Written byAlvin Varughese
Founder•20 professional certifications