{"slug": "using-meta-ai-via-whatsapp-for-opencode", "title": "Using Meta AI via WhatsApp for OpenCode", "summary": "A developer built an OpenAI-compatible endpoint that lets opencode and other clients use Meta AI over WhatsApp, routing requests through whatsmeow to the bot JID 867051314767696@bot. The shim adds tool-call support since Meta AI lacks native function calling, and it works through opencode's agent loop, but a single WhatsApp message caps at ~65k characters and a trivial task already used ~37k, so larger contexts will fail without truncation guards.", "body_md": "OpenAI-compatible endpoint backed by Meta AI, reached over WhatsApp. Lets opencode (or any OpenAI-compatible client) use Meta AI as a model.\n\n``` php\nopencode --> POST localhost:8788/v1/chat/completions --> whatsmeow --> WhatsApp\n                                                     <-- Meta AI (867051314767696@bot)\n```\n\nMeta AI is not a phone-number contact. It is a **bot JID**: `867051314767696@bot`\n\n. Delivery to a bot\nrequires two things on the outgoing stanza:\n\n- a\n`<bot>`\n\nnode appended to the stanza content - an HKDF-derived\n`BotMessageSecret`\n\n(`applyBotMessageHKDF`\n\nover the message secret)\n\nBaileys implements neither — its entire send path references bot JIDs once, only to skip issuing a\nTC token. The observable symptom is precise and misleading: WhatsApp **server-acks** the message\n(`status: 2`\n\n) and then never delivers it, so it sits at one grey tick forever and Meta AI never\nreplies. A control send to a human JID on the same code path went PENDING → 2 → 3 → 4 (read),\nproving the transport was fine and only bot support was missing.\n\nwhatsmeow has it: `types.NewMetaAIJID`\n\nis exactly `867051314767696@bot`\n\n, `send.go`\n\nsets `isBotMode`\n\nwhen the target `IsBot()`\n\n, derives the bot secret, and attaches the `<bot>`\n\nnode.\n\nBaileys' `META_AI_JID = 13135550002@c.us`\n\nis legacy and unroutable — sending to it produces\n`USync fetch yielded no results for pending PNs`\n\n, WhatsApp's way of saying that number isn't a user.\n\nThe account itself must live in a real WhatsApp mobile app (an Android emulator works); this service\nattaches as a **linked device** and cannot hold the registration on its own.\n\n```\nCGO_ENABLED=1 go build -o wametaai .\nWA_PHONE=<digits, country code first> ./wametaai\n```\n\nFirst run prints a pairing code — enter it under **WhatsApp > Linked devices > Link with phone\nnumber**. The session persists in `wametaai.db`\n\n, so later runs need no code.\n\n`~/.config/opencode/opencode.json`\n\n:\n\n```\n{\n  \"provider\": {\n    \"whatsapp\": {\n      \"npm\": \"@ai-sdk/openai-compatible\",\n      \"name\": \"WhatsApp (Meta AI)\",\n      \"options\": { \"baseURL\": \"http://localhost:8788/v1\", \"apiKey\": \"unused\" },\n      \"models\": {\n        \"meta-ai\": { \"name\": \"Meta AI (WhatsApp)\", \"tool_call\": true, \"limit\": { \"context\": 8000, \"output\": 4000 } }\n      }\n    }\n  }\n}\n```\n\nThen `opencode run --model whatsapp/meta-ai \"...\"`\n\n.\n\nMeta AI has no native function calling, so the shim supplies it. When a request carries `tools`\n\n,\n`toolPrompt`\n\nrenders each tool's name, description and JSON Schema into the prompt and asks for a\nsingle fenced object:\n\n```\n{\"tool\": \"<name>\", \"args\": {...}}\n```\n\n`parseToolCall`\n\nextracts that — tolerating the fence, a language tag, and the surrounding chatter\nMeta AI likes to add — and the reply is returned as a real OpenAI `tool_calls`\n\nmessage with\n`finish_reason: \"tool_calls\"`\n\n, in both the JSON and SSE paths. Prior turns are replayed as\n`[ASSISTANT ran tool]`\n\nand `[TOOL RESULT]`\n\nso it can see what already ran.\n\nVerified working through opencode's real agent loop:\n\n``` bash\n$ opencode run --model whatsapp/meta-ai \"Read the file notes.txt and tell me the secret word.\"\n> build · meta-ai\n→ Read notes.txt\npomegranate\n```\n\nObserved: opencode's full system prompt plus its tool schemas came to ~37,000 characters (~9k tokens) per request, and Meta AI handled it without complaint, correctly resolving a relative path to an absolute one. Two round trips, ~6s each.\n\n**The ceiling to watch:** a single WhatsApp text message caps out around 65k characters, and a\ntrivial one-file task already used 37k. Larger context — more files, longer histories — will hit that\nwall, and there is currently no truncation guard, so an oversized prompt fails rather than degrades.\n\n| tool-call reliability | prompted, not native. Meta AI is a consumer assistant, so it can answer in prose where a tool call was wanted; the loop stalls on that turn rather than recovering. |\n| streaming | reply is buffered then emitted as one chunk. Meta AI answers as many separate messages (~10 message IDs per answer), not edits to one, so they are joined in arrival order and considered complete after `WA_QUIET_MS` of silence. |\n| system prompt | folded into a flattened transcript; there is no separate system role |\n| conversation state | one WhatsApp thread with its own memory, so history is resent each turn and Meta AI's own recall can bleed across requests |\n| concurrency | serialized — a single thread cannot serve parallel requests |\n| token usage | estimated at ~4 chars/token; WhatsApp reports none |\n| latency | ~7s for a short answer |\n\n| var | default | |\n|---|---|---|\n`WA_PORT` |\n`8788` |\nHTTP port |\n`WA_PHONE` |\n— | required only for first-time pairing |\n`WA_QUIET_MS` |\n`4000` |\nreply considered complete after this much silence |\n`WA_TIMEOUT_MS` |\n`120000` |\nhard cap per request |\n\nRegistered on a rented TextVerified number, so the account lives only as long as that rental — a released number can be re-rented and re-registered by someone else, which would evict this account. WhatsApp also expires linked devices when the primary stays offline, so keep the emulator reachable. Unofficial-client use is against WhatsApp's terms and carries a ban risk for the number.", "url": "https://wpnews.pro/news/using-meta-ai-via-whatsapp-for-opencode", "canonical_source": "https://github.com/amita-seal/wa-metaai", "published_at": "2026-08-01 21:10:44+00:00", "updated_at": "2026-08-01 21:22:29.945177+00:00", "lang": "en", "topics": ["ai-tools", "developer-tools", "generative-ai"], "entities": ["Meta AI", "WhatsApp", "opencode", "whatsmeow", "Baileys"], "alternates": {"html": "https://wpnews.pro/news/using-meta-ai-via-whatsapp-for-opencode", "markdown": "https://wpnews.pro/news/using-meta-ai-via-whatsapp-for-opencode.md", "text": "https://wpnews.pro/news/using-meta-ai-via-whatsapp-for-opencode.txt", "jsonld": "https://wpnews.pro/news/using-meta-ai-via-whatsapp-for-opencode.jsonld"}}