~/krishna_dhakal
#AWS#Bedrock#AgentCore#Agents#AI

Agents in Amazon Bedrock AgentCore — Fundamentals, Patterns, and the Agent vs Workflow Divide

> June 12, 2026

Modern AI systems are no longer single prompt-response pairs. They plan, act, observe, and adapt. Amazon Bedrock AgentCore is the managed runtime that lets you bring that loop to production without rebuilding the scaffolding every time. This post unpacks what an agent actually is, how any agent code becomes a first-class citizen in AgentCore, every platform feature you can use, the canonical agent patterns, and the practical line between an agent and a workflow.

// What Is an Agent at the Fundamental Level?

Strip away every framework and SDK and you are left with a deceptively simple loop:

┌─────────────────────────────────────────────────────────────────┐
│                     THE AGENT LOOP                              │
│                                                                 │
│   ┌──────────┐    perceive    ┌──────────┐                      │
│   │          │ ◄────────────  │          │                      │
│   │  Model   │                │  World   │                      │
│   │  (LLM)   │  ────────────► │  State   │                      │
│   │          │     act        │          │                      │
│   └──────────┘                └──────────┘                      │
│        │                           ▲                            │
│        │  reason / decide          │  observe result            │
│        └───────────────────────────┘                            │
└─────────────────────────────────────────────────────────────────┘

An agent is any system that:

  1. Perceives — takes in observations from its environment (user messages, tool outputs, sensor data).
  2. Reasons — uses a model (or heuristic) to decide what to do next.
  3. Acts — calls tools, writes memory, sends messages, invokes APIs.
  4. Observes — receives the result of that action and folds it back into step 1.

The loop runs until a stopping condition is met: the goal is achieved, a budget is exhausted, or a human steps in.

> Why "agent" is not the same as "chatbot"

A chatbot maps one input to one output. An agent treats each response as a step toward a goal and may take dozens of actions, none of which are visible to the user, before producing a final answer. The key properties are:

┌──────────────────────────────────────────────────────────────────┐
│              AGENT VS CHATBOT                                    │
│                                                                  │
│  Chatbot                       Agent                             │
│  ──────────────────────        ──────────────────────────────    │
│  Single turn                   Multi-turn goal-directed loop     │
│  No persistent state           Memory across steps               │
│  No tool use (usually)         Arbitrarily many tool calls       │
│  Deterministic output          Emergent behavior from planning   │
│  Stateless                     Stateful                          │
└──────────────────────────────────────────────────────────────────┘

> The three ingredients every agent needs

┌──────────────────────────────────────────────────────────────────┐
│                    AGENT INGREDIENTS                             │
│                                                                  │
│  1. BRAIN  — A model that can reason and plan                    │
│              (Claude, GPT-4o, Llama 3, Mistral, …)              │
│                                                                  │
│  2. TOOLS  — Functions the model can call to interact with       │
│              the world (search, code exec, DB query, API, …)    │
│                                                                  │
│  3. MEMORY — State that persists across steps                    │
│              (short-term: context window,                        │
│               long-term: vector store / KV store)               │
└──────────────────────────────────────────────────────────────────┘

// Amazon Bedrock AgentCore — What It Is

AgentCore is AWS's managed platform for hosting, orchestrating, and observing agents at production scale. It is deliberately agent-framework-agnostic: it does not care whether your agent is built with LangChain, LlamaIndex, Strands Agents, AutoGen, a plain boto3 script, or a custom loop written from scratch. What it cares about is the contract your agent exposes.

┌──────────────────────────────────────────────────────────────────────┐
│                     AGENTCORE PLATFORM OVERVIEW                      │
│                                                                      │
│  ┌────────────┐  ┌────────────┐  ┌────────────┐  ┌───────────────┐  │
│  │  Runtime   │  │  Memory    │  │   Tool     │  │  Identity &   │  │
│  │  (hosted   │  │  Store     │  │   Gateway  │  │  Auth         │  │
│  │   agent)   │  │            │  │            │  │               │  │
│  └────────────┘  └────────────┘  └────────────┘  └───────────────┘  │
│  ┌────────────┐  ┌────────────┐  ┌────────────┐  ┌───────────────┐  │
│  │  Code      │  │  Browser   │  │  Observ-   │  │  Multi-agent  │  │
│  │  Executor  │  │  Tool      │  │  ability   │  │  Collab.      │  │
│  └────────────┘  └────────────┘  └────────────┘  └───────────────┘  │
└──────────────────────────────────────────────────────────────────────┘

// How Any Agent Code Plugs into AgentCore

AgentCore Runtime is the hosting surface. It runs your agent as a container and exposes it through a managed endpoint. The integration contract is minimal.

> Step 1 — Implement the invoke handler

Your agent must expose a function (or HTTP handler) that accepts a payload and returns a streaming or non-streaming response. With the Strands Agents SDK the wiring is one decorator:

from strands import Agent
from strands_tools import calculator, file_read, shell

agent = Agent(
    model="us.amazon.nova-pro-v1:0",
    tools=[calculator, file_read, shell],
    system_prompt="You are a helpful assistant.",
)

# AgentCore calls this entry point
def invoke(payload: dict) -> dict:
    user_input = payload["prompt"]
    response = agent(user_input)
    return {"response": str(response)}

If you prefer LangChain:

from langchain.agents import initialize_agent, AgentType
from langchain_aws import ChatBedrock
from langchain.tools import tool

llm = ChatBedrock(model_id="anthropic.claude-3-5-sonnet-20241022-v2:0")

@tool
def lookup_order(order_id: str) -> str:
    """Look up an order by ID."""
    # ... real implementation
    return f"Order {order_id}: shipped"

agent_chain = initialize_agent(
    tools=[lookup_order],
    llm=llm,
    agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION,
    verbose=True,
)

def invoke(payload: dict) -> dict:
    result = agent_chain.run(payload["prompt"])
    return {"response": result}

The pattern is identical for AutoGen, CrewAI, or a raw loop — wrap your agent's entry point in an invoke function.

> Step 2 — Package as a container

FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "-m", "agentcore_runtime", "--handler", "main.invoke"]

AgentCore Runtime accepts any OCI-compliant image. Push it to Amazon ECR.

> Step 3 — Deploy with the AgentCore API or CDK

import boto3

client = boto3.client("bedrock-agentcore-control")

response = client.create_agent_runtime(
    agentRuntimeName="order-assistant",
    agentRuntimeArtifact={
        "containerConfiguration": {
            "containerUri": "123456789012.dkr.ecr.us-east-1.amazonaws.com/order-assistant:latest"
        }
    },
    networkConfiguration={"networkMode": "PUBLIC"},
)

runtime_arn = response["agentRuntimeArn"]

AgentCore provisions compute, auto-scales to zero, handles TLS termination, and returns a stable HTTPS endpoint. Your agent is now production-ready without managing any infrastructure.

> What AgentCore injects automatically

┌──────────────────────────────────────────────────────────────────┐
│           WHAT AGENTCORE PROVIDES TO YOUR CONTAINER             │
│                                                                  │
│  • AWS credentials via IAM roles (no secret management needed)  │
│  • Session context (session ID, user identity)                  │
│  • Managed scaling (0 → N instances)                            │
│  • TLS-terminated HTTPS endpoint                                │
│  • Request/response logging and tracing                         │
│  • Integration hooks for Memory Store, Tool Gateway, etc.       │
└──────────────────────────────────────────────────────────────────┘

// AgentCore Platform Features

Beyond hosting your container, AgentCore offers a suite of building blocks you opt into.

> 1. Memory Store

Agents are stateless by default. Memory Store gives them durable short-term and long-term state without your team managing DynamoDB tables or Redis clusters.

┌──────────────────────────────────────────────────────────────────┐
│                        MEMORY STORE                              │
│                                                                  │
│  ┌─────────────────┐        ┌──────────────────┐                │
│  │  Conversation   │        │   Semantic (Long  │                │
│  │  History        │        │   Term) Memory    │                │
│  │                 │        │                   │                │
│  │  • Per-session  │        │  • Vector search  │                │
│  │  • Automatic    │        │  • User profile   │                │
│  │    truncation   │        │  • Fact storage   │                │
│  │  • Managed TTL  │        │  • Cross-session  │                │
│  └─────────────────┘        └──────────────────┘                │
│                                                                  │
│  SDK:  from bedrock_agentcore import memory                      │
│        memory.save(session_id, key, value)                       │
│        memory.get(session_id, key)                               │
└──────────────────────────────────────────────────────────────────┘
from bedrock_agentcore import memory

def invoke(payload):
    session_id = payload["sessionId"]
    # Recall user preference from a previous session
    pref = memory.get(session_id, "preferred_language") or "English"
    # ... agent logic ...
    memory.save(session_id, "last_topic", "billing")

> 2. Tool Gateway (Managed Tool Execution)

Tool Gateway lets you register, version, and securely share tools across multiple agents. Instead of bundling tool code inside every agent container, you register them once and agents call them over a managed internal network.

┌──────────────────────────────────────────────────────────────────┐
│                       TOOL GATEWAY                               │
│                                                                  │
│  Agent A ──────────────────────────────────────┐                │
│                                                 ▼                │
│  Agent B ──────────────────────────────► Tool Gateway ─► Tool   │
│                                                 ▲                │
│  Agent C ──────────────────────────────────────┘                │
│                                                                  │
│  Benefits                                                        │
│  • Single IAM policy per tool                                    │
│  • Rate limiting and throttling                                  │
│  • Audit log of every tool call                                  │
│  • Versioning — swap v1 for v2 without touching agents           │
└──────────────────────────────────────────────────────────────────┘

> 3. Code Interpreter (Secure Code Execution)

Agents frequently need to run generated code — data analysis, chart generation, unit-test execution. AgentCore's Code Interpreter spins an isolated sandbox per invocation.

from bedrock_agentcore.tools import CodeInterpreterTool

code_tool = CodeInterpreterTool()

result = code_tool.run("""
import pandas as pd
df = pd.DataFrame({"month": ["Jan","Feb","Mar"], "revenue": [12000, 14500, 11200]})
print(df.describe())
""")
print(result.output)

Each sandbox is:

  • Ephemeral (destroyed after the call)
  • Network-isolated
  • Resource-limited (CPU + memory caps)
  • Language-agnostic (Python, Node.js, bash supported)

> 4. Browser Tool (Managed Web Browsing)

Agents that need live web data get a managed, headless-browser session. AgentCore handles browser lifecycle, JavaScript rendering, and session isolation.

from bedrock_agentcore.tools import BrowserTool

browser = BrowserTool()
page_text = browser.fetch("https://docs.aws.amazon.com/bedrock/latest/userguide/")

No Playwright setup, no Selenium infra, no ephemeral EC2 for screenshots.

> 5. Identity and Authorization

AgentCore integrates with AWS IAM and supports OAuth 2.0 / OIDC for delegating user-level permissions to the agent. The agent can act on behalf of a user without storing that user's credentials.

┌──────────────────────────────────────────────────────────────────┐
│                    IDENTITY FLOW                                 │
│                                                                  │
│  User ──(OAuth token)──► AgentCore Runtime                       │
│                               │                                  │
│                               │ assumes role with               │
│                               │ session tags                    │
│                               ▼                                  │
│                          IAM Role ──► S3, DynamoDB, RDS, …       │
│                                                                  │
│  The agent only has the permissions the user has, nothing more.  │
└──────────────────────────────────────────────────────────────────┘

> 6. Observability (Traces, Metrics, Logs)

Every agent invocation is traced end-to-end with OpenTelemetry-compatible spans. You get:

┌──────────────────────────────────────────────────────────────────┐
│                      OBSERVABILITY STACK                         │
│                                                                  │
│  Trace example for a single agent turn                           │
│                                                                  │
│  [0ms]  invoke()                                                 │
│    [12ms]  LLM call — claude-3-5-sonnet  (input: 420 tok)        │
│    [800ms] tool: lookup_order("ORD-9921")                        │
│    [820ms] LLM call — claude-3-5-sonnet  (input: 510 tok)        │
│    [1.1s]  response returned                                     │
│                                                                  │
│  Metrics surfaced: latency p50/p99, token usage, error rate,     │
│  tool call frequency, cost per invocation.                       │
│                                                                  │
│  Integrates with: CloudWatch, Amazon Managed Grafana, ADOT.      │
└──────────────────────────────────────────────────────────────────┘

> 7. Multi-Agent Collaboration

AgentCore supports supervisor/sub-agent architectures out of the box. A supervisor agent decomposes a complex task and delegates sub-tasks to specialised agents, each running as its own AgentCore Runtime.

┌──────────────────────────────────────────────────────────────────┐
│                  MULTI-AGENT COLLABORATION                       │
│                                                                  │
│               ┌────────────────┐                                 │
│               │   Supervisor   │                                 │
│               │     Agent      │                                 │
│               └───────┬────────┘                                │
│          ┌────────────┼────────────┐                             │
│          ▼            ▼            ▼                             │
│   ┌────────────┐ ┌──────────┐ ┌──────────┐                      │
│   │  Research  │ │  Coding  │ │  Review  │                      │
│   │   Agent   │ │  Agent   │ │  Agent   │                      │
│   └────────────┘ └──────────┘ └──────────┘                      │
│                                                                  │
│  Communication: AgentCore-to-AgentCore API calls,                │
│  authenticated via IAM roles.                                    │
└──────────────────────────────────────────────────────────────────┘

// Agent Architectural Patterns

Agents are not one-size-fits-all. Different problems call for different loop structures. Here are the canonical patterns.

> Pattern 1 — ReAct (Reason + Act)

The most common pattern. The model alternates between reasoning ("Thought") and acting ("Action") until it reaches a final answer.

┌──────────────────────────────────────────────────────────────────┐
│                     REACT PATTERN                                │
│                                                                  │
│  User: "What is the weather in Paris and should I bring a coat?" │
│                                                                  │
│  Thought: I need current Paris weather.                          │
│  Action: weather_tool(city="Paris")                              │
│  Observation: 14°C, light rain, wind 20 km/h                    │
│                                                                  │
│  Thought: 14°C with rain — a coat is appropriate.               │
│  Final Answer: "Yes, bring a coat. It's 14°C and raining."       │
│                                                                  │
│  Loop:  Thought → Action → Observation → Thought → …            │
└──────────────────────────────────────────────────────────────────┘

Best for: single-agent, tool-using tasks with a clear terminal condition.

> Pattern 2 — Plan-and-Execute

The model first produces a complete plan (list of steps) and then executes each step sequentially or in parallel.

┌──────────────────────────────────────────────────────────────────┐
│                  PLAN-AND-EXECUTE PATTERN                        │
│                                                                  │
│  Phase 1 — PLAN                                                  │
│  ┌────────────────────────────────────────────────────────┐      │
│  │  1. Search for Q4 sales data                           │      │
│  │  2. Pull competitor pricing from web                   │      │
│  │  3. Run margin analysis                                │      │
│  │  4. Draft executive summary                            │      │
│  └────────────────────────────────────────────────────────┘      │
│                          │                                       │
│  Phase 2 — EXECUTE (steps run sequentially or in parallel)       │
│  Step 1 ──► Step 2 ──► Step 3 ──► Step 4 ──► Final output        │
│                                                                  │
│  Benefits: explicit plan is reviewable; parallel execution        │
│  is straightforward; errors are localised to a step.             │
└──────────────────────────────────────────────────────────────────┘

Best for: long-horizon tasks, tasks with parallelisable sub-tasks, situations where a human needs to approve the plan before execution.

> Pattern 3 — Reflection (Self-Critique)

After generating an answer the agent critiques its own output and revises until quality gates are met.

┌──────────────────────────────────────────────────────────────────┐
│                    REFLECTION PATTERN                            │
│                                                                  │
│  Generate ──► Critique ──► Revise ──► Critique ──► Accept        │
│                                                                  │
│  Example:                                                        │
│  Draft:    "The function runs in O(n²) time."                    │
│  Critique: "Needs proof and a faster alternative."               │
│  Revision: "The nested loop produces O(n²). Here is an O(n      │
│             log n) merge-sort approach: …"                       │
│  Critique: "Sufficient. Accept."                                 │
│                                                                  │
│  Use when: code generation, essay writing, SQL generation,        │
│  any task where the quality bar is measurable.                   │
└──────────────────────────────────────────────────────────────────┘

> Pattern 4 — Multi-Agent (Supervisor / Sub-agent)

A supervisor agent breaks a complex task into sub-tasks and routes them to specialist sub-agents. Results are aggregated and synthesised.

┌──────────────────────────────────────────────────────────────────┐
│                  MULTI-AGENT PATTERN                             │
│                                                                  │
│  User: "Analyse our Q4 results and draft the board deck."        │
│                                                                  │
│  Supervisor: decompose                                           │
│      ├─► Finance Agent   → revenue / cost breakdown              │
│      ├─► Market Agent    → competitor benchmarks                 │
│      └─► Writing Agent   → narrative + slide structure           │
│                    │                                             │
│  Supervisor: aggregate + produce final deck                      │
│                                                                  │
│  Each sub-agent is an independent, isolated unit.                │
└──────────────────────────────────────────────────────────────────┘

Best for: tasks too large or too specialised for one agent, when you want separation of concerns, when different sub-tasks need different tools or models.

> Pattern 5 — Tool-Calling Agent (Function Calling)

The simplest pattern: the model picks tools from a registered list, calls them, and uses results to compose a response. No explicit planning step.

┌──────────────────────────────────────────────────────────────────┐
│               TOOL-CALLING AGENT PATTERN                         │
│                                                                  │
│  Available tools: [search, calculator, send_email, read_file]    │
│                                                                  │
│  User: "Email Alice the square root of 144."                     │
│  → Model selects: calculator(expr="sqrt(144)") → 12              │
│  → Model selects: send_email(to="alice", body="Answer: 12")      │
│  → Final: "Done. Emailed Alice with the answer 12."              │
│                                                                  │
│  No explicit thought/observation loop — the model decides        │
│  which tools to call in a single generation step.                │
└──────────────────────────────────────────────────────────────────┘

Best for: simple, well-scoped tasks; low-latency requirements; when you have a known, bounded tool set.

> Pattern 6 — Human-in-the-Loop

The agent pauses at defined checkpoints and waits for human approval before continuing. Critical for high-stakes or irreversible actions.

┌──────────────────────────────────────────────────────────────────┐
│               HUMAN-IN-THE-LOOP PATTERN                          │
│                                                                  │
│  Agent: plan drafted ──► [PAUSE] Human approves ──► Execute       │
│  Agent: SQL ready   ──► [PAUSE] DBA reviews     ──► Run query     │
│  Agent: email draft ──► [PAUSE] User edits      ──► Send         │
│                                                                  │
│  AgentCore supports async pause/resume via session state.        │
│  The agent serialises its state, suspends, and resumes when      │
│  the human response arrives — even hours later.                  │
└──────────────────────────────────────────────────────────────────┘

// Agent vs Workflow — Drawing the Line

This is one of the most common sources of confusion in AI engineering. Both agents and workflows sequence steps, both can call tools, both can involve LLMs. So what is the difference?

┌──────────────────────────────────────────────────────────────────────┐
│                   AGENT vs WORKFLOW                                  │
│                                                                      │
│  DIMENSION          WORKFLOW                  AGENT                  │
│  ─────────────────  ──────────────────────    ─────────────────────  │
│  Control flow       Deterministic (graph)     Dynamic (LLM decides)  │
│  Steps              Fixed at design time      Discovered at runtime  │
│  Branching          Rule-based (if/else)      Model-based reasoning  │
│  State              Usually stateless         Inherently stateful    │
│  Tool selection     Hard-coded                Model selects tools    │
│  Failure mode       Predictable               Emergent / unexpected  │
│  Auditability       High (every step known)   Moderate (inspect trace│
│  Latency            Low (no LLM reasoning)    Higher (LLM per step)  │
│  Best for           Stable, known processes   Ambiguous, open-ended  │
└──────────────────────────────────────────────────────────────────────┘

> The mental model

A workflow is a recipe. An agent is a chef.

The recipe specifies every step in order. The chef uses judgement — reads the ingredients on hand, adapts when something is missing, and decides how to plate the dish.

A workflow is the right choice when:

  • The process is well-defined and rarely changes.
  • Every edge case is enumerable and can be coded as a branch.
  • You need deterministic, auditable behavior (compliance, finance).
  • Latency is critical and you cannot afford an LLM reasoning step per action.

An agent is the right choice when:

  • The task is open-ended or the required steps are not known in advance.
  • The input space is too large to enumerate all branches.
  • Adaptability to new situations is more important than predictability.
  • The task requires synthesising information across many sources in ways that are hard to express as fixed rules.

> A concrete example

Scenario: process a customer refund request.

┌──────────────────────────────────────────────────────────────────┐
│                REFUND — WORKFLOW VS AGENT                        │
│                                                                  │
│  WORKFLOW approach (step function / Airflow)                     │
│  ─────────────────────────────────────────                       │
│  1. Parse order ID from request                                  │
│  2. Check order age (if > 30 days → reject)                      │
│  3. Check item category (if non-returnable → reject)             │
│  4. Issue refund via payments API                                │
│  5. Send confirmation email                                      │
│                                                                  │
│  Fast. Predictable. Auditable. No LLM needed.                    │
│                                                                  │
│  AGENT approach                                                  │
│  ──────────────                                                  │
│  User: "I bought the wrong size and a part arrived broken."      │
│  → Agent reads the policy, determines two issues are in play     │
│  → Calls order lookup tool to get line items                     │
│  → Decides: broken part → full refund, wrong size → exchange     │
│  → Checks inventory for replacement size                         │
│  → Initiates partial refund + exchange order                     │
│  → Drafts a personalised apology email                           │
│                                                                  │
│  Flexible. Handles edge cases. Requires LLM per step.            │
└──────────────────────────────────────────────────────────────────┘

The best production systems often combine both: a workflow orchestrates the high-level stages; an agent handles the stages where human-like reasoning adds value.

// Putting It All Together

Here is how the concepts align inside AgentCore:

┌──────────────────────────────────────────────────────────────────────┐
│              AGENTCORE DEPLOYMENT OVERVIEW                           │
│                                                                      │
│  Your code (any framework)                                           │
│  └─► implement invoke()                                              │
│  └─► containerise                                                    │
│  └─► push to ECR                                                     │
│                    │                                                 │
│                    ▼                                                 │
│         AgentCore Runtime (managed compute)                          │
│              │         │         │         │                         │
│              ▼         ▼         ▼         ▼                         │
│         Memory    Tool Gate  Code Exec  Browser                      │
│         Store     way        Sandbox    Tool                         │
│              │         │         │         │                         │
│              └─────────┴─────────┴─────────┘                         │
│                              │                                       │
│                    Identity + Observability                          │
│                    (IAM, CloudWatch, ADOT)                           │
│                              │                                       │
│                    Multi-agent Collaboration                         │
│                    (supervisor ↔ sub-agents)                         │
└──────────────────────────────────────────────────────────────────────┘

> Key takeaways

  • An agent is any loop that perceives, reasons, acts, and observes — the framework is irrelevant.
  • AgentCore turns that loop into a production service: managed hosting, auto-scaling, built-in memory, tools, identity, and observability.
  • Any agent code plugs in by implementing a single invoke() entry point and packaging it as a container.
  • Choose the right pattern (ReAct, Plan-and-Execute, Reflection, Multi-Agent, Human-in-the-Loop) based on your task's uncertainty and structure.
  • Use a workflow when steps are known; use an agent when steps must be discovered.

The decision between agent and workflow is ultimately a question of how much do you know at design time? The more you know, the more you should encode as a workflow. The more open-ended the task, the more you should trust an agent to navigate it.