Hightower's AI Harness Engineering

Hightower's AI Harness Engineering

AgentCore IV: Your AgentCore Session Is Not a Conversation. Confusing Sessions and Conversations Breaks Continuity

Part 4: In AgentCore session means a microVM lease with a conversation ID. Forgetting this causes agent amnesia, and the 8-hour limit is a lease, but you still have to stop your loop

Rick Hightower's avatar
Rick Hightower
Jul 27, 2026
∙ Paid
Cover image for “Your AgentCore Session Is Not a Conversation. Confusing the Two Is How Continuity Dies.” by Rick Hightower

There are two definitions of "session," and the 8-hour limit on leasing your microVM will not stop your agent for you.

When your agent starts acting like a stranger, and you start racking up bug reports that say your agent is forgetting. You might be confusing the two definitions of the word session.

In this article, you will learn the AgentCore contract that mediates your agent loop and Amazon Bedrock AgentCore Runtime. Then the article covers how async generators become server-side events (SSE), and how to read the Runtime session ID. Another key point is that your AgentCore session and your agent framework's session are different objects. This is where in-process checkpoints are killed. Then we cover the four stopping conditions that must still live only in your code. By the end, you will have a firm understanding that streaming, identity, durable state, and loop bounds are one logically consistent contract.


Share


Imagine building a conversational agent system, spinning up your agent in production, and watching its operational state vanish without throwing a single error. Poof. Your agent has amnesia. When deploying an agentic application, agent loop on your harness, to AWS AgentCore, this sudden agent lobotomy, or total loss of conversation state, can be an operational reality. New Developers to AgentCore can encounter intermittent agent amnesia with their production agents.

The AgentCore “session” is the microVM, and it only lives for a max 8-hour lease. The AgentCore session is not to be confused with the conversation session. It is easy to confuse these two things, and the outcome is the agent starts responding like a stranger when its local file system memory written to the microVM goes bye-bye.

Another problem you can run into is the agent works for many minutes on a problem, and your clients are just sitting there staring at a spinner. To get past these issues, you want to use streaming response, which is built on top of SSE. This forces the agent to send incremental progress as it goes using the async generator, which gets translated into SSE events that can be filtered and displayed to the end user. This is perceived performance; your end users can see incremental progress as agent output is displayed, and your clients don't think your agentic app is stuck. If you want your clients to be able to guide agent work in the middle, then you use a WebSocket connection.

Understanding the AgentCore Lease SessionID

The AgentCore session boils down to a computer box lease, which is the lease on the microVM. The lease is live for a maximum of 8 hours. If your agent is asleep/idle for fifteen minutes, then it dies. When your agent is killed/dies, all the memory on that microVM you were leasing is gone.

The actual framework agentic harness session is real conversation memory that gets stored (LangChain DeepAgents thread_id or Claude Agent SDK session_id). These are completely different session IDs that do different things.

You must join them with the same ID. If you mess up this join, your agent forgets everything. There will be no loud error. Just the agent has silent amnesia.

The context you did not ask for

Your entrypoint has been taking one parameter. It can take two.

@app.entrypoint
async def handler(request, context):
    session_id = context.session_id
    ...

AgentCore inspects your signature, notices the second parameter, and passes a RequestContext carrying session_id and headers. Note that now there is nothing to register, and nothing to import. The detection is a function named _takes_context in the AgentCore’s app.py.

There is a second way to get this session ID. Just in case you need to get to it from somewhere other than the handler:

from bedrock_agentcore.runtime import BedrockAgentCoreContext

session_id = BedrockAgentCoreContext.get_session_id()

That is a contextvar, populated from the X-Amzn-Bedrock-AgentCore-Runtime-Session-Id header that the AgentCore substrate injects. This contextvars exists so you can access the session ID without you passing it around the call stack as an argument to every level.

Both mechanisms hand you the same string. Use the parameter when you have it, and the contextvar when you are three layers down.

For clarity: two sessions

Again, AgentCore’s session is a microVM lease. AgentCore provides compute with isolated CPU, memory, and filesystem, with states Active, Idle, and Terminated. This microVM dies after 15 minutes of inactivity, at 8 hours maximum, or when it goes unhealthy. It is oblivious and ignorant of conversational state. It is a container with a countdown.

Your agentic harness framework’s session is conversation state. In the Claude Agent SDK, it is the session_id that arrives on the SystemMessage at init, and you resume it with ClaudeAgentOptions(resume=session_id). In DeepAgents, it is thread_id, passed through config["configurable"]["thread_id"], enabling the LangGraph checkpointer. The agent harness session_id/thread_id knows nothing about compute. It is a key that points to conversational memory.

A mindmap of two unrelated meanings of session: AgentCore's microVM lease with Active, Idle, and Terminated states, versus the framework conversation keyed by session_id or thread_id, joined only by a string you pass by hand.

How to really persist conversational state

The trick is to not just store the conversation memory inside the microVM (InMemorySaver). When you lose your lease, you will lose your conversational state with it. Don’t do this.

Put memory outside microVM by using: Postgres, DynamoDB, or AgentCore Memory.

When the box dies because the lease on the microVM ended, your agent’s conversational state lives on.

The sessionIds represent different objects, different lifetimes, and the only thing connecting them is an ID you remembered to pass:

from bedrock_agentcore.runtime import BedrockAgentCoreContext

@app.entrypoint
async def handler(request):
    prompt = request.get("prompt", "")
    session_id = BedrockAgentCoreContext.get_session_id() or request.get(
        "session_id", "default"
    )
    config = {"configurable": {"thread_id": session_id}}
    result = await agent.ainvoke({"messages": [("user", prompt)]}, config=config)
    yield result["messages"][-1].content

One line does the join: the AgentCore session ID becomes the DeepAgents thread ID, so one lease equals one checkpointed conversation. The Claude Agent SDK equivalent threads context.session_id into resume.

A sequence diagram of the join: Runtime injects a session header, the entrypoint maps it to thread_id or resume, a durable checkpointer reloads prior state, and SSE events stream back to the client.

Miss that one line of mapping, and nothing breaks loudly. There is no smoking gun. The agent answers. It just answers as an amnesia patient every time. The bug report says “it forgets sometimes,” and you cannot reproduce it locally because locally there is only ever one session.

The two sessions are joined by a string you pass by hand, and forgetting it produces an agent with a lobotomy rather than an error. Write the session/conversation join first, before the interesting code, in every @app.entrypoint that you build.


If you are a paid subscriber, thank you. Your support makes this work possible.

If you are a free subscriber and find these articles useful, please consider upgrading. A paid subscription is $80 per year or $8 per month.

Share Hightower's AI Harness Engineering

User's avatar

Continue reading this post for free, courtesy of Rick Hightower.

Or purchase a paid subscription.
© 2026 Rick Hightower · Privacy ∙ Terms ∙ Collection notice
Start your SubstackGet the app
Substack is the home for great culture