This is a submission for the Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle
What I Built
replydesk drafts replies to a small business's reviews in the owner's own voice.
Reviews sit in public under a business's name, and the next customer reads the replies. Writing them is the hard part. The first owner who tried replydesk put it plainly: "I suck at putting all that together."
Here's how it works. You sign up at replydeskhq.tech, write a few lines about how you talk (the tone guide), and paste in your reviews. replydesk sorts each one into thank-you, fix-it, or needs-a-human. Legal threats, safety or health claims, refund disputes, and anything personal go to needs-a-human. Those never get a drafted reply, only a short note saying why. Everything else gets a draft from GLM-5.3-Flash, an open-weight model released under the MIT license.
Before you see a draft, a checker reads it against your tone guide, the review, and your business profile. If the draft makes a promise, quotes a price, names a person, or states a policy that isn't in one of those, it goes back to the model with the problem quoted. If the second try fails too, you get a template reply with a label on it instead of a made-up fact. Either way, you edit the reply, copy it, and post it yourself. replydesk never posts anything for you.
It's for solo owners and small shops, where answering reviews is real work and nobody's actual job. The founding plan is $9 a month, and my first user signed up for it.
Demo
The product is live at replydeskhq.tech. Sign up, start the founding trial (no card), paste in a few reviews, and draft replies.
If you'd rather not make an account, there's a recorded run at replydeskhq.tech/demo. It's the same pipeline run against Ridgeline Plumbing, a made-up company with reviews written for the project. A fresh clone runs the same demo with no key: py app.py --demo.
If live drafting is ever down, the app falls back to template replies, each one labeled [Template reply - edit before posting].
Code
dev-brewery
/
replydesk
Review replies in your own voice - open-weight GLM-5.3-Flash, triage + fact-grounded drafts. Live: replydeskhq.tech
replydesk
A review-reply desk for small businesses: paste the raw copy from your Google Business Profile or Yelp page, and replydesk triages every review (praise mixed, needs-a-human) and drafts a reply in your own voice โ grounded in your tone guide, with a verifier that rejects any draft inventing facts your paste never contained. The offline core runs entirely from committed fixtures, and a recorded demo renders the full flow without a network. Hosted demo and help replydeskhq.tech ยท recorded demo ยท help.
The open-source core is model-agnostic: it ships pointed at GLM-5.3-Flash
(MIT weights) but speaks to any OpenAI-compatible endpoint โ set
LLM_BASE_URL and LLM_API_KEY in a gitignored .env and it runs.
Quickstart
Python 3.12, standard library only โ no dependencies to install.
# offline demo, no key needed
py app.py --demo
# online mode: copy .env.example to .env and fill endpoint + key
py app.py --online
#โฆPython 3.12 and the standard library, with no dependencies, plus plain JavaScript for the site. MIT licensed.
How I Built It
There are two sets of models in this project: the one inside the app, and the ones that built it.
The model in the app. GLM-5.3-Flash writes the drafts, through any OpenAI-compatible endpoint. On the live site, the browser talks to a small API on an Oracle Cloud ARM VM, and that API calls GLM-5.3-Flash on z.ai. The model's job is narrow on purpose, and two pieces of plain code keep it that way.
The first is triage. A rule table decides what needs a human. The model gets one small say: when no rule matches and the star rating is all that's left to go on, it can move a review between thank-you and fix-it. In the recorded demo, a four-star review says the crew had to come back a second time to finish a water heater swap. The stars said thank-you, and the model moved it to fix-it, which is right. Escalation is different. The review that mentions a lawyer goes to a human because the word matched a rule, and nothing the model writes can talk the app out of that.
The second is the checker. In the run that produced the demo, four drafts passed on the first try, one passed after the checker sent it back, and one failed twice. The one that failed twice was the water heater review, so the demo shows the labeled template in its place.
The models that built the app. replydesk was built by three roles in pi, an open-source coding agent. Each role has its own model and a written charter, and all three ran on z.ai:
- An orchestrator (GLM-5.3, max thinking) turned the task list into one brief at a time, launched the builder, checked each result against the acceptance criteria before writing the next brief, and kept the journal.
- An architect (GLM-5.3, high thinking) wrote the design and the task list.
- A builder (GLM-5.3-Flash, low thinking) wrote the application code and its tests, one task per commit.
I made the product calls. The first version had you paste reviews in one at a time, and I told the orchestrator nobody would pay for that. Then I told it the app had to be ready to sign up a real user, hosted on the real domain. By the time my first user sat down, it had sign-up, the founding plan, a parser that reads a raw copy of a Google reviews page, and live drafting at replydeskhq.tech.
The test suite has 303 tests and runs offline with the network mocked. That number means less than it sounds like, and My Agent Session below is why.
Why Does Open Innovation Matter?
Reviews are full of other people's information: names, complaints, what went wrong in somebody's kitchen. A tool that answers them reads all of it.
Right now the live site sends it to z.ai's hosted GLM-5.3-Flash. That's a setting I can change. The weights are open and replydesk talks to any OpenAI-compatible endpoint, so moving the model is three lines in a config file: LLM_BASE_URL, LLM_MODEL, and LLM_API_KEY. A shop, or someone who sets this up for a handful of local shops, can run the app and the model on their own hardware, and the reviews never leave it. And if z.ai's pricing changes, the same weights can be served by someone else, so a $9 plan doesn't depend on one company's rate card. A closed API can't make either offer. Your customers' reviews go wherever its model lives, at whatever price it sets.
The build is open the same way. The team runs in pi, and every task went to the builder as a brief written to a file. If the builder did something strange, I could open the brief and read exactly what it had been told.
My Agent Session
The whole build is on the record in JOURNAL.md: the tasks the orchestrator handed out, the checks it ran, the calls I made, and the places the agents got it wrong.
A few of the bugs in that journal passed every test and broke the real thing.
-
The app that didn't start. For the better part of a day,
py app.pydid nothing. It had no__main__guard, so starting the server was a silent no-op, and the suite stayed green the whole time. It turned up when the orchestrator ran the app for real. -
The drafts that died in the browser. Every live draft in Chrome failed with "Illegal invocation," because the code passed
fetcharound detached fromwindow. The tests hand the code their own fetch, so they never saw it. -
The
.envthat wasn't there. Part of the suite only passed on a machine with a local.env. The final audit runs the tests on a fresh clone without one, and it caught that on its first run. The same blind spot came back on the move to the VM: the container has no.envon purpose, and the config loader crashed looking for the file before it ever checked the environment.
The builder's first try at committing that audit put real values from my privacy patterns into its tests. The pre-commit privacy guard blocked the commit, and the builder rewrote the tests with made-up values instead of going around the hook. That's what the hook is for.
Before I published, I had Claude Code review the repo against the challenge rules, read-only. It came back with twelve findings, and the three serious ones were all things the agents had written down as true that weren't. The draft of this post said every commit carried the builder's sign-off, and 24 of 49 didn't. It said the app ran on my own hardware, when the model calls went to z.ai. And the recorded demo labeled the water heater template as a verified model draft, which is the one thing the checker exists to prevent. All three are fixed, and the fixes are in the journal too.
My First User
A local business owner tried replydesk on his own reviews. We signed him up at replydeskhq.tech, started the founding trial, and worked through a real review from his Google Business Profile. I recorded the session, 22 minutes of it, and transcribed it on my own machine with faster-whisper, an open-source speech model, in about two minutes.
His first draft came back wordy. I asked what he thought, and he said it was "a fair amount of almost, like, saying it twice." So I had him go back to the voice section of his tone guide and add a few words: don't be too wordy, get to the point, and always sign off with "God bless." He hit draft again. The new draft came back quicker and signed off with "God bless."
"See, I like that. I suck at putting all that together. But now reading this..."
Putting the words together is the part he doesn't like, and a couple of lines in a text box were enough to get the drafts close to his voice.
- Did he pay? Would he? Not yet, because there's no billing to pay through. When we got to price, I told him I was thinking $9 a month, enough to cover the AI behind it with a little margin. "Yeah, absolutely. And then we just have to set something up, you know, a payment plan." He's on the founding trial now: $9 a month, invoiced later, no card up front.
- What did he ask for next? A way to know when a review comes in. "How am I going to get notified that I get a new review? That's going to be my catch." He was worried about remembering to come back, and a watcher that pings him about new reviews is first on the list.
-
Where did it rub? The paste. He copied his reviews from his Google Business dashboard, which formats them differently from the public Maps page (the stars come through as the literal word "star"), and the parser had only been built against the public page. He typed the review in as a
5 | review textline instead, and that worked. Once I had the exact text that failed, the builder taught the parser the dashboard format the same afternoon, and the help page covers it now.
His name and his business stay out of this post and out of the repo, and so does the recording.
Where It Stands
replydesk is five days old. Accounts live in your browser for now, so they don't follow you to another device. A server-side account system is already running behind api.replydeskhq.tech for when billing arrives, but the site doesn't use it yet. Until then, founding members get invoiced. New-review notifications are next.
The parts of replydesk I trust are the parts where something other than the model checks the model's work. That goes for the app and for the team that built it.
Prize Categories
Best Use of a .tech Domain. replydesk lives at replydeskhq.tech, a domain I claimed through Hacktoberfest. It serves the product itself: the landing page, sign-up, the founding trial, and drafting all happen there. The recorded demo is at /demo, the help page at /help, and the API at api.replydeskhq.tech.


Top comments (0)