Amazon Bedrock Agents in boto3: invoke_agent and create_agent Code, the "Bedrock Agents Is in Maintenance Mode" Error, and the AgentCore Route
To call an Amazon Bedrock agent from Python, use boto3.client("bedrock-agent-runtime").invoke_agent(agentId=..., agentAliasId=..., sessionId=..., inputText=...) and read the answer from the completion event stream, joining each chunk's bytes. Agents are built with a different client, bedrock-agent: create_agent, create_agent_action_group, prepare_agent and create_agent_alias. The 2026 catch: the service is now Bedrock Agents Classic, and since July 30, 2026 it has been in maintenance mode. Existing agents keep working and every API (including invoke_agent) stays available, but accounts with no Bedrock Agents activity in the past 12 months get "AccessDeniedException: Bedrock Agents is in Maintenance Mode" on create_agent and invoke_inline_agent, with no exception process. New features and new models go to Amazon Bedrock AgentCore instead, whose managed harness is the closest replacement. Below: what a Bedrock agent is, complete boto3 code to create, prepare and invoke one, action groups with Lambda, traces and return of control, every common error, and the AgentCore route for new accounts.
Jake followed a year-old tutorial to build an order-tracking agent for the shop, in a brand-new AWS account the team had just set up for AI work. The first call, create_agent, failed with an access error that had nothing to do with IAM. The tutorial was correct when it was written. The account was simply too new for a service that stopped taking new customers in July.
New to agents or Bedrock? The cards below cover what an AI agent is, AgentCore, Bedrock itself, the 2026 retirements and the agent toolkit.
What is a Bedrock agent?
What is a Bedrock agent? It is a managed AI assistant that can do things, not just answer. You give it a model, plain-English instructions, and action groups (functions it may call, backed by Lambda or by your own code), and optionally knowledge bases to search. When a user asks "where is order A-1042?", the agent decides it needs your order lookup, calls it, reads the result and writes the reply. Bedrock runs that loop (it is called orchestration) for you, keeps the conversation per session, and records a trace of every step. Our plain-English guide to AI agents covers the idea in general.
The parts and the boto3 clients that handle them:
- The agent (model, instructions, settings) with a working DRAFT version, managed with
bedrock-agent. - Action groups: a function schema or OpenAPI schema plus a Lambda function (or "return of control" to your app).
- Knowledge bases attached for answering from documents; see our knowledge base guide.
- Aliases: named pointers to a numbered version, which your app calls. The built-in test alias
TSTALIASIDalways points at DRAFT. - Invocation through
bedrock-agent-runtimewithinvoke_agent.
There is no charge for the agent layer itself: you pay for the model tokens the orchestration uses, plus Lambda, knowledge bases and anything else it calls. Agents use noticeably more tokens than a single model call, because each step (planning, calling a tool, reading the result) is a model call of its own.
"Bedrock Agents is in Maintenance Mode": what it means for you
Since July 30, 2026, the original service has been renamed Bedrock Agents Classic and closed to new customers. The rules are per account:
| Your account | What still works | What fails |
|---|---|---|
| Used Bedrock Agents in the past 12 months (allowlisted) | Everything: create, update, prepare, aliases, action groups, invoke_agent, inline agents, CloudFormation and Terraform templates | Nothing, but no new features and no new models after July 30, 2026 |
| No Bedrock Agents activity in the past 12 months (including brand-new accounts) | Read and manage APIs on anything that exists; Bedrock models, knowledge bases and guardrails are unaffected | create_agent and invoke_inline_agent with AccessDeniedException (HTTP 403) |
The exact message is: "Bedrock Agents is in Maintenance Mode. New agent creation is not available for accounts without prior service usage." It is not an IAM problem, so adding permissions does not fix it, and there is no exception or allowlist request. What you can do:
- Check whether another account of yours is allowlisted: the allowlist is per account, so an older account in your organization that ran agents recently can still create them.
- For anything new, build on AgentCore: the managed harness is the configuration-based equivalent (model, tools, instructions), covered below.
- For existing agents, keep running them: there is no end-of-life date and no migration deadline. Plan a move when you next need a new model or feature, since Classic's model list is frozen.
Templates that create agents keep working in allowlisted accounts; in new accounts, switch those resources to AgentCore ones. The API namespaces (bedrock-agent, bedrock-agent-runtime), SDK clients and IAM action prefixes did not change with the new name. Our 2026 retirements roundup lists the other services that moved to maintenance this year.
Jake: "So the tutorial was fine, and my code was fine?"
Ethan: "Both fine. Our old account would have run it. The new one never used agents, so it's locked out of creating them."
Which boto3 client? bedrock-agent vs bedrock-agent-runtime and the rest
Bedrock is split across several boto3 clients, and calling an operation on the wrong one is the most common first error ("object has no attribute invoke_agent"). The map:
| Client name | What it does | Typical calls |
|---|---|---|
bedrock | Manage models and settings | list_foundation_models, inference profiles, guardrails |
bedrock-runtime | Call models directly | converse, invoke_model |
bedrock-agent | Build agents and knowledge bases (build time) | create_agent, create_agent_action_group, prepare_agent, create_agent_alias, create_knowledge_base |
bedrock-agent-runtime | Use agents and knowledge bases (run time) | invoke_agent, invoke_inline_agent, retrieve, retrieve_and_generate |
bedrock-agentcore-control, bedrock-agentcore | AgentCore, the newer agent platform | Runtime, Memory, Gateway and Identity operations |
The pattern is consistent: the plain name builds and configures, the -runtime name uses what you built. Creating an agent is bedrock-agent; talking to it is bedrock-agent-runtime. Both need a Region, and the IAM actions follow the same split (bedrock:CreateAgent versus bedrock:InvokeAgent). If you only want a model to answer questions, you need neither agent client; the Converse API on bedrock-runtime is simpler.
How a Bedrock agent runs a request
Understanding the loop explains both the agent's behavior and its cost. Each invoke_agent call goes through up to three stages:
- Pre-processing: the model checks and categorizes the user's input, which can reject harmful or off-topic requests before any work happens.
- Orchestration: a loop. The model writes a rationale for its next step, picks an action from an action group or decides to query a knowledge base, the action runs (through your Lambda function or by returning control to your app), and the result, called an observation, goes back to the model. The loop repeats until the model can answer or needs more information from the user.
- Post-processing: an optional final formatting step, off by default.
Each stage uses a prompt template. There are four base templates (pre-processing, orchestration, knowledge base response generation and post-processing), which you can view and override with advanced prompts to add rules or examples, or to turn a step off. The practical consequence: a single user question can mean several model calls, one per orchestration step plus pre-processing, so an agent costs and takes more than one direct model call. Simple requests that do not need tools are cheaper through converse.
Jake: "The agent took eight seconds to say our shop opens at nine."
Ethan: "Four model calls for a fact in the system prompt. Answer the easy questions without the agent."
invoke_agent: call an existing agent from Python
If you have an agent (yours, or one your account already runs), this is the call your app makes. The answer comes back as an event stream:
import uuid
import boto3
runtime = boto3.client("bedrock-agent-runtime", region_name="us-east-1")
session_id = str(uuid.uuid4()) # one per conversation; reuse it for follow-ups
response = runtime.invoke_agent(
agentId="AGENT12345",
agentAliasId="ALIAS67890", # or "TSTALIASID" to test the DRAFT version
sessionId=session_id,
inputText="Where is order A-1042?",
enableTrace=False,
)
answer = ""
for event in response["completion"]:
if "chunk" in event:
answer += event["chunk"]["bytes"].decode("utf-8")
print(answer)
What each part does for you:
sessionId: you choose it (letters, numbers, dots, hyphens, underscores and colons). The agent remembers the conversation for that ID until the session's idle timeout; sendendSession=Trueto close it early.agentAliasId: your app should call an alias that points at a tested version;TSTALIASIDis for testing the DRAFT while you build.sessionState: passsessionAttributes(values your action groups receive, such as the logged-in customer's ID) andpromptSessionAttributes(values added to the prompt, such as today's date) without putting them in the user's text.enableTrace=True: addstraceevents showing each step; see traces.
response = runtime.invoke_agent(
agentId="AGENT12345", agentAliasId="ALIAS67890", sessionId=session_id,
inputText="And when will it arrive?",
sessionState={"sessionAttributes": {"customerId": "C-778"},
"promptSessionAttributes": {"today": "2026-10-20"}},
)
The event stream must be read to the end; an exception inside it (for example a throttling or dependency failure) surfaces while you iterate, so wrap the loop, not just the call, in your error handling.
Create an agent with boto3 (allowlisted accounts)
In an account that can still create Classic agents, the build sequence is the same as before. Each step uses the bedrock-agent client:
- Create a service role the agent assumes, trusted by
bedrock.amazonaws.comand allowedbedrock:InvokeModelon the model (and inference profile) you choose. - Create the agent with a model, instructions and that role.
- Add action groups (next section) and knowledge bases.
- Prepare the agent: this builds the DRAFT so it can be tested; run it after every change.
- Create an alias, which snapshots a numbered version for your app to call.
import time
import boto3
agents = boto3.client("bedrock-agent", region_name="us-east-1")
agent = agents.create_agent(
agentName="shop-order-helper",
foundationModel="us.amazon.nova-pro-v1:0",
instruction=("You help customers of an online shop track orders and understand delivery times. "
"Always look up the order before answering, and never guess a delivery date."),
agentResourceRoleArn="arn:aws:iam::111122223333:role/AmazonBedrockExecutionRoleForAgents_shop",
idleSessionTTLInSeconds=900,
)["agent"]
agent_id = agent["agentId"]
while agents.get_agent(agentId=agent_id)["agent"]["agentStatus"] == "CREATING":
time.sleep(3)
# ... add action groups here, then:
agents.prepare_agent(agentId=agent_id)
while agents.get_agent(agentId=agent_id)["agent"]["agentStatus"] != "PREPARED":
time.sleep(3)
alias = agents.create_agent_alias(agentId=agent_id, agentAliasName="live")["agentAlias"]
print(agent_id, alias["agentAliasId"])
The instruction must be at least 40 characters, and it is worth writing carefully: it is the agent's whole job description. The create call needs iam:PassRole on the service role for whoever runs it; our PassRole guide explains that error.
Action groups: let the agent call your Lambda function
An action group tells the agent what it can do. The simplest form is a function schema: names, descriptions and parameters, which the model reads to decide when to call each one.
agents.create_agent_action_group(
agentId=agent_id, agentVersion="DRAFT",
actionGroupName="orders",
actionGroupExecutor={"lambda": "arn:aws:lambda:us-east-1:111122223333:function:order-status"},
functionSchema={"functions": [{
"name": "get_order_status",
"description": "Get the delivery status and expected date for an order ID such as A-1042.",
"parameters": {"order_id": {"type": "string", "description": "The order ID", "required": True}},
}]},
)
The Lambda function receives the function name and parameters, and must answer in the agent's response format:
def handler(event, context):
params = {p["name"]: p["value"] for p in event.get("parameters", [])}
status = lookup_order(params["order_id"]) # your own code
return {
"messageVersion": "1.0",
"response": {
"actionGroup": event["actionGroup"],
"function": event["function"],
"functionResponse": {"responseBody": {"TEXT": {"body": status}}},
},
}
Two permission steps people miss:
- Let Bedrock invoke the function:
aws lambda add-permission --function-name order-status --statement-id bedrock-agent --action lambda:InvokeFunction --principal bedrock.amazonaws.com --source-arn arn:aws:bedrock:us-east-1:111122223333:agent/AGENT12345. Without it, the agent fails with a dependency error when it tries the tool. - The function's own role needs whatever it touches (DynamoDB, an API key in Secrets Manager); if it cannot start at all, our Lambda role guide covers the trust policy.
Instead of Lambda, an action group can use actionGroupExecutor={"customControl": "RETURN_CONTROL"}: the agent then pauses and sends a returnControl event to your app with the function and parameters; your app runs it (useful when the action needs the user's own session or approval) and sends the result back through sessionState on the next invoke_agent call.
Remember to run prepare_agent after adding or changing an action group, then test through TSTALIASID; aliases keep pointing at their old version until you update them.
Jake: "It called my Lambda, but the agent said it couldn't get the status."
Ethan: "Your function returned a plain string. The agent needs the messageVersion and functionResponse wrapper, or it can't read the answer."
Agent versions and aliases (and the TSTALIASID test alias)
Agents have a draft and numbered versions, and your code calls them through an alias:
- Draft: what you edit. After any change, call
prepare_agentso the draft is packaged and testable. - Test alias: every agent has a built-in alias with the ID
TSTALIASIDthat points at the draft, for trying changes in the console or code. - Versions: creating an alias (
create_agent_alias) snapshots the current draft as a numbered, unchangeable version and points the alias at it. - Production alias: your application should call a named alias such as
prod, never the test alias, so edits to the draft cannot change live behavior.
To release a change: edit the draft, prepare it, test it through TSTALIASID, then create a new version and point the production alias at it with update_agent_alias. To roll back, point the alias at the previous version; the application keeps the same alias ID throughout, so no code change or deploy is needed.
Agents with knowledge bases
An agent can have one or more knowledge bases attached (associate_agent_knowledge_base on the bedrock-agent client), and during orchestration it decides when to search them. That decision is driven by the knowledge base description you give when attaching it, so write it like an instruction: "Use for questions about return policy, shipping times and warranty terms." A vague description means the agent either never searches or searches for everything.
Use an agent with a knowledge base when answers need both documents and actions, such as "check whether this order can still be returned, and if so start the return". For pure question-answering over documents, calling retrieve_and_generate directly is simpler, faster and cheaper, with no orchestration loop; our knowledge base guide covers that route and its costs.
Return of control: let your app run the action
Instead of a Lambda function, an action group can return control to your application: the agent decides which action to take and with which parameters, then hands that decision back in the invoke_agent response, and your code runs it. This suits actions that must run inside your own system (a call to an internal API, something that needs the user's session), or that need human confirmation first.
resp = runtime.invoke_agent(agentId=AGENT_ID, agentAliasId=ALIAS_ID,
sessionId=session_id, inputText="Cancel order 10442")
for event in resp["completion"]:
if "returnControl" in event:
rc = event["returnControl"]
# rc["invocationInputs"] describes the action and its parameters; run it yourself
results = run_my_action(rc["invocationInputs"])
follow = runtime.invoke_agent(agentId=AGENT_ID, agentAliasId=ALIAS_ID, sessionId=session_id,
sessionState={"invocationId": rc["invocationId"],
"returnControlInvocationResults": results})
The results you send back list each action's outcome, in the shape of the action group (an API result or a function result) with a response body the model can read, so keep them short and factual, such as "Order 10442 canceled, refund of $48 issued". Set this up by choosing "return control" as the action group's executor when you create it. The agent still plans the steps; your code keeps full control over what actually happens, and nothing runs that your application did not approve.
Sessions, session attributes and memory
Conversation context lives in the session: reuse the same sessionId across invoke_agent calls and the agent remembers earlier turns; use a new ID for a new conversation, and pass endSession=True when one is over. Two kinds of attributes let you pass facts the user should not have to repeat:
- sessionAttributes: values sent to your action group's Lambda function on every call in the session, such as the signed-in customer's ID, so the function knows who it is acting for.
- promptSessionAttributes: values added to the prompt for the model, such as today's date or the customer's country, so its answers fit the context.
Take identity information from your own sign-in system, not from what the user typed into the chat, and pass it as a session attribute; a user can claim to be anyone in a message. Agents can also keep a memory across sessions, so a returning user does not have to start from scratch; turn it on only where storing conversation summaries fits your privacy rules.
Traces: see what the agent did
When an agent gives a strange answer, the trace shows why. With enableTrace=True, the stream carries trace events alongside the chunks:
for event in response["completion"]:
if "trace" in event:
step = event["trace"]["trace"]
if "orchestrationTrace" in step:
orch = step["orchestrationTrace"]
if "rationale" in orch:
print("THINKING:", orch["rationale"]["text"])
if "invocationInput" in orch:
print("CALLING:", orch["invocationInput"].get("actionGroupInvocationInput", {}).get("function"))
if "observation" in orch:
print("RESULT:", orch["observation"].get("type"))
elif "chunk" in event:
print(event["chunk"]["bytes"].decode("utf-8"), end="")
Read it in order: the rationale (why it chose a step), the invocation input (which tool and parameters), the observation (what came back), and the final response. Wrong parameters usually mean the function description is vague; a missing tool call usually means the instruction does not tell the agent when to use it. The trace also shows token usage per step, which is how you find out why one conversation cost ten times another.
Traces are large, so keep them on while developing and testing, and in production log them only for a sample of requests or for failures. They contain the full prompts, including your instructions and whatever the user typed, so store them where only the team that maintains the agent can read them. A simple habit that pays off: when a user reports a bad answer, save the session ID with the report, so you can find the matching trace instead of trying to reproduce the conversation.
Bedrock Agents Classic vs AgentCore
The question "Bedrock Agents vs AgentCore" now has a practical answer: Classic for agents you already run, AgentCore for everything new. How the pieces map:
| Bedrock Agents Classic | AgentCore equivalent |
|---|---|
| Managed orchestration loop | The managed harness |
| Action groups (function or OpenAPI schema + Lambda) | Tools through AgentCore Gateway, exposed as MCP tools over REST APIs, Lambda or code |
| Knowledge bases attached to the agent | Knowledge bases through Gateway or a retrieval tool |
| Session memory settings | AgentCore Memory, short and long term, per user (actor) |
| Return of control | Inline function tools: the harness pauses and returns the tool call |
| Code interpreter action group | AgentCore Code Interpreter |
| Trace UI and APIs | End-to-end tracing of every action |
| Stage-specific prompt overrides | Only a system prompt in the harness; stage overrides need your own code |
| Multi-agent collaboration (supervisor and routing) | Limited in the harness (agent-as-tool); full patterns need a code-defined agent |
| Model catalog frozen at July 30, 2026 | The full Bedrock catalog plus other OpenAI-compatible providers |
The AgentCore route for new accounts
AgentCore has two paths. The managed harness is the closest thing to Classic: you declare the model, tools and system prompt, and AgentCore runs the loop, compute, memory, identity and tracing. Code-defined agents let you bring a framework (Strands, LangChain, the OpenAI Agents SDK or your own loop) and run it on AgentCore Runtime. Start with the harness unless you need multi-agent routing or custom orchestration. The shop's order helper, with the AgentCore CLI:
agentcore create --name shop-order-helper agentcore add harness --name shop-order-helper \ --model-id us.amazon.nova-pro-v1:0 \ --system-prompt "You help customers track orders. Always look up the order before answering." agentcore add tool --harness shop-order-helper --type agentcore_gateway --name orders \ --gateway-arn arn:aws:bedrock-agentcore:us-east-1:111122223333:gateway/shop-orders agentcore deploy agentcore invoke --harness shop-order-helper --session-id "$(uuidgen)" --actor-id C-778 "Where is order A-1042?"
The --actor-id gives each customer their own memory. Your existing Lambda function can sit behind an AgentCore Gateway as an MCP tool, so the order lookup code does not have to change. If you are migrating a Classic agent, the AgentCore CLI can import its configuration, and the agent toolkit for AWS has an amazon-bedrock skill that inventories the agent, checks eligibility and walks a coding assistant through the move; our agent toolkit install guide covers setting it up.
From Python, an agent deployed on AgentCore Runtime is called through the bedrock-agentcore client:
import json, uuid, boto3
core = boto3.client("bedrock-agentcore", region_name="us-east-1")
response = core.invoke_agent_runtime(
agentRuntimeArn="arn:aws:bedrock-agentcore:us-east-1:111122223333:runtime/shop_order_helper-AbC123",
runtimeSessionId=str(uuid.uuid4()) + "-session", # at least 33 characters
payload=json.JSONEncoder().encode({"prompt": "Where is order A-1042?"}).encode("utf-8"),
)
print(response["response"].read().decode("utf-8"))
AgentCore is billed by consumption across runtime, memory and gateway, with no separate orchestration charge, plus the model tokens. Our AgentCore explainer covers its other parts (Identity, Browser, Observability) in plain English.
Jake: "So I keep my Lambda, swap create_agent for a harness, and the customer memory comes for free?"
Ethan: "That's the deal. And next year's models will show up there, not in Classic."
Do you need an agent at all? Agents vs Converse tool use
Many projects that start with Bedrock Agents only need a model that can call a few functions, and the Converse API does that directly: you pass toolConfig, the model asks for a tool, your code runs it and sends the result back. The difference is who runs the loop.
| Converse with tools | Bedrock Agents | |
|---|---|---|
| Who runs the loop | Your code | The managed agent |
| Conversation history | You keep and send it | Kept per session for you |
| Knowledge bases | Call retrieve as a tool | Attached and queried automatically |
| Model calls per request | As few as you design | Several (pre-processing plus orchestration steps) |
| Availability | Every account, every Converse model with tools | Existing customers only (Classic) |
For a handful of tools and a chat interface, a Converse loop of 30 lines is cheaper, faster and fully under your control; our Converse guide shows one. Managed agents earn their place when you want sessions, knowledge bases and tracing handled for you, or when non-developers configure the agent in the console.
Inline agents: configure the agent per request
Existing customers can also call invoke_inline_agent on the bedrock-agent-runtime client, which takes the agent's definition (model, instructions, action groups, knowledge bases) in the request itself instead of a saved agent ID. That suits applications that build a different agent per user or per tenant, such as giving each customer access only to their own tools, without creating and preparing hundreds of saved agents. The trade-off is that there is no version or alias history, so your code becomes the place where agent definitions are versioned and reviewed. Keep the definitions in configuration files under source control, test them like any other code, and log which definition served each session so that a bad answer can be traced back to the exact setup that produced it.
Example: designing a shop support agent
A worked design shows how the pieces fit. Jake's shop wants an agent that answers order questions and can start returns:
- Instructions: "You help customers of an online clothing shop with orders and returns. Always confirm the order number before acting. Start a return only for orders delivered within 30 days. Make no refund promises; say the refund follows inspection." Short, specific, and with the business rules spelled out.
- Action group with three functions:
get_order(order_id),start_return(order_id, reason)andget_return_status(return_id), each with a one-line description of what it returns and when to use it. - Knowledge base with the returns policy, size guides and delivery FAQ, described as "Use for questions about policies, sizing and delivery times."
- Session attributes carrying the signed-in customer's ID, so
get_ordercan refuse orders that belong to someone else. - A guardrail blocking topics outside the shop and masking card numbers.
- A production alias pointing at a tested version, and a test set of 40 real customer messages run before every release.
Notice what is not in the design: the agent never sees payment systems, and every action checks the customer ID itself rather than trusting the model. Agents are good at choosing what to do; your functions should still decide what is allowed.
The same design moves almost unchanged to AgentCore later: the instructions become the system prompt of your agent code, the three functions become tools, the knowledge base stays as it is, and the session attributes become values your code passes in. Designing the tools and rules carefully now is work that survives any platform change, and so does the test set of real customer messages you collected along the way.
Jake: "Can the agent just issue refunds directly?"
Ethan: "Let it start the return. A person or a rule in your code approves the money."
IAM for agents: the service role and the Lambda permission
Two permissions trip up most first agents, and both are easy once you know them. The agent itself runs with a service role that Bedrock assumes: its trust policy allows bedrock.amazonaws.com (ideally with conditions on your account and the agent's ARN), and its permissions allow invoking the chosen model (or inference profile) and, if attached, retrieving from the knowledge base. The console creates this role for you; with boto3 you pass its ARN as agentResourceRoleArn when calling create_agent.
Separately, each action group's Lambda function needs a resource-based policy that lets Bedrock invoke it: a permission for the principal bedrock.amazonaws.com with the agent's ARN as the source ARN. Without it, the agent plans the action correctly and then fails with an access error when it tries to run it. The caller of invoke_agent needs only bedrock:InvokeAgent on the agent alias, so a web backend can talk to the agent without any build permissions.
Testing and improving an agent
- Write 30 to 50 real requests with the answer or action you expect, covering easy questions, multi-step tasks and requests the agent should refuse.
- Run them through the test alias with traces on, and read where the agent chose the wrong action, skipped the knowledge base or asked for information it already had.
- Fix the cheapest thing first: clearer instructions, better action and parameter descriptions, a sharper knowledge base description. Advanced prompts come last.
- Attach a guardrail to the agent for content filters and denied topics, so safety does not depend on the instructions alone.
- Re-run the whole set after every change and compare, since fixing one case often breaks another.
- Release through a new version and alias update only when the set passes.
Jake: "Fixing the refund question broke the shipping one."
Ethan: "That's why the test set exists. Run all fifty after every change, not just the one you fixed."
What a Bedrock agent costs to run
An agent's bill comes from what it uses on each request. The main drivers:
- Model tokens for every step: pre-processing, each orchestration step and any post-processing are separate model calls, each sending the instructions, tool descriptions and conversation history again. A three-step request can use several times the tokens of a direct answer.
- Knowledge base queries: retrieval from the vector store, plus the model tokens for the retrieved text.
- Lambda invocations for action groups, and whatever those functions call.
- Logs and traces stored in CloudWatch if you keep them.
Ways to cut it: use a smaller, cheaper model where it handles the orchestration well; keep instructions and action descriptions short; turn off pre-processing if you validate input yourself; limit the number of knowledge base results; trim long sessions; and route simple questions around the agent entirely. Check the Bedrock pricing page for your model and Region, and watch the token counts in traces during testing to estimate cost per conversation before launch.
A simple estimate before launch: take ten typical conversations from your test set, add up the input and output tokens shown in their traces, divide by ten for an average, and multiply by your expected monthly conversations and the model's per-token prices. Add the knowledge base and Lambda costs on top. If the number surprises you, the traces also show which step spends the most, which is usually long instructions repeated in every orchestration step or a knowledge base returning too many results. Set a monthly budget alert in AWS Budgets for the account as well, since agent traffic can grow faster than expected once customers find it useful.
Multi-agent collaboration
Classic Bedrock Agents can also work as a team: a supervisor agent receives the user's request and routes parts of it to collaborator agents, each with its own instructions, actions and knowledge bases, such as one for orders and one for product questions. It keeps each agent focused and easier to test. The trade-off is more model calls per request, since the supervisor reasons about routing before the collaborators work, so reserve it for requests that really span several areas. A supervisor can also run in a simpler routing mode that sends a request straight to the single best collaborator when one is clearly right, which saves the extra reasoning for requests that need several agents. Give each collaborator a clear, narrow description, since that is what the supervisor routes on, the same way an agent picks a knowledge base by its description.
Moving from Bedrock Agents Classic to AgentCore
Existing agents keep working, but new accounts cannot create Classic agents, and new features arrive in AgentCore. If you plan a move, the pieces map across roughly like this:
- The orchestration loop becomes your own agent code (with a framework such as Strands Agents or LangGraph) running on AgentCore Runtime.
- Action groups become tools, either in your code or exposed through AgentCore Gateway, which can turn existing APIs and Lambda functions into MCP tools.
- Knowledge bases stay where they are; your agent calls
retrieveas a tool. - Sessions and memory map to AgentCore Memory.
- Aliases and versions become your normal deployment process for the agent code.
The gain is control and model choice; the cost is that you now own the loop that Classic ran for you. Our AgentCore explainer covers the platform in plain English.
Jake: "Do we have to migrate our support agent right away?"
Ethan: "No, it still runs. Plan the move for the next big change, not as an emergency."
Errors and fixes
AccessDeniedException: Bedrock Agents is in Maintenance Mode...oncreate_agentorinvoke_inline_agent: the account has no Bedrock Agents activity in the past 12 months. Use an allowlisted account or AgentCore; IAM changes will not help.ResourceNotFoundExceptionfrominvoke_agent: wrong agent or alias ID, or the client is in a different Region from the agent.DependencyFailedException: a Lambda action group failed, timed out, returned the wrong format, or Bedrock lacks permission to invoke it (theadd-permissionstep). The function's CloudWatch logs say which.- "Access denied when calling Bedrock" inside the agent: the agent's service role cannot invoke the model or its inference profile; add
bedrock:InvokeModelon both. - "on-demand throughput isn't supported": the agent's
foundationModelis a bare model ID for a model that needs an inference profile; our on-demand throughput guide explains it. - Changes do not show up: you forgot
prepare_agent, or you are calling an alias that still points at an older version. ThrottlingException: agents make several model calls per question, so they hit tokens-per-minute quotas sooner than single calls; retry with backoff or request more quota.ValidationExceptionon create: an instruction shorter than 40 characters, or an invalid agent name.
For catching these by error code in Python, our boto3 ClientError guide shows the pattern.
Frequently asked questions
Will my Bedrock agent design work on AgentCore later?
Mostly yes: instructions become your agent's system prompt, action group functions become tools, knowledge bases stay as they are, and session attributes become values your code passes in.
How do I roll back a Bedrock agent change?
Point the production alias back at the previous version with update_agent_alias; the alias ID your application uses does not change.
How do I estimate a Bedrock agent's monthly cost?
Average the tokens of ten test conversations from their traces, multiply by expected conversations and the model's prices, then add knowledge base and Lambda costs.
Should a Bedrock agent be allowed to issue refunds?
Let it start actions like returns, but keep money movements behind a rule in your code or a human approval.
Do I need Bedrock Agents for tool calling?
No. The Converse API's toolConfig lets any supported model call your functions in a loop you control; agents add managed sessions, knowledge bases and tracing.
What is invoke_inline_agent?
A bedrock-agent-runtime call that defines the agent's model, instructions and tools in the request itself, without a saved agent, for per-user or per-tenant agents.
Why does my Bedrock agent fail when calling its Lambda function?
The function needs a resource-based policy allowing bedrock.amazonaws.com to invoke it, with the agent's ARN as the source ARN.
What IAM role does a Bedrock agent need?
A service role trusted by bedrock.amazonaws.com with permission to invoke its model or inference profile and to retrieve from attached knowledge bases.
How do I test a Bedrock agent?
Run a set of 30-50 real requests through the TSTALIASID test alias with traces on, fix descriptions and instructions, and re-run the whole set after each change.
Should I keep agent traces on in production?
Only for a sample of requests or for failures; traces are large and contain full prompts, so store them securely.
What is TSTALIASID in Bedrock Agents?
The built-in test alias that points at the agent's draft; production code should call a named alias pointing at a numbered version.
How much do Bedrock agents cost?
You pay for what the agent uses: model tokens for every orchestration step, knowledge base queries and Lambda invocations; check the Bedrock pricing page for your model.
What is return of control in Bedrock Agents?
An action group setting where the agent returns the chosen action and parameters to your application, which runs it and sends the results back.
How does a Bedrock agent decide to use a knowledge base?
From the description you give when attaching it; write it as an instruction saying which questions it answers.
Is Bedrock Agents deprecated?
Bedrock Agents Classic is in maintenance mode: closed to new customers, still working for existing ones; AgentCore is the path for new agents.
Can Bedrock agents work together?
Yes, with multi-agent collaboration: a supervisor agent routes parts of a request to collaborator agents.
How do I pass the user's ID to a Bedrock agent action?
Send it as a sessionAttributes value from your own sign-in system; the action group's Lambda function receives it on every call.
What is a Bedrock agent?
A managed AI assistant on Amazon Bedrock that uses a model, instructions, action groups and knowledge bases to complete tasks, not just answer questions.
How do I invoke a Bedrock agent with boto3?
Call bedrock-agent-runtime invoke_agent with agentId, agentAliasId, sessionId and inputText, then join the chunk bytes from the completion stream.
Is Amazon Bedrock Agents deprecated?
It is now Bedrock Agents Classic and in maintenance mode since July 30, 2026: closed to new customers, no new features, but existing agents keep working with no end-of-life date.
What does "Bedrock Agents is in Maintenance Mode" mean?
Your account has no Bedrock Agents activity in the past 12 months, so create_agent and invoke_inline_agent are blocked; use AgentCore instead.
Can I request access to Bedrock Agents Classic for a new account?
No. There is no exception process; the allowlist is based on each account's activity in the past 12 months.
Does invoke_agent still work after July 30, 2026?
Yes. invoke_agent and the other management APIs remain available for existing agents.
What replaces Bedrock Agents?
Amazon Bedrock AgentCore: the managed harness for configuration-based agents, or code-defined agents on AgentCore Runtime.
How do I create a Bedrock agent with boto3?
In an allowlisted account: bedrock-agent create_agent, create_agent_action_group, prepare_agent, then create_agent_alias.
What is TSTALIASID?
The built-in test alias that always points at the agent's DRAFT version; use it while building.
What is the difference between bedrock-agent and bedrock-agent-runtime?
bedrock-agent builds and manages agents and knowledge bases; bedrock-agent-runtime invokes them and queries knowledge bases.
How does an agent call a Lambda function?
Through an action group whose executor is the function's ARN; Bedrock needs lambda:InvokeFunction permission on it, and the function must return the agent response format.
What is return of control in Bedrock agents?
An action group mode where the agent pauses and hands the function call to your app, which runs it and sends the result back.
How do I see what a Bedrock agent is doing?
Set enableTrace=True and read the trace events: rationale, tool calls, observations and token usage per step.
Do Bedrock agents cost extra?
No charge for the agent itself; you pay for model tokens, Lambda and other resources it uses.
Will new models be added to Bedrock Agents Classic?
No. Its model catalog is frozen as of July 30, 2026; new models arrive through AgentCore.
How do I call an AgentCore agent from Python?
Use the bedrock-agentcore client's invoke_agent_runtime with the runtime ARN, a session ID of at least 33 characters and a JSON payload.
Can I migrate a Bedrock agent to AgentCore automatically?
The AgentCore CLI can import Classic configurations, and the agent toolkit for AWS has a skill that guides the migration.
Do my knowledge bases and guardrails still work?
Yes. Maintenance mode only affects the Agents Classic orchestration layer, not models, knowledge bases or guardrails.
For readers preparing for an AWS certification
We have been covering AWS certifications alongside our fixes, so here is a short extra for readers studying for one. If you only came for the fix, you already have it; feel free to skip this part.
Exams that test this topic: AI Practitioner (AIF-C01) • AI Business Strategist (AIB-C01) • Developer – Associate (DVA-C03 from December 1, 2026).
Here are the exam-style questions this topic tends to raise, with the reasoning you need to answer them:
1. What lets a generative AI application take actions such as looking up an order, not just answer?
An agent with tools (action groups or function calling).
2. Which AWS service is the platform for building and running new AI agents in 2026?
Amazon Bedrock AgentCore.
3. A Bedrock agent must call business logic in AWS Lambda. What must allow the call?
A resource-based permission on the function for bedrock.amazonaws.com (lambda:InvokeFunction).
4. How can a developer see each reasoning and tool step an agent took?
Enable tracing and read the trace events.
5. An agent should pause and let the application run an action itself. What pattern is this?
Return of control (inline function tools in AgentCore).
6. Where do Bedrock agents get answers from company documents?
An attached knowledge base (retrieval-augmented generation).
Exam codes and dates change often. Our AWS certification changes page and our guide to the AI Business Strategist exam keep track of what is current.
The order helper now runs on the AgentCore harness in the new account, with the same order-status Lambda behind a gateway and per-customer memory. The team's older account still runs a Classic agent for internal stock questions, called with the same invoke_agent code as before; Ethan has a note to move it when the next model upgrade is wanted.
📌 If you keep one line from this page
Existing Bedrock agents keep working with bedrock-agent-runtime invoke_agent, but Bedrock Agents Classic has been closed to new accounts since July 30, 2026; if create_agent says "Maintenance Mode", build the agent on the AgentCore harness instead.
prepare_agent after changes · TSTALIASID for testing · enableTrace to debug.
Revision note. Written October 20, 2026, under the Agents Classic maintenance-mode rules in effect since July 30, 2026.