WhatsApp Go Assistant
和語屋 · 記憶 · 人格
wagoya puts a language model behind a WhatsApp number. She has a persona of her own, a long memory of everyone she meets, a set of tools for reminders, backlogs and the web, and she can hand coding work to Claude Code on your laptop. It all runs as one static Go binary.
— reminder saved · survives restarts —
wagoya remembers people, not just conversations. What she learns about someone in one group is there in every other chat and DM.
Every profile is keyed by the person's WhatsApp ID, never their display name, so nobody can pose as someone else by renaming themselves. Namesakes get tags like Omar #9249.
Each fact records who said it and how far that source is trusted: the owner, the person themselves, another member, or Rin's own guess. Hearsay ranks lower and never overrules a better source.
There's no cap on facts. Instead of stuffing the prompt, she searches with SQLite FTS5 plus embeddings, so “what does he do for work” finds Job: accountant.
Each person also gets a prose profile of up to 400 words. A curator rewrites it only when there's a reason, like a new role, a shift in views or how they treat her, and logs that reason.
A background curator reads every chat she's in, every 16 messages or after 10 quiet minutes. It saves facts and nicknames, merges stray profiles, and keeps a rolling summary of each chat.
Corrections retire a fact instead of deleting it, so history stays. Short-lived states like “on the way home” expire after a day, and a repeated bait overwrites one fact instead of piling up fifty.
A single character with a name, a look, a voice and quirks, stored with its full version history.
@Rin from now on be more cheerful and she writes her whole merged persona back. Requests from anyone else are refused in character and logged.Built-in tools the model calls itself. Every call is checked, and mistakes come back to her as errors rather than failing silently.
What she knows, and how she learns it
search_factsSearch everyone she knows by handle, name or fact text, combining keywords and meaning.save_factStore a short, labelled fact about anyone in the chat, or anyone only talked about.invalidate_factMark a fact as no longer true. It stays as history.save_memoryTag chat context (a plan, a decision, a preference) for later recall.read_profileRead a person's full prose portrait.chat_historySearch older messages of this chat, kept for 72 hours.Reminders, nags and a backlog of your own
schedule_message“Remind me to eat at 12.” Owners can make it repeat hourly, daily, on weekdays or weekly, or send it to another group.list_scheduledUpcoming reminders, with the time left worked out by the server.cancel_scheduledCancel one.add_taskAdd to your private backlog: name, description, due time, category.update_taskMove a task between backlog, ongoing, hold and done.list_tasksYour tasks, soonest due first. You're reminded the day before, at 09:00.The web, any API, any MCP server
web searchWeb search and link reading, run by the model provider.http_requestCall any public HTTP API. She can search or page a large response, like a 400 KB OpenAPI file, so she reads the docs instead of guessing.mcp__<server>__<tool>Any MCP server, local or remote, from a Claude Desktop-style mcp.json. Owners only./keyOwners store an API key once. It's added to requests to that host, and the model never sees it.Coding work through Claude Code (owners only)
ask_claude_codeQueue a task, or a follow-up to one, in the owner's own words.answer_claude_codeRelay the owner's answer to a question Claude Code asked.claude_tasksList tasks and fetch any task's full report.cancel_claude_taskStop a queued or running task.push_claude_branchPush the branch of an older task.Say “have Claude Code add X to my project.” A small runner on your laptop picks up the task over SSH, runs Claude Code in the repo with your own login, and reports back in the chat.
The task is queued with your exact words.
Claude Code needs a permission or an answer. Reply yes or no, and the server reads it, not the model.
The full report, the commits and the diff stat, then a line from Rin.
“Also add a test for #3” resumes the same session.
Built for real group chats with real people in them.
http_request refuses loopback, private, link-local and metadata addresses at connect time./reset, /key, /mute @person 30m and /unmute are handled by the bot itself, never stored or sent to the model.Choose the model behind her. Input is capped at 128k tokens by default; old transcript lines are trimmed first.
| Provider | Auth | Notes |
|---|---|---|
anthropic | API key | Claude Messages API with the tool loop, server-side web search and fetch, image input |
anthropic | Claude Code OAuth | Claude Code CLI in headless mode, on a subscription, with local tools off |
openrouter | API key | Any OpenRouter model, cheapest provider first at fp8 or better, with an image fallback for text-only models |
Use a spare number, not your own. She sends real messages.
# fetch the grimoire $ git clone https://github.com/kritzerenkrieg/wagoya && cd wagoya $ cp .env.example .env # a provider key and your WHITELIST $ go run . # scan the QR, or set PAIR_NUMBER # for a Linux server $ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o wagoya .