My Very First AI Assistant Experience
I kinda struggled when people DM’ed me while I was working. Like, either it was my coworkers who needed help about work, family, or friends. I needed a few hours to reply to them and it had been my problem for the past few months.
So i was thinking “why dont i just integrate AI to my number so it can reply to incoming messages while im AFK or busy working. YEAHH, it’s a good idea. I’ll do that.”
I was wrong. This project took a lot of my sanity and time, LOL.
So, I need a few things to make this project happen. Like I have to have access to Whatsapp Gateway/API since I’m using WhatsApp as my main messaging app. The other one is the access to AI models.After a bit of research and chatting with Gemini (yes, i’m using AI to research about this project), I decided to use one of Gemini models to run the AI chatbot in my WhatsApp. One objective was completed. Shortly after that, I found a post from Threads and the guy said he had been using Unofficial Whatsapp Gateway (yes, you read it right. Unofficial) called GOWA.
If you look it up on GitHub, the repository is actually named go-whatsapp-web-multidevice. At its core, it's a powerful RESTful WhatsApp API Service that lets you automate your WhatsApp via WhatsApp Web's multi-device protocol. But what really caught my eye and convinced me to use it was its modern feature. It already has built-in support for AI Agents and Model Context Protocol (MCP). It’s like this tool was specifically tailored for the exact chaotic AI automation project I was trying to build.
2. Planning the Project
Of course I don't code after getting inspiration. I started to make a plan for this project so everything doesn't break while I'm working on this project. I don’t know if this plan and the technical stuff I chose was the right thing. But as long as it runs, I think it's okay. hopefully…
After a few chit chatting with AI (again. Im sorry), i came to conclusion to chose this kind of tech stack:
- Go-WhatsApp Gateway as a Gateway (of course): This runs inside a Docker container.The job is to stay connected to WhatsApp, watch for incoming DMs, and immediately forward that raw message data (the HTTP POST payload) to my backend.
- Fastify + PM2: Located on my VPS, Fastify (Node.js) acts as the main control center. It receives the payload from the front gate, filters out group chats (because I don't want the AI replying to random family groups), and handles the main routing logic. To keep this thing alive 24/7 without crashing, I used PM2 to manage the process.
- Supabase: I use supabase to store some configs, like knowledge base for the AI so it can dynamically know what kind of answer it provides. The other one is for the status that I'm currently on. Whether I'm AFK or active. Pretty much simple right?
- Gemini API: When Fastify receives incoming DMs, it sends the context over to the Gemini API. I chose Gemini because I'm too lazy to do more research on other models.
3. Modes
Once the architecture was up, I realized one thing, I couldn't let the AI treat everyone the same way. If my boss texts me, the bot shouldn't respond with a casual "Yo, what's up?". Also, if a close friend hits me up, a stiff "Dear Valued Colleague, I am currently indisposed" would just sound ridiculous.
To solve this, I built a routing logic that divides incoming chats into different "Modes":
- Settings (.afk / .afk off): This, as you probably already know, is the settings. It’s toggle the system, I just send a quick command to my own number. Fastify catches the text, updates the status in Supabase, and the bot responds with a clean green checkmark emoji to confirm it’s now guarding my gate.
- Work Mode: When coworkers or clients message me about tasks, the AI automatically shifts into a professional, informative, and straight-to-the-point tone. It ensures they get the necessary work updates without me having to break my deep-work focus.
- Boss Mode (The Honorific Guard): This one required a bit of custom logic. I mapped out specific boss numbers and configured the prompt to automatically use proper, respectful local honorifics (like Sir, Ma’am, or other respectful terms). It guarantees the AI handles the upper management with the exact level of politeness and courtesy they expect, keeping my job safe while I’m AFK.
- Casual Mode: If the incoming message is from family or close friends, the bot drops the formalities entirely. It switches to a relaxed, laid-back persona, letting them know I'm just caught up with something and will hit them back soon.
- Crush Mode (The Priority Lane): Let’s be honest, you can’t keep your crush waiting, but you also don't want to look desperate by replying in 0.2 seconds while you're actually drowning in work. For this specific mode, the AI is fine-tuned to be my wingman. It drops the stiff robotic tone, matches her energy, keeps the conversation naturally flowing, and subtly drops a hint like, "Hey, I'm a bit tied up right now, but I'll text you properly as soon as I'm done!" It perfectly balances being attentive without blowing my cover. Though now that I'm posting this on my website, she'll probably see this LOL.
4. Migration Drama: A 3 AM Facepalm and Networking Nightmares
Everything worked perfectly on my local machine. Classic.
The real chaos started on Thursday night after I got home from work around 10 PM. I decided it was time to migrate the entire setup to my new VPS. I figured it would take an hour tops.
I was completely wrong. That migration turned into a grueling 4-hour tech marathon that dragged on until 3 AM.
When I first deployed everything, I was immediately greeted by a beautiful 502 Bad Gateway error. The Front Gate (Docker container) was running, and Fastify on the host OS was alive, but they simply refused to talk to each other.
At 2:30 AM, staring blankly at the screen with blurry eyes, I found the first culprit. It was a ridiculous configuration typo inside my .env file. I had literally written:
WEBHOOK=WEBHOOK=my-silly-webhook
Yup, I accidentally doubled the variable name. Because of that silly copy paste mistake, GOWA couldn't parse the webhook URL correctly. I quickly fixed the typo, restarted the process via PM2, and thought, "Finally, I can go to sleep."
Nope. Still 502 Bad Gateway.
Fuck it. I decided to call it a night at 3 AM and went to sleep.
The next morning at 9 AM, I woke up, poured myself a hot cup of coffee, and looked at the server with a fresh mind. It turned out the remaining issue was purely in my Nginx setup. When configuring the reverse proxy to point to my Fastify backend (port 6000), I had messed up the IP address. Instead of targeting the correct local/internal network path, I was pointing Nginx to the wrong IP.
The fix was simple: I changed the target configuration in Nginx to route directly through the VPS’s internal private IP address provided by the data center.
I saved the Nginx config, reloaded it, and hit the endpoint using curl. Suddenly, my terminal spat out:
HTTP/1.1 404 Not Found Content-Type: application/json; charset=utf-8
In any other context, a 404 Not Found means failure. But to me at that moment? It was absolute victory.
Nginx doesn't reply with JSON by default when it errors out. That Content-Type: application/json meant Nginx had successfully found the backend and was answered directly by Fastify! It only threw a 404 because I hit the root URL (/) which I didn't define in my routing.
To prove it, I immediately fired another curl, this time targeting the actual route:
curl -i https://mysillywebhook
And boom! HTTP/1.1 200 OK. The logs lit up, Supabase connected, Gemini woke up, and the gateway was finally, officially alive.
5. Conclusion
Building this project taught me something: Sleep early, and don’t force yourself to stay up late at night.
Taking a break and looking at the server with a fresh mind the next morning was what actually solved the problem. In the end, the setup was totally worth it. I now have a lightweight, self-hosted system that guards my WhatsApp 24/7. It filters my chats, uses proper local honorifics for my boss, and handles casual DMs perfectly while I’m focusing on work.
Now, it’s time to finally turn on .afk mode and get some actual work done.