Generated banner for Agents Build
Generated logo for Agents Build

Agents Build

AWSOfficialCreated by aws-agentcore

  • Skill
  • Workflow
  • Cloud and DevOps
  • Apache-2.0
  • Low risk
  • Has scripts

From the author

Use to extend an existing agent project with memory, app integration, VPC, multi-agent, migration, model, browser, code interpreter, payments, or resource removal. Triggers: "add memory", "remember across sessions", "call agent from app", "invoke agent from code", "agent auth", "streaming", "VPC", "VPC connectivity", "can't reach from VPC", "multi-agent", "A2A", "A2A auth", "orchestrator not delegating", "specialist not called", "migrate Bedrock Agent", "migration issue", "change model", "browser tool", "code interpreter", "delete agent", "tear down", "agentcore remove", "cross-account memory", "add payments capability to my agent", "wire payments plugin", "integrate x402 payments with the agent I'm building", "add MPP payments", "Machine Payments Protocol". External APIs via Gateway: use agents-connect. New project: use agents-get-started. CLI/dev-server errors: use agents-debug. Runtime x402/MPP payments: use agents-pay. Migration-specific Strands vs LangGraph routes here.
— the description by aws-agentcore

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

  1. Download the skill as a ZIP:

    https://autogineer.com/agent-skills/aws/agents-build/download
  2. Unzip 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-connect

  • Scaffolding a new project → use agents-get-started

  • Deploying → 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:

  1. Check if the developer is in the wrong directory. Look for agentcore/agentcore.json in parent directories (up to 3 levels). If found, tell them: "Found an AgentCore project at <path>. Are you working in that project?"

  2. 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, cd into 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 build

  • If the developer says something is broken (wrong answers, errors, tool failures) → this is agents-debug, not build

  • Build 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 intentReference to load
Add memory, remember things, user preferences, cross-sessionreferences/memory.md
Call agent from app, invoke from code, streaming, SDK client, agent URL, execute shell in sessionreferences/integrate.md
VPC, private network, RDS, internal API, subnet, security groupreferences/vpc.md
Multi-agent, orchestrator, specialist, A2A, delegation, agent handoffreferences/multi-agent.md
Custom headers from caller to agent, header allowlist, tenant ID/correlation ID/trace propagationreferences/request-headers.md
Migrate Bedrock Agent, import agent, move to AgentCorereferences/migrate.md
Browser tool, web navigation, form filling, scraping, Nova Act, Playwright, live viewreferences/browser.md
Code Interpreter, execute code, sandbox, run Python/JS/TS, data analysis in agent, pandasreferences/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/connectorreferences/payments.md
Delete agent, remove resource, tear down, clean up, destroy, start freshreferences/teardown.md
Change model, switch model, use Haiku/Sonnet/Nova, different modelInline — 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:

  1. Open app/<AgentName>/model/load.py

  2. Change the model_id parameter in the BedrockModel() 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 ARN

  • Run agentcore dev to test locally, then agentcore deploy to 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:

ResourceMax charsAllowedStarts with
Agent (add agent)48alphanumeric + _letter
Memory, gateway, gateway-target, credential, evaluator, online-eval, policy, policy-engine, payment-manager, payment-connector48alphanumeric + _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

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 create or agentcore add memory and need to wire it into your agent code

  • Memory 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 name

Process

Step 1: Read the project

Read agentcore/agentcore.json. Look for:

  • The memories array — is memory already configured?

  • The runtimes array — 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 30

This 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:

FrameworkRecommended integrationSource
StrandsAgentCoreMemorySessionManager (CLI template)bedrock_agentcore.memory.integrations.strands.*
LangGraphAgentCoreMemorySaver + AgentCoreMemoryStorelanggraph-checkpoint-aws (official AWS-maintained)
OpenAI Agents SDKMemoryClient via @function_toolbedrock_agentcore.memory.MemoryClient
Google ADK / Claude Agent SDKBYO — use MemoryClient directlyValidate 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.

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 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-aws

Required IAM permissions on the agent's execution role:

  • bedrock-agentcore:CreateEvent

  • bedrock-agentcore:ListEvents

  • bedrock-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's ClaudeAgentOptions.system_prompt is 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:

  1. Deploy with memory enabled

  2. Invoke the agent with facts to remember

  3. Start a new session

  4. Invoke again and verify the agent recalls those facts

  5. Check agentcore logs --runtime <AgentName> --query "memory" --since 1h --level error for 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:

  1. Check that LTM strategies (SEMANTIC, USER_PREFERENCE) are configured — not just SUMMARIZATION

  2. Wait 5–30 seconds after a session ends before starting a new one — extraction is async

  3. Verify the memory resource is ACTIVE: agentcore status --type memory

  4. Use 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 invoke generates compliant IDs by default.

Memory not loading at session start:

  1. Verify MEMORY_<NAME>_ID env var is set: agentcore status --type memory --json

  2. Check the actor_id is consistent across sessions — memory is scoped per actor

  3. 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

  4. 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 memory

S3 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:

  1. Create one memory resource: agentcore add memory --name SharedMemory --strategies SEMANTIC

  2. In each agent's code, read the same env var: MEMORY_SHAREDMEMORY_ID

  3. Use a consistent actor_id scheme 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.json with memory resource (via CLI command)

  • Wiring code for app/<AgentName>/main.py appropriate for the detected framework

  • Explanation of the local dev gap and how to test after deploy

Quality criteria

  • Generated code handles MEMORY_ID being None (local dev) without crashing

  • Env 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