A deterministic compiler over rectified context.
Website · 한국어: README-ko.md
Akela is a context compiler for AI agents: it turns your existing markdown knowledge base — a wiki, a references folder, a team playbook — into a bounded, reproducible context slice per task, and uses evidence from agent runs to govern what that knowledge becomes.
Three tools, three different questions:
RAG asks: what information is probably relevant? Agent memory asks: what should the agent remember? Akela asks: what knowledge is this agent authorized to use for this task — and what evidence justifies changing that knowledge?
If you already have a RAG, keep it: retrieved results enter the slice as just another tracked source.
Everything in Akela is an implementation of one of these:
1 · Knowledge — what your team believes, in markdown you own. Wiki sections, proposed learnings, retrieved notes. Akela indexes it and never writes it.
2 · Compilation — what the agent is allowed to know for this task. Deterministic set logic (no embeddings, no LLM step): same inputs, same slice, byte for byte. Every compile opens with a manifest — the audit trail of what was packed and what was dropped, with reasons. This is a real one:
---
manifest: 1
run: refund-T-4821-15816c
activity: refund
compiler: akela 0.1.4 domain: default scoring: off
sources:
- id: WIKI-refunds#approval tier: must lines: 2
- id: LRN-20260829-01 tier: lrn lines: 3
- id: WIKI-refunds#method tier: should lines: 2
dropped:
- id: WIKI-shipping#carriers reason: general-scope
---
The question "was the stale rule in front of the agent?" is answered by a file, not a guess.
3 · Evidence — what happened when the agent used that knowledge. The agent reports what it applied and what the outcome contradicted; an append-only, content-hashed log accumulates a record per rule. Rules that keep failing are flagged falsified — the mechanism no memory tool ships — and provably stop appearing. Rules that keep proving out become promotion candidates. A curator (you, or an agent whose edits you review) reads the counts and decides; nothing changes your knowledge base silently.
The full vocabulary — scopes, tiers, learnings, fingerprints, domain packs — lives in the docs; every term is one of these three primitives wearing work clothes.
Born inside a QA automation tool, where the loop ran on real work first; extracted and generalized so any domain — support, ops, research, QA — can run it. That tool (QABuddy) is now Akela's reference consumer, running its full test suite against this engine in CI. Zero dependencies, Node ≥ 18.
The whole claim set was put through our experiments: three isolated agents — a trainee that works tasks, a curator that reads akela stats, a silent script that updates the source when the world shifts — and a deterministic grader outside the loop, run across many conditions and seeds with every result archived. The full experiment program (harness, task beds, result archives, findings) will be published separately.
The buyer's table — files / maintained wiki / RAG, each without → with Akela, same bed, same model, same grader, after the rules change:
| files | maintained wiki | RAG | |
|---|---|---|---|
| accuracy | 0.53 → 0.51 | 0.96 → 0.90 | 0.89 → 0.81 |
| stale rules in context | 26/26 → 21/26 | 17/26 → 2/26 | 23/26 → 21/26 |
| context tokens / task | 35,690 → 139 | 35,773 → 138 | 35,772 → 201 |
| $ / correct answer | $2.37 → $1.48 | $1.17 → $0.81 | $1.45 → $1.02 |
Stated honestly, in the order the data forces:
- Maintenance beats tooling. The biggest jump anywhere is unmaintained files → maintained wiki (0.53 → 0.96), from nothing but someone keeping the source current. Akela's job is making that affordable and provable, not replacing it.
- On raw accuracy, dumping everything wins every pair by a hair — and stayed flat to 353k tokens/task in a scaling test. If today's accuracy is all you measure and tokens are free, you don't need this tool.
- Akela wins everything structural, in every pair: context 257× smaller at any knowledge-base size, better cost per correct answer, and a knowledge base that is provably clean (2/26 → 0/26 stale at 10× scale) instead of attentionally lucky (the dump carried stale rules in 17–19 of 26 contexts at every scale and dodged them until it didn't).
- Unlearning works unattended; relearning needs the source. With accept/reject alone the trainee ends, honestly, at "rule absent". Corrections that arrive through the wiki are adopted without anyone being told (r=0 on trusted classes); retrieved corrections graduate into the wiki through the promotion path.
- The residual failure is epistemic, reproduced 3/3: a correct, freshly-updated rule can be retired on sincere wrong distrust — accurate quotes, correct attribution, honest counting, wrong outcome. Every mechanism checks whether evidence is honest; none can check whether it is right. That is why the curator exists.
Akela has two users with different jobs: you set it up and curate; your agent operates it on every task.
You, once — install and point it at your knowledge:
npx akela init --knowledge wiki # akela.json + LEARNINGS.md + the three agent protocols (PROTOCOL, ONBOARD, CURATE)
# --knowledge <dir> path to your existing markdown folder — wiki/, docs/, kb/, notes/, anything
# --domain <pack> optional domain pack name or JSON path (default: "default")
# RAG is not an init flag — plug yours in after, one line in akela.json ("RAG, if you have one" below)
npx akela index # every addressable section: <NS>-<file>#<id> tier scopeYou, once — wire your agent. init wrote the operating protocol to akela/PROTOCOL.md inside your project (next to LEARNINGS.md; commit it). A file on disk does nothing by itself — an agent follows only what its harness loads — so the wiring is one line in the instruction file your agent auto-loads (CLAUDE.md for Claude Code, AGENTS.md, .cursorrules, or your system prompt):
Follow
akela/PROTOCOL.mdfor every task.
That line is the entire integration; without it, Akela is installed but unwired. (init detects your instruction file and names it.)
You + your agent, once — scope the knowledge. An unscoped wiki packs nothing (Akela never guesses relevance). init also wrote akela/ONBOARD.md — tell your agent "Follow akela/ONBOARD.md" and it drafts the initial scoping (which sections serve which activities, at what tier) as a review table; you approve, and the approved scoping is applied as config or tags. Ten well-scoped sections is a working start.
Your agent, every task — automatically, per the protocol:
akela compile --activity support --task T-123 # → slice.md: its only source of domain knowledge
# … works the task from the slice …
akela log applied WIKI-refunds#under-50 # "I relied on this rule"
akela log contradicted LRN-20260822-01 --note "…" # "the outcome proved this rule wrong" (verbatim quote)
akela log outcome --status DONE # closes the runYou, ten minutes a week — curate from the counts:
akela stats # per-source evidence + findings: promotion candidate · falsified · restates · dormant
akela check # validates the knowledge base after your editsThe counts recommend; you decide — and even the review legwork is delegatable: init also writes akela/CURATE.md, so "Follow akela/CURATE.md" turns the whole routine into an agent-drafted table you approve.
init generates three protocols; your agent runs the cycle, and you supply only judgment — one review table and a yes/no at each decision point:
| moment | who acts | protocol |
|---|---|---|
| every task | agent: compile → work from the slice → log evidence | PROTOCOL.md |
| initial scoping, and whenever new pages appear | agent drafts scope/tier, you approve (every compile reports unscoped drift, so new pages are noticed within hours) |
ONBOARD.md |
| critical finding mid-task | agent asks whether to run the review now | PROTOCOL.md → CURATE.md |
| weekly (or per sprint) | agent runs stats, reads the notes, hands you one review table; approved edits applied and validated | CURATE.md |
The division is the design: the agent drives everything except judgment; you supply only judgment, and only when there's evidence to judge. Full walkthrough: docs/guide.md.
For the full picture in diagrams — the evidence loop, selection, a rule's life, and how retrieved notes graduate — see docs/how-akela-works.md. For day-to-day usage (tagging, the agent protocol, the curation routine) see docs/guide.md. Quick answers to first-use questions: docs/faq.md. Shipping Akela inside your own tool: docs/embedding.md.
your markdown (wiki / references) ← you author; Akela indexes
───────────────────────────────────
LEARNINGS.md LRN-20260822-01 … ← proposed by runs; promoted or retired by you
───────────────────────────────────
akela compile → slice.md + manifest ← deterministic; must-floor, scope, project overrides
akela log / fp → learnings-log.jsonl ← read path writes back: applied · contradicted · outcome
akela stats → findings ← arithmetic, not judgement; you approve every change
Every ## in a knowledge root is a source with a stable id. Two ways to get there:
- Tagged — the line after a heading carries
<!-- akela: id=refunds-under-50 scope=support tier=must -->. Ids are explicit; parse errors are loud. (The legacyqab:tag name is accepted for content migrated from the parent tool.) - Derived (
"untagged": "derive") — ids come from heading slugs; scope defaults toall, tier toshould. Zero edits to an existing wiki. Derived sections contribute nothing until you scope them (compiler.scope), and show up underdropped: general-scopein every manifest until you do — selection is yours, not the indexer's.
A pack says what kind of work happens here: the activities, the deterministic profile probes, the closed vocabulary of failure fingerprints, the outcome statuses. domains/default.json has no probes and a generic vocabulary. Every pack field can also be declared inline in akela.json (inline wins), so most projects never write a pack file at all; extract one when a second project shares the vocabulary, and point "domain" at any JSON path. A pack belongs to the domain that defines it, not to the engine — a tool built on Akela ships its own pack to its own users. Full concept and field reference: domains/README.md.
A retriever is any command. It gets {activity, task, profile} on stdin and returns [{id, heading, text}]. Its items enter the slice as EXT-<name>#<id>, tier context, after the floor, marked via: retriever:<name> — and they are cited and counted like every other source. Akela never lets a retriever remove or reorder anything; it lets the retriever audition, and your run logs decide whether what it surfaced was ever applied.
docs/DESIGN.md — the problem, the design principles, the architecture with diagrams, and the reasoning behind every non-obvious decision — including the failures each one answers and the limits stated honestly.
0.1.4 — engine extracted, generalized, and hardened by the experiment program and by its first real consumer (QABuddy runs its full 1,275-check suite against Akela in CI); 139-check test suite, ubuntu + windows × Node 18–24. The evidence loop is version-scoped (blame binds to the content hash a run actually saw; rewrites start clean), the capture gate is Unicode-aware arithmetic validated against an out-of-domain Korean corpus and an adversarial bed, and a byte-level replay showed the extracted engine reproducing its parent tool's real recorded compile slices exactly. Every non-obvious design decision was forced by an observed failure and is recorded with its reason in docs/DESIGN.md §5. Known open items: an evidence-only stats view for large knowledge bases (the full table grows with corpus size), tombstones for values removed by page edits, and a promotion bar that requires surviving disconfirmation — the last two are the research frontier the replication named.
The thesis, in one line: AI agents are probabilistic — the knowledge system surrounding them doesn't have to be. Akela is deterministic control over what enters an agent's context, an audit trail for every decision, and an evidence-governed path for changing the knowledge underneath.
MIT
{ "domain": "default", "knowledge": [ { "path": "references", "namespace": "REF" }, { "path": "wiki", "namespace": "WIKI", "untagged": "derive" } ], "learnings": "akela/LEARNINGS.md", "runs": ".akela/runs", "activities": ["support", "triage"], "profile": { "tier": [ { "task": "^VIP-", "value": "vip" }, { "value": "standard" } ] }, "fingerprints": ["wrong-answer", "stale-rule", "missing-context"], "compiler": { "scope": { "WIKI-refunds#under-50": { "add": ["support"] } }, "retrievers": [ { "name": "rag", "cmd": "node scripts/retrieve.js" } ] } }