AXIOM
An intelligent software engineer
- Role
- Solo build, design
- Type
- Personal · Pre-implementation
- Systems
- LangGraph · MCP · Tree-sitter
- Scale
- 5 MCP servers · 6 data models
Objective
Not a chatbot. Not editor autocomplete. An agent that reads a codebase, plans a fix, edits files, runs tests, and proposes a reviewable diff — the way a junior engineer works a ticket.
$ yagent fix "bug #23" → reads project, plans, edits files, runs tests, iterates on failures, proposes a diff awaiting approval.
Why this is hard: the failure mode isn't "the model writes bad code" — it's that a plausible-looking diff passes review and breaks something the tests didn't cover. An agent that edits without re-running the suite is a liability, not a tool. The loop has to distrust its own output by default and treat a green test run as the only evidence that counts.
Decisions
The core mindset shift
The LLM is not the center of this system — the agent runtime is. The LLM is one interchangeable component alongside memory, tools, and planning; swapping Claude for a local Ollama model should never touch planning, memory, or tool logic.
Why hand-written MCP servers?
AXIOM implements its own MCP servers — filesystem, git, shell, browser, database — one per tool domain, over STDIO/SSE transports. Understanding the protocol at the implementation level, not just consuming a third-party server, is what makes it debuggable and extensible later.
Why Tree-sitter?
A Project Index built from Tree-sitter parses functions, classes, imports, and symbol references into a queryable structure — so the Planner's first move is an index lookup, not a raw file read.
Why dual memory (Postgres + vector DB)?
Structured memory (Postgres) holds preferences and conventions. Semantic memory (vector DB) holds embeddings of past fixes for similarity recall — together they let AXIOM get better at one codebase over time, instead of starting cold on every run.
Architecture
Runtime architecture
User → Conversation Manager → Planner → Model / Memory → Tool Router → Filesystem / Git / Shell MCP → Test Runner
- The Planner never writes code directly — it only ever calls a tool.
- The Tool Router is the only subsystem that touches the outside world.
- The Memory Manager stores preferences and recalls semantically similar past fixes.
Execution loop
Plan → Edit → Test → Pass → Complete / Fail → Read failure → Fix → Retest
- The runtime repeats this cycle until all tests pass or the retry budget is exhausted.
Result
AXIOM hasn't shipped yet — the design is complete and implementation is underway. Every model swap or prompt change will be measured against a benchmark suite (seeded bug fixes, spec-to-endpoint generation, behavior-preserving refactors) before being called an improvement.
By the numbers
Stack
Python, FastAPI, LangGraph, Tree-sitter, MCP, Postgres, Vector DB, Docker
Lessons learned
- The first architecture pass had Planner, Coder, Reviewer, and Tester as four separate agents from day one. It didn't survive contact with the design doc — four agents means four places for context to drift before a single line of code exists. Collapsing back to one agent was a direct result of that assumption breaking.
- I'd design the evaluation benchmark suite before the agent loop itself, not after — without it, early progress is indistinguishable from a lucky demo.
- I'm avoiding a plugin system until the core tool set has been used in anger — extensibility designed before real usage tends to guess wrong about the seams.
