Agents Build
AWSOfficialCreated by aws-agentcore
- Skill
- Workflow
- Cloud and DevOps
- Apache-2.0
- Low risk
- Has scripts
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
The agents-build skill provides a structured workflow for adding advanced features to existing AgentCore projects. It acts as a central hub for configuring infrastructure and functional capabilities, such as cross-session memory, VPC connectivity, multi-agent delegation, and sandboxed code execution. The skill ensures project integrity by verifying the environment, checking for existing project configurations, and guiding the user through the appropriate implementation path based on their specific requirements.
What it does
- Adds cross-session memory to maintain user context.
- Configures VPC networking for secure access to private resources.
- Enables multi-agent systems with orchestrator-specialist patterns.
- Integrates browser and code interpreter tools for enhanced agent capabilities.
- Facilitates the migration of existing Bedrock Agents to AgentCore.
- Handles resource removal and project teardown.
When to use it
- When you need to expand an existing agent's functionality.
- When setting up private network connectivity for your agent.
- When transitioning from a single-agent to a multi-agent architecture.
- When you need to add sandboxed code execution or web browsing capabilities.
- When you need to clean up or remove specific agent resources.
Advantages
- Provides a consistent, guided workflow for complex configuration tasks.
- Prevents common errors by validating project context and naming conventions.
- Reduces manual setup time for infrastructure-heavy features like VPCs.
- Centralizes documentation and implementation steps for diverse agent capabilities.
Usage examples
- “add memory to my agent”
- The skill reads the project configuration and provides the necessary steps to implement cross-session memory storage.
- “I need to add a code interpreter to my agent”
- The skill guides you through the integration of the AgentCore Code Interpreter tool for sandboxed Python or JS execution.
- “how do I set up VPC connectivity?”
- The skill loads the VPC reference documentation and walks you through configuring subnets and security groups for your agent.
- “tear down my agent”
- The skill initiates the resource removal workflow to safely destroy the specified agent deployment.
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/aws/agents-build/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip agents-build.zip -d .agents/skills
Documentation by aws-agentcore
build
Add capabilities to your AgentCore agent project.
When to use
Adding cross-session memory to your agent
Calling your deployed agent from a web app, mobile app, or backend service
Configuring VPC networking for private resources (RDS, internal APIs)
Building multi-agent systems with orchestrator/specialist patterns
Migrating an existing Bedrock Agent to AgentCore
Adding the Browser tool so the agent can navigate websites
Adding the Code Interpreter so the agent can execute code in a sandbox
Adding AgentCore Payments so the agent can pay for x402- or MPP-protected APIs, tools, or content
Removing resources from your project or tearing down a deployment
Do NOT use for:
Connecting to external tools/APIs via Gateway (OpenAPI specs, Lambda, MCP servers, credentials, policies) → use
agents-connectScaffolding a new project → use
agents-get-startedDeploying → use
agents-deploy
Input
$ARGUMENTS can be:
A capability: "memory", "integrate", "vpc", "multi-agent", "migrate", "browser", "code-interpreter", "payments", "teardown"
A description of what they want: "remember user preferences", "call from React app", "scrape a website", "run pandas in the agent", "delete my agent", "clean up resources"
Empty — the skill will determine the workflow from context
Process
Step 0: Verify CLI version
Run agentcore --version. This skill requires v0.9.0 or later.
If older: "Run agentcore update to get the latest version."
Step 1: Read project context
Read agentcore/agentcore.json to understand the current project — framework, existing resources, agent configuration.
If agentcore/agentcore.json is not found:
Check if the developer is in the wrong directory. Look for
agentcore/agentcore.jsonin parent directories (up to 3 levels). If found, tell them: "Found an AgentCore project at<path>. Are you working in that project?"If no project exists anywhere nearby, ask what capability they wanted to add. Then offer two paths:
"I can walk you through creating a project first and then adding CAPABILITY — want to do that?" (run the get-started flow inline, then continue with the build workflow)
"If you already have a project elsewhere,
cdinto it and try again."
Do not just say "go use agents-get-started" and stop — that loses the developer's context about what they actually wanted to do.
Step 2: Determine the workflow
Important disambiguation — before routing to a build reference, check if the prompt is actually a connect or debug concern:
If the phrase mentions external APIs, Lambda functions, OpenAPI specs, gateways, credentials, MCP servers, or policies → this is
agents-connect, not buildIf the developer says something is broken (wrong answers, errors, tool failures) → this is
agents-debug, not buildBuild is for adding new capabilities to a working project, not fixing broken ones
Based on the developer's prompt and $ARGUMENTS, load the appropriate reference:
| Developer intent | Reference to load |
|---|---|
| Add memory, remember things, user preferences, cross-session | references/memory.md |
| Call agent from app, invoke from code, streaming, SDK client, agent URL, execute shell in session | references/integrate.md |
| VPC, private network, RDS, internal API, subnet, security group | references/vpc.md |
| Multi-agent, orchestrator, specialist, A2A, delegation, agent handoff | references/multi-agent.md |
| Custom headers from caller to agent, header allowlist, tenant ID/correlation ID/trace propagation | references/request-headers.md |
| Migrate Bedrock Agent, import agent, move to AgentCore | references/migrate.md |
| Browser tool, web navigation, form filling, scraping, Nova Act, Playwright, live view | references/browser.md |
| Code Interpreter, execute code, sandbox, run Python/JS/TS, data analysis in agent, pandas | references/code-interpreter.md |
| Payments, pay for x402 or MPP content, 402 Payment Required, Machine Payments Protocol, WWW-Authenticate: Payment, microtransactions, paid API/tool, payment manager/connector | references/payments.md |
| Delete agent, remove resource, tear down, clean up, destroy, start fresh | references/teardown.md |
| Change model, switch model, use Haiku/Sonnet/Nova, different model | Inline — see "Changing the model" below |
If the developer asks about the difference between local dev and deployed (e.g., "why does my memory work after deploy but not locally?"), load references/local-vs-deployed.md alongside the specific workflow reference.
Read the matching file into context and follow its Process section step by step — do not summarize.
If the intent is ambiguous, ask the developer which capability they want to add.
Changing the model
The model is configured in app/<AgentName>/model/load.py (scaffolded by agentcore create). To change it:
Open
app/<AgentName>/model/load.pyChange the
model_idparameter in theBedrockModel()constructor
# Default (scaffolded by CLI)
return BedrockModel(model_id="global.anthropic.claude-sonnet-4-5-20250929-v1:0")
# Switch to Haiku for cost savings
return BedrockModel(model_id="us.anthropic.claude-3-5-haiku-20241022-v1:0")
# Switch to Nova Lite
return BedrockModel(model_id="amazon.nova-lite-v1:0")Cross-region inference profile prefixes (us., eu., apac., global.) control where inference runs. Use global. for maximum throughput, or a geographic prefix for data residency. Not all models support all prefixes — check the Bedrock inference profiles docs.
After changing the model:
Verify the model is enabled in your region: AWS Console → Amazon Bedrock → Model access
For cross-region profiles, enable in all destination regions
If using
agents-harden, update the IAM policy to scope to the new model ARNRun
agentcore devto test locally, thenagentcore deployto update the deployed agent
No agentcore.json change is needed — the model is configured in code, not in the project config.
Pre-flight: validate any --name before generating the CLI command
Whichever reference you load, most end up producing an agentcore add <resource> --name <something> command. The CLI fails late on invalid names — you'll see the error after walking through prompts, not before running the command. Validate up front:
| Resource | Max chars | Allowed | Starts with |
|---|---|---|---|
Agent (add agent) | 48 | alphanumeric + _ | letter |
| Memory, gateway, gateway-target, credential, evaluator, online-eval, policy, policy-engine, payment-manager, payment-connector | 48 | alphanumeric + _ | letter |
Count the characters before constructing the command. If the name is over the limit or contains hyphens, dots, or spaces, push back: "<name> is N characters / uses -, which the CLI rejects. How about <suggestion>?" Never run the command with an invalid name hoping the CLI message will be clear.
Note: agentcore create --name (the project name) has a stricter 23-char limit and does not allow underscores. That's covered in agents-get-started; if you see the developer re-running create, flag the 23-char limit specifically.
Output
Depends on the workflow — see the loaded reference for specific outputs.
Quality criteria
The correct reference was loaded based on the developer's intent
All output follows the loaded reference's quality criteria
Cross-references to other skills (agents-connect, agents-deploy) are included where relevant
Files
- ATTRIBUTION.mdAdded by AutoGineer1011 B
- LICENSELicence file added by AutoGineer9.9 KiB
- NOTICELicence file added by AutoGineer67 B
- SKILL.md8.9 KiB
- references/browser.md10.0 KiB
- references/code-interpreter.md8.9 KiB
- references/integrate.md19.1 KiB
- references/local-vs-deployed.md4.2 KiB
- references/memory.md27.7 KiB
- references/migrate.md5.5 KiB
- references/multi-agent.md16.2 KiB
- references/payments.md71.4 KiB
- references/request-headers.md6.8 KiB
- references/teardown.md5.3 KiB
- references/vpc.md12.5 KiB
- scripts/process_payment_tool.pyScript7.0 KiB
- scripts/setup_payment_user.pyScript5.3 KiB
references/memory.md
memory
Add, configure, and debug AgentCore Memory — the managed service that lets your agent remember things across sessions.
When to use
You want your agent to remember user preferences, facts, or conversation history across separate sessions
You added memory via
agentcore createoragentcore add memoryand need to wire it into your agent codeMemory recall isn't working as expected
You want to share memory across multiple agents
Do NOT use this skill for within-session conversation history. That's handled automatically by the runtime — no configuration needed.
Input
$ARGUMENTS is optional. If provided, use it as the memory resource name:
/memory # uses name from agentcore.json, or prompts
/memory UserContext # targets a specific memory resource by nameProcess
Step 1: Read the project
Read agentcore/agentcore.json. Look for:
The
memoriesarray — is memory already configured?The
runtimesarray — what agents are in the project and what framework do they use?The project
name— needed for env var construction
If agentcore/agentcore.json does not exist, check if there's any AgentCore project structure nearby (look for agentcore/ directory). If none found, proceed with the most helpful answer possible based on what the developer asked — don't block on missing context. If the question is about strategy selection or code patterns, answer it directly. Only ask "which situation are you in?" if the answer genuinely depends on it (e.g., they need CLI commands that differ by setup type).
Step 2: Determine the situation
Case A — No memory configured yet
The memories array is empty or missing. Proceed to Step 3 (strategy selection).
Case B — Memory configured, needs wiring
Memory exists in agentcore.json but the agent code doesn't use it yet. Skip to Step 5 (generate wiring code).
Case C — Memory configured and wired, debugging recall Ask: "What's happening? What did you expect the agent to remember, and what did it actually do?" Then diagnose using the patterns in the Debugging section below.
Case D — Developer asking about memory without a project Answer the question directly. For strategy questions, explain the options. For code questions, show the pattern with a note that they'll need to substitute their actual memory ID.
Step 3: Choose a strategy
Present the options and ask the developer which fits their use case. Don't skip this — the wrong strategy wastes money and produces worse results.
Which memory strategy fits your use case?
SEMANTIC
Best for: remembering facts about users across sessions
How it works: extracts facts and stores them as embeddings; retrieves
relevant context via similarity search at session start
Cost: higher (embedding model + vector search per session)
Example: "Remember that Alex prefers bullet points and works in fintech"
USER_PREFERENCE
Best for: remembering explicit settings and preferences
How it works: extracts structured preference data; optimized for
key-value retrieval
Cost: lower (structured extraction, no vector search)
Example: "Remember my preferred response format and language"
SUMMARIZATION
Best for: remembering what you talked about last time
How it works: compresses conversation history into summaries; injects
the summary at the start of each new session
Cost: medium (summarization model runs at session end)
Example: "Pick up where we left off last time"
EPISODIC
Best for: remembering sequences of events or interactions over time
How it works: stores episodic records of interactions with temporal
context
Cost: medium
Common combinations:
SEMANTIC + USER_PREFERENCE → facts + preferences (most common)
SEMANTIC + SUMMARIZATION → full episodic memory (highest capability, highest cost)
USER_PREFERENCE alone → lightweight preference store
Which strategy (or combination) do you want?Step 4: Add memory to agentcore.json
Run the CLI command to add memory to the project config:
agentcore add memory --name <MemoryName> --strategies <STRATEGY1,STRATEGY2> --expiry 30This updates agentcore/agentcore.json. The memory resource is provisioned when you next run agentcore deploy — it takes 2–5 minutes to become active.
The resulting config entry looks like:
{
"memories": [{
"type": "AgentCoreMemory",
"name": "MyMemory",
"eventExpiryDuration": 30,
"strategies": [
{"type": "SEMANTIC"},
{"type": "USER_PREFERENCE"}
]
}]
}Memory name rules: alphanumeric + underscores, max 48 chars, starts with a letter.
Env var injected at deploy time: MEMORY_<UPPERCASENAME>_ID
Example: memory named UserContext → env var MEMORY_USERCONTEXT_ID
Step 5: Generate wiring code
Read app/<AgentName>/main.py (or the equivalent entrypoint) to detect the framework. Each framework has its own integration pattern — pick the one that matches:
| Framework | Recommended integration | Source |
|---|---|---|
| Strands | AgentCoreMemorySessionManager (CLI template) | bedrock_agentcore.memory.integrations.strands.* |
| LangGraph | AgentCoreMemorySaver + AgentCoreMemoryStore | langgraph-checkpoint-aws (official AWS-maintained) |
| OpenAI Agents SDK | MemoryClient via @function_tool | bedrock_agentcore.memory.MemoryClient |
| Google ADK / Claude Agent SDK | BYO — use MemoryClient directly | Validate end-to-end before shipping |
[!WARNING] Always check for the MEMORY_ID env var before initializing memory. Memory is NOT available during
agentcore dev— the env var is only set after deploy. Code that assumes memory is always available will fail silently in local development.
Strands — Session Manager pattern (recommended for new projects)
import os
from bedrock_agentcore.runtime import BedrockAgentCoreApp
from bedrock_agentcore.memory.integrations.strands.config import AgentCoreMemoryConfig, RetrievalConfig
from bedrock_agentcore.memory.integrations.strands.session_manager import AgentCoreMemorySessionManager
from strands import Agent
from model.load import load_model # scaffolded by `agentcore create`
app = BedrockAgentCoreApp()
# AgentCore injects this env var after deploy.
# Format: MEMORY_<UPPERCASENAME>_ID
MEMORY_ID = os.getenv("MEMORY_<UPPERCASENAME>_ID")
REGION = os.getenv("AWS_REGION", "us-east-1")
@app.entrypoint
def invoke(payload, context):
actor_id = payload.get("userId", "default-user")
session_id = getattr(context, "session_id", "default-session")
session_manager = None
if MEMORY_ID:
# RetrievalConfig parameters:
# top_k: max number of memory records to retrieve per namespace (SDK default: 10)
# relevance_score: similarity threshold, 0 = return anything, 1 = exact match (SDK default: 0.2)
# The CLI template deviates from SDK defaults to favor precision over recall:
# top_k=3 limits context window usage; relevance_score=0.5 filters low-quality matches.
# Tune these if retrieval misses relevant facts (lower) or surfaces irrelevant ones (raise).
memory_config = AgentCoreMemoryConfig(
memory_id=MEMORY_ID,
session_id=session_id,
actor_id=actor_id,
retrieval_config={
f"/users/{actor_id}/facts": RetrievalConfig(top_k=3, relevance_score=0.5),
f"/users/{actor_id}/preferences": RetrievalConfig(top_k=3, relevance_score=0.5),
}
)
session_manager = AgentCoreMemorySessionManager(memory_config, REGION)
agent = Agent(
model=load_model(),
session_manager=session_manager, # None is safe — agent runs without memory
system_prompt="You are a helpful assistant.",
)
result = agent(payload.get("prompt", ""))
return {"response": str(result)}
if __name__ == "__main__":
app.run()Strands — Hook pattern (for adding memory to an existing agent)
import os
from bedrock_agentcore.memory import MemoryClient
from strands.hooks import AgentInitializedEvent, HookProvider, MessageAddedEvent
MEMORY_ID = os.getenv("MEMORY_<UPPERCASENAME>_ID")
memory_client = MemoryClient(region_name=os.getenv("AWS_REGION", "us-east-1")) if MEMORY_ID else None
class MemoryHook(HookProvider):
def on_agent_initialized(self, event):
"""Load recent conversation turns into the agent's context."""
if not MEMORY_ID:
return
session_id = event.agent.state.get("session_id", "default")
turns = memory_client.get_last_k_turns(
memory_id=MEMORY_ID,
actor_id="user",
session_id=session_id,
k=3
)
if turns:
context = "\n".join([
f"{m['role']}: {m['content']['text']}"
for t in turns for m in t
])
event.agent.system_prompt += f"\n\nPrevious conversation:\n{context}"
def on_message_added(self, event):
"""Save each message to memory after it's processed."""
if not MEMORY_ID:
return
session_id = event.agent.state.get("session_id", "default")
msg = event.agent.messages[-1]
memory_client.create_event(
memory_id=MEMORY_ID,
actor_id="user",
session_id=session_id,
messages=[(str(msg["content"]), msg["role"])]
)
def register_hooks(self, registry):
registry.add_callback(AgentInitializedEvent, self.on_agent_initialized)
registry.add_callback(MessageAddedEvent, self.on_message_added)
# Add to your existing agent:
agent = Agent(
# ... your existing config ...
hooks=[MemoryHook()] if MEMORY_ID else [],
state={"session_id": "default"},
)LangGraph — langgraph-checkpoint-aws (recommended)
LangGraph has an official AWS-maintained integration via the langgraph-checkpoint-aws package. It provides two integrations that map cleanly to LangGraph's memory model:
AgentCoreMemorySaver— persists LangGraph's checkpoint objects (conversation state, execution graph, metadata) to AgentCore Memory. This is LangGraph's short-term / session memory.AgentCoreMemoryStore— saves conversational messages for AgentCore's long-term extraction (facts, preferences, summaries) and lets the agent search those memories in future sessions.
Use these instead of wiring MemoryClient calls into your graph manually — they handle the protocol conversion, actor/session mapping, and retry logic for you.
Install:
pip install langgraph-checkpoint-awsRequired IAM permissions on the agent's execution role:
bedrock-agentcore:CreateEventbedrock-agentcore:ListEventsbedrock-agentcore:RetrieveMemories
Basic pattern — short-term checkpointing only:
import os
from langgraph.prebuilt import create_react_agent
from langgraph_checkpoint_aws import AgentCoreMemorySaver
from bedrock_agentcore.runtime import BedrockAgentCoreApp
from model.load import load_model # scaffolded by `agentcore create`
app = BedrockAgentCoreApp()
MEMORY_ID = os.getenv("MEMORY_<UPPERCASENAME>_ID")
REGION = os.getenv("AWS_REGION", "us-east-1")
# Only wire checkpointing if memory is available (deployed)
checkpointer = AgentCoreMemorySaver(MEMORY_ID, region_name=REGION) if MEMORY_ID else None
@app.entrypoint
async def invoke(payload, context):
actor_id = payload.get("userId", "default-user")
session_id = getattr(context, "session_id", "default-session")
graph = create_react_agent(
model=load_model(),
tools=tools,
checkpointer=checkpointer, # None is safe — graph runs without persistence
)
# LangGraph's RunnableConfig maps thread_id → AgentCore session_id,
# actor_id → AgentCore actor_id under the hood
config = {
"configurable": {
"thread_id": session_id,
"actor_id": actor_id,
}
}
result = await graph.ainvoke(
{"messages": [("human", payload["prompt"])]},
config=config,
)
return {"response": result["messages"][-1].content}Full pattern — short-term + long-term retrieval:
For long-term memory (facts, preferences, summaries extracted by AgentCore), add AgentCoreMemoryStore with a pre-model hook that saves messages for extraction and (optionally) retrieves relevant memories:
import os
import uuid
from langchain_core.messages import HumanMessage
from langchain_core.runnables import RunnableConfig
from langgraph.prebuilt import create_react_agent
from langgraph.store.base import BaseStore
from langgraph_checkpoint_aws import AgentCoreMemorySaver, AgentCoreMemoryStore
MEMORY_ID = os.getenv("MEMORY_<UPPERCASENAME>_ID")
REGION = os.getenv("AWS_REGION", "us-east-1")
checkpointer = AgentCoreMemorySaver(MEMORY_ID, region_name=REGION) if MEMORY_ID else None
store = AgentCoreMemoryStore(MEMORY_ID, region_name=REGION) if MEMORY_ID else None
def pre_model_hook(state, config: RunnableConfig, *, store: BaseStore):
"""Save the latest human message for async extraction; optionally retrieve preferences."""
actor_id = config["configurable"]["actor_id"]
thread_id = config["configurable"]["thread_id"]
namespace = (actor_id, thread_id)
messages = state.get("messages", [])
for msg in reversed(messages):
if isinstance(msg, HumanMessage):
store.put(namespace, str(uuid.uuid4()), {"message": msg})
break
# Optional: retrieve user preferences to inject into context
# preferences_ns = ("preferences", actor_id)
# preferences = store.search(preferences_ns, query=msg.content, limit=5)
return {"llm_input_messages": messages}
graph = create_react_agent(
model=load_model(),
tools=tools,
checkpointer=checkpointer,
store=store,
pre_model_hook=pre_model_hook if store else None,
)Invoke with config:
config = {"configurable": {"thread_id": "session-1", "actor_id": "user-alice"}}
response = graph.invoke({"messages": [("human", "I prefer short answers.")]}, config=config)
# New session for the same actor — long-term memories are retrieved
new_config = {"configurable": {"thread_id": "session-2", "actor_id": "user-alice"}}
response = graph.invoke({"messages": [("human", "Summarize my latest report.")]}, config=new_config)The agent remembers "I prefer short answers" across sessions because AgentCore Memory extracts it as a user preference. See the AgentCore docs on LangGraph integration for the full reference.
If you need low-level control (custom retrieval queries, direct event management), fall back to MemoryClient:
from bedrock_agentcore.memory import MemoryClient
client = MemoryClient(region_name=REGION)
# client.create_event(...), client.retrieve_memories(...), client.get_last_k_turns(...)Use MemoryClient directly only when the checkpoint/store abstractions don't fit your use case.
OpenAI Agents SDK — memory as function tools
The OpenAI Agents SDK pattern is to expose memory as @function_tool decorated functions. The agent decides when to read and write:
import os
from agents import Agent, Runner, function_tool
from bedrock_agentcore.memory import MemoryClient
MEMORY_ID = os.getenv("MEMORY_<UPPERCASENAME>_ID")
REGION = os.getenv("AWS_REGION", "us-east-1")
_client = MemoryClient(region_name=REGION) if MEMORY_ID else None
def _build_memory_tools(actor_id: str, session_id: str):
"""Factory — binds actor/session into tool closures."""
@function_tool
def recall_context(query: str, top_k: int = 3) -> str:
"""Search long-term memory for facts or preferences about the user."""
if not _client or not MEMORY_ID:
return "Memory unavailable."
try:
memories = _client.retrieve_memories(
memory_id=MEMORY_ID,
namespace=f"/users/{actor_id}/facts",
query=query,
top_k=top_k,
)
return "\n".join(m.get("content", {}).get("text", "") for m in memories) or "No relevant memories."
except Exception as e:
return f"Memory error: {e}"
@function_tool
def save_fact(content: str) -> str:
"""Save a fact to long-term memory."""
if not _client or not MEMORY_ID:
return "Memory unavailable."
try:
_client.create_event(
memory_id=MEMORY_ID,
actor_id=actor_id,
session_id=session_id,
messages=[(content, "ASSISTANT")],
)
return "Saved."
except Exception as e:
return f"Error: {e}"
return [recall_context, save_fact]
@app.entrypoint
async def invoke(payload, context):
actor_id = payload.get("userId", "default-user")
session_id = getattr(context, "session_id", "default-session")
agent = Agent(
name="Assistant",
instructions="Use recall_context at the start of each session to check what you know about the user. Use save_fact when the user tells you something worth remembering.",
tools=_build_memory_tools(actor_id, session_id),
)
result = await Runner.run(agent, payload["prompt"])
return {"response": result.final_output}Google ADK and Claude Agent SDK — bring your own memory integration
AgentCore Memory doesn't have a framework-specific integration for ADK or the Claude Agent SDK yet, and the samples repo doesn't contain a combined pattern we can point to. Use the general MemoryClient API and wire it into the framework's existing extension points:
Google ADK: Expose memory operations as ADK tools (functions passed to
Agent(tools=[...])). The ADK agent decides when to call them.Claude Agent SDK: Wrap
query()with a pre-call memory load and a post-call memory save. The SDK'sClaudeAgentOptions.system_promptis the injection point for retrieved context.
For both frameworks, follow the MemoryClient API shown in the OpenAI Agents pattern above — the client calls (retrieve_memories, create_event, get_last_k_turns) are identical. The framework-specific part is just where you call them.
Before shipping a memory integration for ADK or Claude SDK, validate the end-to-end flow against a deployed agent:
Deploy with memory enabled
Invoke the agent with facts to remember
Start a new session
Invoke again and verify the agent recalls those facts
Check
agentcore logs --runtime <AgentName> --query "memory" --since 1h --level errorfor any memory errors
If you build a working pattern, consider contributing it to awslabs/agentcore-samples so the next developer doesn't have to figure it out.
Step 6: Explain the local dev gap and next steps
Always include this note:
⚠️ Memory is not available during local development (agentcore dev).
The MEMORY_<NAME>_ID env var is only injected after deploy. The code above
handles this gracefully — it runs without memory when the env var isn't set.
To test memory:
agentcore deploy -y
agentcore invoke "My name is Alex and I prefer concise answers"
agentcore invoke "What do you know about me?"
If using long-term memory (SEMANTIC or USER_PREFERENCE), wait 5–30 seconds
between the first and second invoke — extraction runs asynchronously after
each session ends.
Session ID note: use UUIDs (v4) for session IDs — they satisfy the platform's
minimum length requirement (33 characters) and are what `agentcore invoke`
generates by default. Short or sequential session IDs (e.g., "session-1",
"test") can cause long-term memory extraction to fail silently.If the developer is using the SDK directly (no CLI project), they need to create the memory resource first:
from bedrock_agentcore.memory import MemoryClient
client = MemoryClient(region_name="us-east-1")
# Create memory and wait for it to become ACTIVE (takes 2-5 minutes)
memory = client.create_memory_and_wait(
name="UserMemory",
strategies=[
{"userPreferenceMemoryStrategy": {
"name": "prefs",
"namespaces": ["/user/preferences/"]
}},
{"semanticMemoryStrategy": {
"name": "facts",
"namespaces": ["/user/facts/"]
}}
],
event_expiry_days=30
)
MEMORY_ID = memory["id"]
print(f"Memory created: {MEMORY_ID}")
# Set this as an env var or hardcode for testing:
# export MEMORY_ID=<value>Then use the same wiring code from Step 5, reading MEMORY_ID from the environment.
Debugging memory recall
If memory was working and stopped, or never worked:
Agent keeps forgetting things even with memory set up:
Most common cause: the memory resource is configured but the code isn't reading from it at session start. Check that your entrypoint calls get_last_k_turns (or uses the session manager) before creating the agent, not after. Also verify the MEMORY_<NAME>_ID env var is set — it's only injected after deploy, not during agentcore dev.
Memory not persisting across sessions:
Check that LTM strategies (SEMANTIC, USER_PREFERENCE) are configured — not just SUMMARIZATION
Wait 5–30 seconds after a session ends before starting a new one — extraction is async
Verify the memory resource is ACTIVE:
agentcore status --type memoryUse UUIDs (v4) for session IDs — the platform requires a minimum of 33 characters. Short IDs like "session-1" or "test" cause LTM to fail silently.
agentcore invokegenerates compliant IDs by default.
Memory not loading at session start:
Verify
MEMORY_<NAME>_IDenv var is set:agentcore status --type memory --jsonCheck the actor_id is consistent across sessions — memory is scoped per actor
Confirm the namespace paths in retrieval_config match the namespaces used when writing — the retrieval namespace must exactly match the namespace the strategy extracts into
CLI defaults use paths without trailing slashes (e.g.,
/users/{actorId}/facts). If you customized namespace templates when creating the memory resource, use whatever pattern you chose — consistency between writer and reader is what matters.
Memory provisioning slow:
Memory takes 2–5 minutes to become ACTIVE after agentcore deploy. Check status:
agentcore status --type memoryS3 delivery / export buckets must be in the same account
If you're configuring S3 delivery for memory exports, session transcripts, or Browser recording output, the destination bucket must be in the same AWS account as the AgentCore resource. Cross-account S3 buckets are not supported as delivery destinations, even with correct bucket policies granting the service principal access.
Symptom of attempting a cross-account bucket: CreateMemory (or the relevant resource creation call) fails with ValidationException: Role does not have access to required S3 buckets — even when IAM and bucket policies are correctly configured for cross-account access.
Workaround: create a same-account bucket for the AgentCore resource to write to. If you need the data in a different account, replicate from the same-account bucket via S3 replication or a scheduled copy job.
Sharing memory across agents
Memory is a top-level resource — not nested under a single agent. To share:
Create one memory resource:
agentcore add memory --name SharedMemory --strategies SEMANTICIn each agent's code, read the same env var:
MEMORY_SHAREDMEMORY_IDUse a consistent
actor_idscheme across agents (e.g., the end user's ID)
Cross-region inference (data residency)
Memory consolidation (extraction + summarization for long-term strategies) uses cross-region inference by default. Your memory data stays in your primary region, but the inference call that extracts facts or summarizes a session may execute in another AWS region within the same geography (e.g., us-east-1 → us-east-2 or us-west-2; EU stays in EU; etc.).
This matters when:
You have a data-residency requirement that goes beyond storage — some regulations constrain where inference may run, not just where results land
You're building for a customer whose contract pins processing to a single region
Your audit trail needs to show which region handled each prompt
There's no extra cost for cross-region inference, and CloudWatch/CloudTrail logs don't include the inference region. Across the Memory, Policy, and Evaluations services, this is the default behavior.
To opt out for Memory: use a built-in-with-overrides strategy (see memory-custom-strategy) and pin the model to a specific region. The overrides strategy lets you specify the exact model ID used for extraction and consolidation, which gives you region control.
The supported geographies and inference-region mappings change as AgentCore expands — check the cross-region inference docs for the current list rather than baking it in here.
Beyond the CLI: memory features that require the API
The CLI's agentcore add memory and agentcore.json cover strategy selection, expiry, and basic configuration. Some memory capabilities are API/SDK-only — the CLI doesn't expose them. When the developer needs one of these, the graduation path is: create the memory via CLI as usual, deploy, then apply the additional config via boto3 or AWS CLI.
Resource-based policies (cross-account access, principal-level restrictions):
import boto3, json
client = boto3.client("bedrock-agentcore-control")
memory_id = "<MEMORY_ID>" # from: agentcore status --type memory --json
client.put_memory_resource_policy(
memoryId=memory_id,
policy=json.dumps({
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::111122223333:root"},
"Action": [
"bedrock-agentcore:CreateEvent",
"bedrock-agentcore:RetrieveMemories",
"bedrock-agentcore:ListEvents"
],
"Resource": "*"
}]
})
)Custom extraction models (pin the model used for LTM extraction — e.g., for data residency):
Use the "built-in with overrides" strategy type via UpdateMemory. See the custom memory strategy docs for the full configuration shape.
Self-managed strategies (bring your own extraction logic):
Also API-only. See the AgentCore memory docs for the selfManagedMemoryStrategy configuration.
When you hit a memory capability not covered here, use the awsknowledge MCP server if available — search for the specific API operation (e.g., "AgentCore PutMemoryResourcePolicy") to get the current parameter shapes. The API surface evolves between releases.
General rule: if agentcore.json has a field for it, use the CLI. If it doesn't, create the resource via CLI, deploy, then apply the additional config via boto3. Don't fight the CLI to do something it wasn't designed for.
Output
Updated
agentcore/agentcore.jsonwith memory resource (via CLI command)Wiring code for
app/<AgentName>/main.pyappropriate for the detected frameworkExplanation of the local dev gap and how to test after deploy
Quality criteria
Generated code handles
MEMORY_IDbeing None (local dev) without crashingEnv var name matches the memory resource name in
agentcore.json(uppercase, underscores)Framework-specific pattern is used — never generate Strands hooks for a LangGraph project
LTM extraction delay is communicated
Session ID guidance recommends UUIDs (v4) when LTM strategies are used (minimum 33 characters)
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Needs: Declares allowed tools, Needs an MCP server, Needs Python
Security
What our scanner noticed· Low risk
- Instructions that use the network
- Scripts that your agent may run
This skill includes scripts that your agent may run. Read them before you use it.
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- aws-agentcore
- Publisher
- AWS (Official)
- Source
- aws/agent-toolkit-for-aws · plugins/aws-agents/skills/agents-build · commit 0a218f8
- Licence
- Apache License 2.0 (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- NOTICE (added by AutoGineer from NOTICE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by aws-agentcore or AWS.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download agents-build.zip