waku-agent: a local-first agent harness where the loop is about 95 lines
Waku Waku! Waku Agent is a local-first AI agent harness you actually own, including loop, memory, eval, all in code built to stay legible as it grows.
At a glance
- What is it?
- Waku Agent is an MIT-licensed Python harness that keeps the agent loop, memory and evals in readable code and stores state in one SQLite file. It is aimed at engineers who want to step through an agent rather than configure a framework.
- Who is it for?
- Adopt waku-agent if you want to read the loop, inspect the gate decision for each turn, and keep memory in a SQLite file you can open yourself. Do not adopt it if you need a hosted multi-tenant service or a framework with a broad plugin ecosystem; this is a v0.1.x codebase with two tagged releases.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem waku-agent addresses: agent state you cannot open
Most agent stacks hide the parts that decide behaviour. The prompt assembly, the decision to retrieve a memory, the tool loop, the scoring of a response: all of it lives behind an abstraction you install but do not read. waku-agent takes the opposite position. The README describes it as a local-first personal assistant that shows four pillars (harness, loop, memory, eval and LLM-Ops) with, in its words, no frameworks hiding the good parts. The audience is narrow and specific: a Python engineer who wants to step through an agent turn in a debugger, or a developer building a personal assistant on their own laptop and unwilling to ship conversation history to a vendor. The claim that the loop is about 95 lines of plain Python is the whole pitch. If that number is accurate, the loop is small enough to read in one sitting, which is a different proposition from an orchestration library where the control flow is spread across dozens of files. The second half of the pitch is memory. The README states that memory is one SQLite file at .waku/state.db, and that it is yours to open and read. That is a concrete architectural commitment, not a slogan: it means no vector database service, no hosted memory API, and no export step to get your own data out.
Four pillars, one process, and a gate that decides whether to remember
The architecture is described as four pillars. The harness is the outer structure that receives a message and routes it. The loop is the turn engine, roughly 95 lines according to the README, and it calls tools and produces a reply. Memory is split into semantic facts, episodic records and procedural skills, and the README adds two mechanisms on top of that split: a gate that decides whether to remember at all, and a consolidation pass that decides what to keep. The eval pillar combines deterministic tests with LLM-as-judge scoring and a release gate. The dashboard is where these become visible. Each tab maps to a pillar and to real files, and the Overview tab shows the gate skip and retrieve split alongside cost and latency. The Gateway tab tags every message by source, so a conversation that started in the terminal and continued in the browser shows as cli and dashboard in the same thread. The Loop tab records each turn with its gate decision, tool calls, tokens and cost. This is the part worth examining closely: the gate is not a retrieval threshold buried in a config file, it is a per-turn decision surfaced in the UI and in the Ops tab history. The README gives a test for it. Ask when you are swimming with Sergey, then ask what 12 times 8 is, and the second question should skip retrieval. Whether that skip is correct on your own data is something you can only learn by running it.
Getting it running: pip, uv, and the two doors into the same agent
There are two documented install paths. The short one is pip install waku-agent followed by waku for the terminal or waku dashboard for the browser interface on localhost:7777. The repository path is git clone, then uv venv and uv pip install -e ., then cp .env.example .env, then uv run waku or uv run waku dashboard. The README notes that uv run waku needs no virtual environment activation, and lists three invocation styles: uv run waku dashboard for zero activation, source .venv/bin/activate followed by a bare waku, or uv tool install . to put waku on the path globally. Configuration is environment based. WAKU_PROVIDER selects the model provider, and the README names Anthropic as the default along with OpenAI, Gemini, DeepSeek, MiniMax, Kimi, GLM, OpenRouter, OpenCode Zen and OpenCode Go. The README states that a roughly 60-line adapter in waku/loop/models.py handles the differences between them. It also says the program will tell you which key to set the first time you run it. Telegram is opt-in through TELEGRAM_BOT_TOKEN, and the same process then starts the bot. The dashboard binds to 127.0.0.1 and is described as a small web server you own, with a frontend made of plain static files and no build step. One tool in the examples needs an extra key: the multi-step calendar scenario uses search_web and requires a Tavily key, which the README says is pasted in the Connections screen.
What the multi-tool turn reveals about loop engineering
The README's showcase scenario is a single instruction: search for the World Cup games still left to play and add each one to your calendar. The documented result is eight loop iterations, with search_web called several times, then create_event called for each remaining match. The Loop tab is said to show iter 8. This is a useful test case because it exercises the parts that usually break in hand-rolled agents. The loop has to decide when it has gathered enough search results, carry that context forward, and then emit a variable number of side-effecting tool calls. A loop that terminates on the first tool result would fail this; one that never terminates would keep searching. The README does not state the termination condition, the per-iteration token budget, or what happens if the model keeps calling search_web without converging. Those are the questions to answer from the source before trusting the loop with side effects such as create_event. The dashboard is the intended instrument here: the Overview diagram is described as lighting up as a message flows through the harness, with the gate lighting up, the loop calling a tool, the reply returning, and memory updating. Watching that sequence on a real turn is more informative than reading a description of it, which is presumably why the README points at a 20-minute code walkthrough video.
Where waku-agent is the wrong tool
The local-first design is a constraint, not a feature toggle. The dashboard is documented as binding to 127.0.0.1 with nothing leaving the laptop, and memory is a single SQLite file. If you need multiple users sharing one agent, or a hosted endpoint that other services call, this architecture works against you. SQLite plus a loopback server is not a multi-tenant deployment story, and nothing in the supplied material suggests one. The second limitation is ecosystem. The README frames the project against frameworks that hide the good parts, which is a fair position, but the trade is that you get the integrations the repository ships rather than the ones a large community has written. Tools are grouped by origin in the Tools tab and MCP connectors are listed there, so extension appears to go through MCP and local tool definitions, but the material does not describe a plugin registry or a third-party catalogue. The third limitation is maturity. There are two tagged releases, v0.1.0 and v0.1.1, the latter adding agent graphs, with the most recent push dated 2026-08-29. A v0.1.x project with a small release history means interfaces can move. If your agent is load-bearing infrastructure, pin a version and expect to read the diff before upgrading. Finally, the eval pillar deserves scrutiny rather than assumption. The README says deterministic tests and LLM-as-judge sit side by side with a release gate, but it does not specify what the gate blocks or what the default eval suite covers. Treat the gate as a starting point to extend, not as evidence that the agent is correct.
How it differs from LangGraph and from a hosted assistant
The closest comparison named in the material is agent graphs, which arrived in v0.1.1 and appear in the dashboard's Graph tab as a live triage topology drawn from the engine itself. LangGraph takes the position that an agent is a graph you declare, with nodes, edges and a state object, and the framework manages execution. waku-agent takes the position that an agent is a loop you read, with graph workflows layered on top in a later release. The difference in practice is where you look when something goes wrong. In a graph framework you inspect the graph definition and the state transitions the runtime produced. Here you open the Loop tab for the turn, see the gate decision and the tool calls, and if that is not enough you open the roughly 95-line loop file. The other comparison is a hosted personal assistant. Those give you a managed memory store and a polished client, and you accept that the memory lives on someone else's infrastructure. waku-agent inverts that: memory is a file, the server is on loopback, and the interface is plain static files you can modify. The cost is everything you would otherwise get for free, including sync across devices, mobile clients beyond the Telegram gateway, and a support channel. The README's own framing, that this is code you can read in an afternoon, tells you which side of that trade the project has chosen.
Maintenance cost and what the MIT licence leaves open
The project is MIT licensed, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are retained. That is the standard permissive arrangement, and it means you can vendor the code or ship it inside a product. It does not settle anything about the models you connect to: your provider's terms, and the data your prompts carry to that provider, are a separate question from the repository's licence. The README's local-first claim covers storage and the dashboard server, not inference, since every provider listed is a hosted API. If a turn sends memory contents to Anthropic, OpenAI or OpenRouter, that data leaves the laptop regardless of where state.db lives. Read waku/loop/models.py to see what is included in the request payload before assuming otherwise. On maintenance, the picture is a single-maintainer project with a stated funding model (a coffee link in the README) and an accompanying video series. The upgrade path is ordinary Python: pin the version, read the release notes for v0.1.x, and check whether the SQLite schema in .waku/state.db changed, since a schema migration is the one upgrade that can affect data you care about. The Data tab's read-only SQL console over state.db is the quickest way to inspect the schema before and after an upgrade.
Editorial conclusion
Adopt waku-agent if you want to read the loop, inspect the gate decision for each turn, and keep memory in a SQLite file you can open yourself. Do not adopt it if you need a hosted multi-tenant service or a framework with a broad plugin ecosystem; this is a v0.1.x codebase with two tagged releases. Before committing, run waku dashboard and open the Data tab to confirm the schema of .waku/state.db matches how you intend to store facts, then check the eval release gate in the Ops tab to see what a passing verdict actually covers.
Community notes