← Projects

Thinking Memory Hub

A note memory system that supports natural-language retrieval, note updates, and Slack integration.

This project started from a simple idea: if I am sending notes to a system through a messenger, I want that system to do more than just store them. I want to be able to come back later and retrieve them in natural language, update them cleanly, and treat memory as something a system can work with rather than just accumulate.

That pushed the project toward a layered design. The MCP server defines the core memory operations as stable tools: save notes, search notes, update notes, and search tags. LangGraph sits above that as the reasoning layer, handling intent classification, structured input extraction, and workflow routing. Langfuse provides observability across both layers, so the system can be inspected after the fact instead of treated like a black box.

The runtime flow is fairly straightforward, but that separation matters. A user message comes in, gets interpreted by a LangGraph workflow, triggers the appropriate MCP tool calls against PostgreSQL, and returns a response through the same channel. That keeps the storage layer stable while leaving the orchestration layer free to evolve independently.

The part I cared about most was making note handling explicit instead of folding everything into one vague “memory” action. Saving a note, searching notes, updating an existing note, and finding tags are different operations with different failure modes. Modeling them separately made the system easier to extend and easier to debug when the orchestration did the wrong thing.

The first messenger integration is Slack. The channel adapter is kept separate from the MCP and LangGraph core, so the same backend can support a Slack mention, a direct API call, or another messenger integration later without changing the storage model underneath.

The project also pushed me to make the system observable across layers, not just functional. LangGraph spans were useful, but they were not enough on their own, because the behavior I cared about crossed workflow logic, MCP tool calls, and database operations. Adding Langfuse made it much easier to inspect what actually happened on a request instead of guessing from the final response.