Task 3 · 8 tasks

AgentCore Memory

Long-term, per-user memory that learns facts across sessions and keeps users apart.

15 minEasy
Alice’s ask

The “Remember Me, Not Jordan” crisis

Alice is frustrated: “I told the agent last week I prefer Python reports, and today it forgot. Worse, Jordan could see my preferences!” File sessions on one laptop won't cut it. You need memory that persists across sessions and is isolated per user.

Platform

What the platform provisions for you

terminal
uv run bootcamp.py up 3
  • An AgentCore Memory resource with a UserFacts semantic extraction strategy
  • Its MEMORY_ID and MEMORY_STRATEGY_ID, visible in status and injected into the agent in Task 4
You

What you do as a developer

  1. Keep users apart

    Challenge

    The runtime passes the caller's identity in the header X-Amzn-Bedrock-AgentCore-Runtime-Custom-Actor-Id. Write actor_from(context) so that Alice and Jordan never share memories, even if the header's casing changes.

    Hint 1

    RequestContext.request_headers is a dict of the incoming headers (it may be None). HTTP header names are case-insensitive, but Python dict keys are not.

    Hint 2

    Lower-case every key once, then look up the lower-cased header name. Fall back to a fixed default_user when it's missing.

    Solution
    phase2/app/agent/agent.py
    ACTOR_HEADER = "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Actor-Id"
    
    
    def actor_from(context: RequestContext) -> str:
        """Header names arrive with runtime-dependent casing, so match case-insensitively."""
        headers = {name.lower(): value for name, value in (context.request_headers or {}).items()}
        return headers.get(ACTOR_HEADER.lower(), "default_user")
  2. Wire memory into the agent

    Challenge

    Write memory_session_manager(session_id, actor_id): short-term events per session, long-term facts retrieved only from this actor's namespace.

    Hint 1

    Look at AgentCoreMemoryConfig and AgentCoreMemorySessionManager in bedrock_agentcore.memory.integrations.strands. AgentCore Memory docs.

    Hint 2

    retrieval_config maps a namespace template to a RetrievalConfig. The UserFacts namespace is /strategies/{memoryStrategyId}/actors/{actorId}. Watch the relevance_score: see the lesson below.

    Solution
    phase2/app/agent/agent.py
    MEMORY_RELEVANCE_SCORE = 0.3
    """The guide uses 0.7, but semantic-memory scores for an exact fact are ~0.45, so 0.7 drops everything."""
    
    
    def memory_session_manager(session_id: str, actor_id: str) -> AgentCoreMemorySessionManager:
        config = AgentCoreMemoryConfig(
            memory_id=MEMORY_ID,
            session_id=session_id,
            actor_id=actor_id,
            retrieval_config={
                "/strategies/{memoryStrategyId}/actors/{actorId}": RetrievalConfig(
                    top_k=5, relevance_score=MEMORY_RELEVANCE_SCORE, strategy_id=MEMORY_STRATEGY_ID
                )
            },
        )
        return AgentCoreMemorySessionManager(agentcore_memory_config=config, region_name=REGION)
  3. Experiments

    • What's the difference between short-term memory (raw events in a session) and long-term memory (extracted facts)?
    • What would you trade by raising top_k to 20, or the relevance score to 0.7?
  4. Re-test

    The agent code you wrote here is deployed in Task 4. For now, check the memory resource:

    terminal
    uv run bootcamp.py test --only 3

Check your work

terminal
uv run bootcamp.py test --only 3

Passes when your memory is ACTIVE with the UserFacts strategy.

Under the hood

AgentCore Memory stores conversation events per session and actor (short-term), and runs extraction strategies asynchronously to build long-term records. The semantic strategy uses a model to pull out durable facts (“prefers Python reports”) and indexes them for vector retrieval. Strands' AgentCoreMemorySessionManager writes each turn as an event and injects retrieved facts into the context before the model call. Extraction takes a minute or so, so a fact isn't searchable instantly.