Overview
I love markdown because it is frictionless. That is also the problem.
Ideas become ideas.md.
Then ideas-2.md.
Then a folder called poc-notes/.
Then a README inside a toy repository.
Then a half-written architecture note I forgot existed.
After a few months, the information is technically mine but practically lost.
What I wanted was not another general-purpose chatbot. I wanted a second brain for my own material — markdown notes, proof-of-concept writeups, architecture sketches, project journals, rough drafts that are still useful even if they are not pretty.
By late 2025, AWS had a stack that finally made this idea feel practical. Strands Agents for the agent loop, Amazon Bedrock AgentCore Memory for short-term and long-term memory, and Amazon Bedrock Knowledge Bases for retrieval over my document archive.
This combination is much more interesting to me than the usual “AI reads contracts” demo. Contracts can wait. I want something that remembers the strange half-finished technical ideas I keep leaving around my filesystem.
The Actual Use Case
The concrete use case is simple:
I keep a bucket of personal technical material:
notes/for markdown notesideas/for product ideas and rough conceptspocs/for experimental writeups and README filesdocs/for small architecture notes and operating checklistsjournal/for dated progress logs
I want to ask questions like “What was that idea I had about using EventBridge for scheduled dataset refreshes?”, “Which POC already explored semantic search over markdown?”, or “What am I actively exploring right now, and what did I postpone last time?”. Questions that need retrieval over documents, memory of previous sessions, and a conversational loop that can decide what to look up. That is the right shape for an agent.
Why These Three Pieces Belong Together
Strands is AWS’s open-source agent SDK. What I like about it is that it stays close to code — you define tools as normal Python functions, pass them to an Agent, give the model access to Bedrock, and let the loop handle the rest. It feels much lighter than frameworks that force you to model every thought as a graph.
AgentCore Memory solves the “every session starts from zero” problem. It stores short-term events inside a session and extracts longer-lived memories across sessions. In practice that means the assistant can remember that I prefer short summaries before deep dives, that I’m actively exploring two POCs and intentionally parked a third, or that I already rejected a particular approach last week and don’t need to rediscover it.
Knowledge Bases handles the grounding problem: where the actual markdown files live, how they are chunked, embedded, indexed, and retrieved. The useful 2025 twist is that Bedrock Knowledge Bases can now use S3 Vectors as the backing vector store, which makes this stack much more attractive for personal use than the older “always-on search backend” story.
A Cleaner Architecture for a Personal Second Brain
I ended up with a mental model like this:
- My notes, ideas, and POC markdown files live in a normal S3 bucket.
- Bedrock Knowledge Bases ingests that bucket and stores embeddings in S3 Vectors.
- A Strands-based Python app runs the conversational agent.
- The agent uses Bedrock models for reasoning, the Knowledge Base for retrieval, and AgentCore Memory for continuity across sessions.
- Each meaningful interaction is written back as an AgentCore event so future sessions remember what mattered.
That gives me two kinds of recall:
- document recall: what exists in the archive
- context recall: what I was trying to do, what I decided, and what style of answer I prefer
Those are different problems, and I like that this architecture treats them separately.
The Document Layer
The document archive is intentionally boring: markdown, text, a few PDFs, and whatever lightweight technical artifacts I want indexed.
Bedrock Knowledge Bases supports markdown files directly, so a folder structure like this is enough:
second-brain/
├── notes/
│ ├── ecs-express-mode.md
│ ├── lambda-managed-instances.md
│ └── eventbridge-patterns.md
├── ideas/
│ ├── semantic-notebook-search.md
│ └── tiny-observability-dashboard.md
├── pocs/
│ ├── poc-rag-markdown/README.md
│ └── poc-home-lab-agent/notes.md
└── journal/
├── 2025-10-20.md
└── 2025-10-23.md
The important thing is not perfect structure. The important thing is that the assistant can search it semantically when filenames stop being helpful.
For the vector store, I would now use Knowledge Bases with S3 Vectors rather than defaulting to OpenSearch Serverless. That is a much better fit for the kind of personal, low-ops setup I had in mind.
The Memory Layer
The original version of this article leaned too hard into fake-freelancer-enterprise territory. That is not where the interesting part is.
The useful long-term memories in this setup are much more personal and much more technical — things like “the user prefers short summaries before deep dives”, or “the user postponed the local MCP indexing prototype because retrieval quality was not stable enough”, or “architecture notes should be practical, not generic”. The kind of context that takes five minutes to re-explain at the start of every session.
AgentCore Memory organizes raw events by actor and session, then extracts longer-lived memories through strategies. That is a much better model than trying to cram permanent preferences into a giant system prompt.
The write path is event-based:
import time
import boto3
memory = boto3.client("bedrock-agentcore", region_name="eu-west-1")
memory.create_event(
memoryId=MEMORY_ID,
actorId="made2591",
sessionId=session_id,
eventTimestamp=int(time.time()),
payload=[
{
"conversational": {
"role": "USER",
"content": {"text": "I'm comparing ECS Express Mode and Lambda Managed Instances for small workloads."}
}
}
],
)
And the retrieval path goes after extracted long-term memories:
response = memory.retrieve_memory_records(
memoryId=MEMORY_ID,
namespace="/users/made2591/preferences",
searchCriteria={
"searchQuery": "What is the user actively exploring right now?",
"topK": 5,
},
)
What matters here is not the exact SDK ceremony. What matters is the split: raw interactions go in as events, useful patterns come back out as memory records.
The Agent Layer
On the Strands side, the agent can stay refreshingly small.
The only tools I really need are one to query the Knowledge Base, one to query long-term memory, and one to write back a session event or summary. That gives the model enough leverage without turning the whole thing into a fake autonomous coworker.
from strands import Agent, tool
from strands.models import BedrockModel
@tool
def search_notes(query: str) -> str:
"""Search the knowledge base for markdown notes, POC docs, and technical drafts."""
...
@tool
def recall_context(query: str) -> str:
"""Recall persistent preferences and recent working context from AgentCore Memory."""
...
@tool
def remember_fact(text: str) -> str:
"""Store a useful new fact or session summary in AgentCore Memory."""
...
agent = Agent(
model=BedrockModel(
model_id="anthropic.claude-sonnet-4-20250514-v1:0",
region_name="eu-west-1",
),
tools=[search_notes, recall_context, remember_fact],
)
That is enough for useful interactions like “Summarize the notes I wrote about semantic retrieval”, “Which ideas are still open?”, or “Give me a one-page recap before I continue working”. I do not need the agent to pretend it is my project manager. I just need it to help me reconnect threads that are currently scattered across markdown and memory.
Where This Runs
During development, the Strands app runs locally — Python virtualenv, AWS credentials, direct calls to Bedrock, Knowledge Bases, and AgentCore Memory. That is the fastest way to iterate on prompts, tools, and memory behavior.
If I want a permanent HTTPS endpoint, I would containerize the same Python app and run it on ECS on Fargate, optionally published through ECS Express Mode for the easy HTTPS front door. That gives me a stable endpoint with IAM-based access to Bedrock and AgentCore, CloudWatch logs, and nothing to maintain at the VM level.
For this specific project ECS/Fargate feels more natural than Lambda because I want a small long-lived app surface, not just an event handler.
What the System Actually Uses
The final service list is surprisingly reasonable: S3 for the source document bucket, Bedrock Knowledge Bases with S3 Vectors as the backing store, AgentCore Memory for short-term and long-term memory, Bedrock model runtime for the LLM itself, Strands Agents in the Python app, ECS Fargate if I want a hosted version, and CloudWatch Logs for observability.
That is why I like the stack. It feels modular, but not absurdly so.

Final Thoughts
This stack feels useful because it respects the shape of the problem.
My markdown archive is not a CRM. My notes are not legal records. My POCs are not enterprise workflows.
They are just the messy, valuable by-products of technical work.
Strands gives me a lightweight agent loop. Knowledge Bases gives me retrieval over the archive. AgentCore Memory gives me continuity between sessions. Put together, they create something much closer to the assistant I actually want: one that helps me resume thinking instead of forcing me to restate everything from scratch.
That is a much better definition of “second brain” than yet another demo about PDFs and contracts.
See also: