All posts
ENGINEERINGPRODUCT

Your Trading Journal as Durable Agent Memory: An Agent-Maintained Knowledge Base

TradeLoop Engineering·May 1, 2026·9 min read

The Compounding-Knowledge Problem

Talk to Claude about a name over a few weeks. By the next session, every conversation starts from scratch. Claude can't tell you "based on the thesis you wrote when you opened this NVDA position plus the 8-K from last Thursday, here's what's changed." There's no accumulation. RAG over your past chats helps a little, but RAG retrieves; it doesn't synthesize.

Andrej Karpathy [described the alternative pattern](https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f) earlier this year: the LLM incrementally builds and maintains a persistent knowledge base — a structured, interlinked set of markdown files between you and the raw sources. Add a new source and the LLM doesn't just index it; it reads it, integrates it into existing pages, notes contradictions, updates summaries. The base keeps getting richer.

For a trader, that's a journal that actually thinks: theses that update as the story changes, trades cross-linked to the reasoning behind them, lessons that surface when you're about to repeat a mistake. We built it as a TradeLoop skill.

The Three-Layer Architecture

~/.tradeloop/journal/<name>/
├── raw/                    immutable sources
│   ├── filings/            SEC EDGAR 10-K / 10-Q / 8-K / Form 4
│   ├── research/           perplexity / firecrawl output, articles
│   ├── data/               indicator snapshots, price series, CSVs
│   ├── sentiment/          filed FinTwit / Reddit reads
│   ├── messages/           important emails / broker alerts
│   └── media/              chart screenshots
├── journal/                LLM-derived synthesis
│   ├── index.md            curated catalog (Open positions + Watchlist)
│   ├── log.md              chronological trade + decision log
│   ├── theses/             one page per name you have a view on
│   ├── tickers/            entity pages per symbol
│   └── reviews/            "post-trade reviews filed back"
├── .git/                   every write auto-commits
└── .journal-fts.sqlite     BM25 search index, gitignored

Three layers, each with a clear owner:

  • raw/ — you own. Immutable once written. The journal cites it but never edits.
  • journal/ — the LLM owns entirely. Creates, updates, cross-references, deletes.
  • schema — co-evolved between you and the LLM. Lives in the skill's SCHEMA.md, returned by the journal_rules() tool.

raw immutability is enforced in code, not just convention. Calling write_page on an existing raw/... path returns { committed: false, reason: "raw_immutable" }. Schema rule and IO layer agree — your original filing or research snapshot can't be silently overwritten.

10 Tools, All I/O

The skill exposes 10 MCP tools to the agent:

journal_init   bootstrap a journal at ~/.tradeloop/journal/<name>/
journal_rules  return the full maintenance contract (schema)
read_page      read any page (raw/ or journal/)
write_page     write + auto-commit; returns dead links
list_pages     filter by prefix / type / tag
search         BM25 full-text via SQLite FTS5
attach_file    copy a binary (chart png / filing pdf) into raw/
delete_page    git rm + report inbound links
move_page      git mv + report inbound links
log            append to journal/log.md with structured prefix

Notably no `ingest_source` tool. We deliberately don't bake "read source → suggest pages" into the skill — that's reasoning, and reasoning belongs in the agent. The skill is pure I/O. The agent reads sources with its own tools (the market-data tools, Read, WebFetch), decides what to file, and calls write_page 5-15 times in one pass.

Search: SQLite FTS5 over Embeddings

The obvious choice for a search backend is embeddings + a vector store. We chose SQLite FTS5 with BM25 instead:

Stdlib only. sqlite3 is in Python's stdlib on every platform, FTS5 ships compiled into nearly every build. No pip install, no external service — fits the local-first model.

BM25 with column weights handles "title vs body" naturally. We weight title 5×, tags 2×, body 1×. A thesis page titled "NVDA" wins over one that mentions NVDA in passing. Embeddings would need a separate "search title heavily" trick on top.

At journal scale (<1000 pages) it's instant. A 250-page corpus searches in 1-10ms. Index rebuilds in 50-200ms when stale.

Phrase + boolean + prefix queries work natively. "earnings beat" NOT guidance is a single FTS5 expression. With embeddings, that's a custom reranker.

The index lives at <root>/.journal-fts.sqlite, gitignored — pure derived state. Delete it and the next search rebuilds from markdown. The design principle: markdown is the truth source, everything else is regenerable.

Write-Time Link Integrity

Every write_page parses [[journal/...]] and [[raw/...]] references in the body. References that don't resolve come back as dead_links: [...]. The agent sees a dangling link the moment it writes a thesis that points at a filing you haven't saved — not three sessions later.

delete_page and move_page go further: they scan all pages for *inbound* references to the path being changed and return inbound_links: [...]. Delete a stale thesis and the agent gets back the list of pages whose links it needs to fix — and follows up in the same conversation.

We deliberately do not auto-rewrite links on rename. Alias syntax and section anchors make safe regex rewriting unreliable, and silent corruption is worse than a few extra agent edits.

Cross-Skill Ingest, Agent-Driven

Karpathy's gist assumes you manually drop files into raw/. TradeLoop opens a second route: other skills produce content the agent files into `raw/` in the same conversation. There's no hardcoded auto-ingest hook — every write still goes through the agent — but the SCHEMA maps source types to subdirs so the agent does the right thing without thinking:

  • the SEC EDGAR tool returns a filing → agent writes raw/filings/<symbol>-8k-<date>.md when you say "file this 8-K"
  • firecrawl.scrape returns markdown → agent writes raw/research/<slug>.md when you say "save this writeup"
  • the indicator tool returns a snapshot → agent writes raw/data/<symbol>-<date>.md when you want to capture the setup at entry

The journal becomes a convergence point: every content-producing TradeLoop skill has a natural destination subdir, and the agent learns the pattern from the SCHEMA in one round-trip. After a few weeks of normal trading — filings saved, theses written, post-trade reviews filed — you have a journal that reflects what you actually did and thought. The compounding happens through agent muscle memory, not background daemons.

When This Isn't Right

A journal adds value when knowledge compounds. It doesn't when:

  • You're asking one-off questions ("what's BTC right now")
  • The session is a quick price check, not building a view
  • You want speed over structure

The schema explicitly tells the agent don't ingest: throwaway lookups, idle speculation, a setup you already passed on. Filing trivia creates noise that harms recall.

What It Costs

Local markdown + git + SQLite FTS5 = zero per-call cost beyond filesystem I/O. The agent's token cost for an ingest is real (5-15 write_page calls with frontmatter + body) — filing a thesis plus a 10-K summary runs 8-12K agent tokens. That's the price of compounding synthesis, cheap compared to re-deriving the same view every session forever.

The journal ships as the journal skill, automatically discovered by the daemon's hot pool. Available at the Free tier — no quota, no upstream service, no API key. Open ~/.tradeloop/journal/default/ in Obsidian on the side and watch the agent write your book.

Try TradeLoop for free

Connect 50+ tools to Claude, Cursor, and Windsurf in under 5 minutes. No API keys required to get started.

Get Started Free
$curl -fsSL https://tradeloop.top/install.sh | sh