GitHub - amita-seal/wa-metaai: Use Meta AI (inside WhatsApp) as an OpenAI-compatible LLM provider for opencode, with synthesized tool calling · GitHub
/" data-turbo-transient="true" />
Skip to content
Search or jump to...
Search code, repositories, users, issues, pull requests...
-->
Search
Clear
Search syntax tips
Provide feedback
--><br>We read every piece of feedback, and take your input very seriously.
Include my email address so I can be contacted
Cancel
Submit feedback
Saved searches
Use saved searches to filter your results more quickly
-->
Name
Query
To see all available qualifiers, see our documentation.
Cancel
Create saved search
Sign in
/;ref_cta:Sign up;ref_loc:header logged out"}"<br>Sign up
Appearance settings
Resetting focus
You signed in with another tab or window. Reload to refresh your session.<br>You signed out in another tab or window. Reload to refresh your session.<br>You switched accounts on another tab or window. Reload to refresh your session.
Dismiss alert
{{ message }}
amita-seal
wa-metaai
Public
Notifications<br>You must be signed in to change notification settings
Fork
Star
main
BranchesTags
Go to file
CodeOpen more actions menu
Folders and files<br>NameNameLast commit message<br>Last commit date<br>Latest commit
History<br>6 Commits<br>6 Commits
.gitignore
.gitignore
README.md
README.md
go.mod
go.mod
go.sum
go.sum
main.go
main.go
main_test.go
main_test.go
View all files
Repository files navigation
wa-metaai
OpenAI-compatible endpoint backed by Meta AI, reached over WhatsApp. Lets opencode (or any<br>OpenAI-compatible client) use Meta AI as a model.
POST localhost:8788/v1/chat/completions --> whatsmeow --> WhatsApp<br>opencode --> POST localhost:8788/v1/chat/completions --> whatsmeow --> WhatsApp
Why whatsmeow and not Baileys
Meta AI is not a phone-number contact. It is a bot JID : 867051314767696@bot. Delivery to a bot<br>requires two things on the outgoing stanza:
a node appended to the stanza content
an HKDF-derived BotMessageSecret (applyBotMessageHKDF over the message secret)
Baileys implements neither — its entire send path references bot JIDs once, only to skip issuing a<br>TC token. The observable symptom is precise and misleading: WhatsApp server-acks the message<br>(status: 2) and then never delivers it, so it sits at one grey tick forever and Meta AI never<br>replies. A control send to a human JID on the same code path went PENDING → 2 → 3 → 4 (read),<br>proving the transport was fine and only bot support was missing.
whatsmeow has it: types.NewMetaAIJID is exactly 867051314767696@bot, send.go sets isBotMode<br>when the target IsBot(), derives the bot secret, and attaches the node.
Baileys' META_AI_JID = 13135550002@c.us is legacy and unroutable — sending to it produces<br>USync fetch yielded no results for pending PNs, WhatsApp's way of saying that number isn't a user.
Setup
The account itself must live in a real WhatsApp mobile app (an Android emulator works); this service<br>attaches as a linked device and cannot hold the registration on its own.
./wametaai">CGO_ENABLED=1 go build -o wametaai .<br>WA_PHONE=digits, country code first> ./wametaai
First run prints a pairing code — enter it under WhatsApp > Linked devices > Link with phone<br>number . The session persists in wametaai.db, so later runs need no code.
opencode config
~/.config/opencode/opencode.json:
"provider": {<br>"whatsapp": {<br>"npm": "@ai-sdk/openai-compatible",<br>"name": "WhatsApp (Meta AI)",<br>"options": { "baseURL": "http://localhost:8788/v1", "apiKey": "unused" },<br>"models": {<br>"meta-ai": { "name": "Meta AI (WhatsApp)", "tool_call": true, "limit": { "context": 8000, "output": 4000 } }
Then opencode run --model whatsapp/meta-ai "...".
Tool calling
Meta AI has no native function calling, so the shim supplies it. When a request carries tools,<br>toolPrompt renders each tool's name, description and JSON Schema into the prompt and asks for a<br>single fenced object:
", "args": {...}}">{"tool": "", "args": {...}}
parseToolCall extracts that — tolerating the fence, a language tag, and the surrounding chatter<br>Meta AI likes to add — and the reply is returned as a real OpenAI tool_calls message with<br>finish_reason: "tool_calls", in both the JSON and SSE paths. Prior turns are replayed as<br>[ASSISTANT ran tool] and [TOOL RESULT] so it can see what already ran.
Verified working through opencode's real agent loop:
build · meta-ai<br>→ Read notes.txt<br>pomegranate">$ opencode run --model whatsapp/meta-ai "Read the file notes.txt and tell me the secret word."<br>> build · meta-ai<br>→ Read notes.txt<br>pomegranate
Observed: opencode's full system prompt plus its tool schemas came to ~37,000 characters (~9k<br>tokens) per request, and Meta AI handled it without complaint, correctly resolving a relative path<br>to an absolute one. Two round trips, ~6s each.
The ceiling to watch: a single WhatsApp text message caps out around 65k characters, and a<br>trivial one-file task already used 37k. Larger context — more files, longer histories —...