Most agents hardcode their personality and knowledge into the source code. This chapter shows a better way: keep everything in plain files on disk. Swap a file, change how the agent behaves — no code changes needed.
The Big Picture
Chapter 6 answers: how does an agent have personality, memory, and knowledge?
The answer: all from files on disk, not hardcoded.
STARTUP (once): EVERY TURN:
═══════════════ ════════════
BootstrapLoader User input
SOUL.md │
IDENTITY.md ─────> _auto_recall()
TOOLS.md search memory
MEMORY.md │
AGENTS.md ▼
USER.md build_system_prompt()
│ 8 layers assembled
SkillsManager │
scan SKILL.md ▼
│ LLM API call
cached every turn
The BootstrapLoader is the startup routine that reads all the files in your agent’s directory and caches them before the first turn.
Swap a file = change behavior. Zero code changes.
Four Key Concepts
1. 8-Layer System Prompt Assembly
Built every turn. Order = priority (earlier = stronger influence):
Layer 1: IDENTITY.md → "Who you are"
Layer 2: SOUL.md → "Your personality" (early = dominant)
Layer 3: TOOLS.md → "How to use tools"
Layer 4: Skills → "Available skills"
Layer 5: MEMORY.md + auto-recalled memories
Layer 6: HEARTBEAT.md, AGENTS.md, USER.md
Layer 7: Runtime → agent_id, model, current time
Layer 8: Channel hint → "You respond via Discord/Terminal/etc"
LLMs tend to weight earlier content in the prompt more heavily. By placing personality (SOUL.md) in layer 2 — right after the agent’s name — it becomes the dominant behavioral influence for the rest of the conversation.
2. Memory — Two-Tier Storage
MEMORY.md — Evergreen facts, manually maintained and permanent. Example: “User prefers concise answers. Timezone UTC+7.”
daily/YYYY-MM-DD.jsonl — Daily logs written by the agent at runtime.
{"ts":"...", "category":"fact", "content":"..."}
The agent writes memories via a memory_write tool and searches them via memory_search.
3. Auto-Recall — Automatic Every Turn
Before every LLM call, the user’s message is searched against memory. Top 3 results are injected into Layer 5. The user doesn’t ask — it happens automatically.
memoryContext := autoRecall(userInput) // search top-3
systemPrompt := buildSystemPrompt(memoryContext)
4. Hybrid Search Pipeline (mini-RAG)
RAG (Retrieval-Augmented Generation) means the agent retrieves relevant notes from memory and adds them to the prompt before calling the LLM. This makes it much more accurate for personal or domain-specific use.
1. Keyword (TF-IDF) → top-10
2. Vector (hash) → top-10
3. Merge → 70% vector + 30% keyword
4. Temporal decay → older memories score lower
5. De-duplicate + diversify (MMR) — avoid surfacing five memories that all say the same thing
↓
top-k → inject into system prompt
This is a RAG pattern without an external vector database — pure Python. For production at scale, swap in a real vector DB (Chroma, Qdrant, Pinecone) for better accuracy.
File-Based vs External Memory
| Pure File-Based | External (Qdrant, etc.) | |
|---|---|---|
| Setup | Zero — works immediately | Install + config |
| Cost | Free | Free self-host / paid cloud |
| Search quality | TF-IDF + hash — good enough | Embedding API — more accurate |
| Scale | Hundreds of entries | Thousands+ |
| Privacy | 100% local | Depends on setup |
For personal agents: file-based is fine. For enterprise with large knowledge bases, external RAG is worth the setup cost.
Takeaway
- System prompt — files on disk, not hardcode → change files = change behavior
- 8 layers, order = priority → SOUL at layer 2 for dominance
- Memory: MEMORY.md (evergreen) + daily JSONL (runtime)
- Auto-recall — inject relevant memories into every turn automatically
- Hybrid search: TF-IDF + vector + MMR → foundation of the RAG pattern