S3SessionManager abandoned; conversation history written manually to S3
dropthejase wired Strands' built-in `S3SessionManager`, then ripped it out after it failed to give the control needed over history reload - specifically, tool activity cards and reasoning blocks were lost on page refresh. The replacement writes `agent.messages` directly to S3 after each invocation and reads them back before the next turn.
The first iteration wires SessionManager with S3Storage pointing at a sessions bucket. Each chat turn passes a sessionId through the agent factory. This approach stores the full Strands conversation snapshot, but when the backend rehydrates history for the frontend it can't reconstruct tool activity events or reasoning blocks from the baked snapshot - they get stripped or misformatted.
The replacement (efdae23) drops SessionManager entirely. A loadMessages() function reads conversations/{chatId}/messages.json from S3 before each turn and passes the deserialized MessageData[] into the agent constructor as messages: previousMessages. An AfterInvocationEvent hook writes agent.messages back to S3 after each turn. The system prompt is excluded from the snapshot and always loaded fresh from code - this was a specific failure mode of the baked-snapshot approach.
The session ID protocol on the SSE stream is a separate concern and stays: the frontend generates a {userId}-{uuid} session ID on the first turn and immediately PUTs it to PUT /chat/:chatId/session-id when the chat_id SSE event arrives - not after the stream completes, to handle tab-close mid-stream. The backend never overwrites an existing session ID for a chat row.
A follow-up commit (febe83f) fixes the snapshot-to-frontend translation layer: snapshotMessagesToMikeMessages now handles Strands' nested content block format (both text and textBlock types, and blocks with no type at all), restoring tool activity cards on history reload.
Spotted something wrong? Or know the PR text has fresher detail than the writeup above?