Build Your Own Agent
Practical guidance drawn from all 8 frameworks.
Start with TypeScript or Python. Build the agent loop first, then add 3-4 tools, session persistence, system prompt, and a channel adapter. Memory search comes last. Use files for state -- add a database only when you actually need one. For studying codebases: HermitClaw first (smallest), then PicoClaw, pi, Spacebot, IronClaw, OpenClaw.
Core Architecture Decisions
Language Choice
| Language | Pros | Cons | Frameworks |
|---|---|---|---|
| TypeScript | Fast iteration, rich npm ecosystem, same language for web UI | Higher memory, slower startup, no static binary | OpenClaw, pi |
| Rust | Memory safety, single binary, excellent concurrency | Steep learning curve, slower development | IronClaw, Spacebot |
| Go | Single binary, fast compilation, low memory, easy concurrency | Less expressive type system | PicoClaw |
| Python | Fastest to prototype, best ML/AI library ecosystem | Slowest runtime, GIL, dependency management | HermitClaw |
My take: start with TypeScript or Python for prototyping. Move to Go or Rust if you need deployment efficiency or you're targeting constrained environments.
Loop Style
This depends on what you're building:
- Request-response (most frameworks): User sends message, agent processes, returns response. Best for assistants, coding agents, chatbots.
- Continuous (HermitClaw): Agent thinks on its own schedule. Best for research agents, monitoring, autonomous systems.
- Delegation (Spacebot): Orchestrator dispatches to specialized workers. Best for multi-user, high-concurrency, team environments.
State Management
Every framework here stores state as files or SQLite. None require an external database -- IronClaw supports PostgreSQL but also works with libSQL.
Start with files. JSON for structured data, markdown for human-readable content. You can always add a database later, but files are debuggable, portable, and simple.
Essential Components Checklist
Build these roughly in this order:
1. LLM Client
- Call an LLM API with messages and tools
- Parse tool call responses
- Handle streaming (or buffer for simplicity)
- Support at least 2 providers (for fallback)
2. Agent Loop
- Send messages + tool definitions to LLM
- Execute tool calls and append results
- Loop until LLM returns text (no tool calls)
- Set a max iteration limit (10-20)
3. Basic Tools
- Shell command execution
- File read/write
- Web search (Brave API or similar)
- 3-4 tools is plenty to start. Add more as you need them.
4. Session Persistence
- Save conversation history to disk (JSON/JSONL)
- Load history on session resume
- Session key routing (channel + chat ID)
5. System Prompt
- Load identity files (AGENTS.md, SOUL.md)
- Inject tool descriptions
- Add runtime context (date, model, capabilities)
6. Context Window Management
- Estimate token count (chars/4 is fine to start)
- Implement basic compaction (LLM summarization of old messages)
- Emergency fallback: drop oldest messages
7. Channel Adapter
- Define a channel interface (receive messages, send responses)
- Implement one channel (Telegram or Discord are easiest)
- Route messages to correct session
8. Memory
- Workspace files (MEMORY.md pattern)
- Optional: embeddings + vector search for semantic retrieval
- Optional: daily note logging
Memory System Design
Decision Tree
-
Do you need cross-session memory?
- No → Session history + AGENTS.md is enough (pi approach)
- Yes → Continue
-
How much memory?
- Small (fits in system prompt) → File injection (PicoClaw approach: MEMORY.md + daily notes)
- Large → You need search. Continue.
-
What kind of search?
- Keyword only → BM25/FTS is fast and good enough
- Semantic → Add embeddings + vector search
- Both → Hybrid with RRF (OpenClaw/IronClaw/Spacebot approach)
-
Real-time or pre-computed?
- Real-time → Search on every query (most frameworks)
- Pre-computed → Background bulletin synthesis (Spacebot Cortex approach, better for high-traffic)
Embedding Setup
If you go the vector route, here's what I'd pick:
- Model:
all-MiniLM-L6-v2(384 dims, fast, local) ortext-embedding-3-small(OpenAI, better quality) - Storage: SQLite + sqlite-vec (simplest), LanceDB (Spacebot), or PostgreSQL + pgvector (IronClaw)
- Chunk size: 500-1000 tokens per chunk
- Search: Always combine with FTS via RRF for best results
Tool System Design
Minimum Viable Tool Set
Every framework ends up with these:
- Shell execution --
exec/bash/shell - File read -- Read file contents
- File write -- Create/overwrite files
- File edit -- Surgical find-and-replace (better than full rewrites)
Add as needed: web search, web fetch, message sending, browser automation.
Tool Definition Pattern
All of them use the same shape (it matches the LLM APIs):
typescriptinterface Tool { name: string; description: string; parameters: JSONSchema; execute(args: unknown): Promise<ToolResult>; }
Operations Pattern (from pi)
A clean way to make tool I/O pluggable:
typescriptinterface FileOperations { read(path: string): Promise<string>; write(path: string, content: string): Promise<void>; } function createReadTool(ops: FileOperations): Tool { return { name: 'read', execute: (args) => ops.read(args.path), }; }
Now you can redirect tools to SSH, Docker, or any other backend without touching the tool logic itself.
Security Considerations
Threat Model
Your agent has tools, and the LLM decides which ones to call. The LLM can be manipulated by:
- Prompt injection -- Malicious content in web pages, emails, or user input that instructs the LLM to take harmful actions
- Data exfiltration -- The LLM sends private data to external services via tool calls
- Privilege escalation -- The LLM runs commands that exceed intended permissions
Minimum Security (Do This)
- Restrict exec tool to a working directory
- Block obviously dangerous commands (rm -rf /, sudo, etc.)
- Wrap untrusted content with markers (OpenClaw pattern)
- Log all tool calls for audit
Better Security (If You Care)
- Run tools in a container/sandbox
- Implement tool allowlists per context (Spacebot's process separation)
- Add approval workflow for destructive operations (IronClaw pattern)
- Scan for credential leaks in tool output (IronClaw leak detector)
Best Security (IronClaw's Approach)
- WASM sandbox for untrusted tools
- Capability-based permissions (deny by default)
- Credential injection at the host boundary (tools never see secrets)
- Endpoint allowlisting for HTTP requests
- Prompt injection detection (Aho-Corasick + regex)
Recommended Reading Order
If you're reading these codebases to learn agent architecture, here's the order I'd suggest:
-
Start with HermitClaw -- Smallest codebase (~3K lines, 14 files). You can read the whole thing in an afternoon. The Generative Agents memory system and continuous thinking loop are worth understanding even if you end up building something different.
-
Then PicoClaw -- Clean Go code (~20K lines). Shows how to build a complete agent with tools, channels, and sessions while staying resource-efficient. A good model for "the minimum viable agent framework."
-
Then pi -- The extension system and pluggable operations pattern are beautifully designed. Worth studying if you want to build something extensible.
-
Then Spacebot -- The delegation model (Channel/Branch/Worker) is the most creative architecture in this group. Go here for multi-user or high-concurrency designs.
-
Then IronClaw -- Deep security architecture. Go here if security is a priority or you want to understand WASM sandboxing.
-
Finally OpenClaw -- The most complete framework. Save it for last -- it's the most complex, but also the most production-hardened.
"If You Want X, Study Y"
| If you want... | Study... | Specifically... |
|---|---|---|
| Simplest possible agent | HermitClaw | brain.py -- the entire loop in one file |
| Best tool interface design | pi | core/tools/*.ts -- operations pattern |
| Best memory system | Spacebot | memory/ -- typed graph + bulletin synthesis |
| Best security model | IronClaw | safety/ + tools/wasm/ -- 5 security layers |
| Best channel abstraction | OpenClaw | channels/plugins/ -- most mature multi-channel system |
| Best extension system | pi | core/extensions/ -- 20+ event types, full lifecycle |
| Smallest footprint | PicoClaw | The whole codebase -- every design decision is about efficiency |
| Multi-user concurrency | Spacebot | agent/channel.rs -- event loop + delegation |
| Context window management | Spacebot | agent/compactor.rs -- tiered compaction |
| Autonomous agent behavior | HermitClaw | brain.py -- continuous thinking + reflection |
| Hardware/IoT integration | PicoClaw | tools/i2c_linux.go -- direct syscall tools |
| Cross-provider LLM support | pi | packages/ai/ -- unified API with context handoff |