What it does
One message goes in. One structured result comes out:
- Category: new project or sale, support problem, billing, partnership, spam, or other.
- Urgency: low, medium or high, with a one-line reason.
- Summary: one or two sentences, so you get the gist without rereading.
- Key details: name, business, what they need, deadline, budget and contact info, but only when the message actually says them. Blank means it wasn't mentioned.
- Suggested next step and a drafted reply you can edit. Anything the AI can't know, like a price or a date, is left as a
[placeholder]for you to fill in.
Why a small business would want it
- Sorting: sales leads, support problems and billing questions land in the same inbox. A label on each one lets you deal with them in batches, or route them to the right person.
- Faster first replies: starting from a draft is quicker than starting from a blank email.
- Fewer missed messages: an urgent "our booking form is broken" gets flagged instead of sitting under ten newsletters. Spam gets labelled so you can skip it.
It won't run your inbox for you. It does a first pass so you can spend your time on the reply.
How it works
- Form: this page sends the message (max 2,000 characters) to a small API.
- Worker: a Cloudflare Worker checks where the request came from (only neonkey.tech is allowed), applies the rate limits, and rejects anything empty or too long.
- AI: the Worker sends the message to Google's Gemini model with instructions and a strict JSON schema. The schema fixes the allowed categories and urgency levels, so the answer always has the same shape. The message is treated as data, so instructions hidden inside it are ignored.
- Structured result: the Worker checks the JSON and returns it. Nothing is saved.
- Human review: you read the summary and the draft, fix anything that's off, and send it yourself. In a real setup the result would go to a shared inbox label, a spreadsheet row or a task, not straight back to the customer.
Stack & tools
- Astro (static page)
- Cloudflare Workers (free plan)
- Durable Objects (rate-limit counters only)
- Google Gemini API (free tier)
- JSON-schema structured output
What it costs to run
For this demo, nothing so far. Each piece runs on a free tier, and each has limits:
- Cloudflare Workers, free plan: 100,000 requests a day and 10 ms of CPU time per request. The rate-limit counters live in a small Durable Object; the free plan includes 100,000 Durable Object requests and 100,000 written rows a day, and each run here uses only a handful of each. The 150-runs-a-day cap mainly protects the AI quota.
- Google Gemini API, free tier: Google sets per-model request limits on the free tier and changes them from time to time. The trade-off is data use. On the free tier Google may use what's submitted to improve its products, and human reviewers may read it. Google's terms also don't allow free-tier apps for users in the UK, Switzerland or the EEA, so the demo is switched off there.
- Size of a run: the example runs below used about 580–831 tokens each (instructions + message + result), as reported by the API.
For a real business handling customer messages, I'd use Gemini's paid tier, or another provider with similar terms. On the paid tier Google says it doesn't use prompts or responses to improve its products. It bills per token at Google's current rates (opens in new tab). For short messages like these the bill is usually small, but it depends on your volume, so I'd check it with you during scoping. I won't promise you a number here.
Limitations
- The AI can misclassify. A vague message, sarcasm or a mix of topics can get the wrong label or urgency. Treat the result as a suggestion.
- A human should review every reply. The draft can sound confident and still be wrong, and it doesn't know your prices, calendar or policies.
- It only sees the one message. It has no customer history, so it can't tell an important repeat client from a stranger.
- Free tiers can run out or slow down. If the main model is busy, the Worker retries on a lighter model. If both are unavailable, you get a friendly error instead of a result.
- Rate limits are per connection, not per person. People behind the same office network, mobile carrier or VPN share one limit, and someone switching IP addresses can get around it. The daily total cap is the backstop.
Real example results
These are the results the deployed demo returned for the three made-up samples on Oct 30, 2026. They're copied as-is, not edited. Run a sample yourself and the result will differ a little, because the AI's wording varies between runs.
Sample: New project request
Hi! I'm Dana Ortiz and I run Ortiz Family Bakery in Tucson. Custom cake orders come in through Instagram DMs, email and phone, and we keep losing track of them. Could you set up something that collects orders in one place and sends customers a confirmation? Ideally before the holiday rush starts in mid-November. Our budget is around $300. Thanks!
The client has a clear deadline of mid-November before the holiday rush starts.
Summary
Dana Ortiz from Ortiz Family Bakery needs a system to consolidate custom cake orders from multiple channels and send automatic customer confirmations.
Key details
- Name
- Dana Ortiz
- Business
- Ortiz Family Bakery
- Needs
- A system to collect custom cake orders from Instagram DMs, email, and phone in one place and send customer confirmations.
- Deadline
- mid-November
- Budget
- $300
- Contact
- Not mentioned
Suggested next step
Reply to Dana to discuss potential solutions that fit her $300 budget and mid-November deadline.
Draft reply (review before sending)
Hi Dana, Thanks for reaching out! Consolidating your custom cake orders into one place sounds like a great way to streamline things before the holidays. I would love to help you set up an order management system that fits your workflow and budget. Given your mid-November target, we can explore a few options that keep things simple and automated. Are you available for a quick phone call or chat [insert available days/times] to go over the details? Best regards, [Your name]
Sample: Something is broken
Hello, this is Sam from Ridgeway Physio. The online booking form on our website stopped sending us notification emails yesterday morning, and two patients said they booked but we never saw it. We have a full clinic tomorrow. Can someone look at this today? Best number is 555-0142.
The online booking notifications are broken and the clinic is full tomorrow.
Summary
Sam from Ridgeway Physio reports that website booking notification emails stopped working yesterday, resulting in missed appointment alerts with a full clinic tomorrow.
Key details
- Name
- Sam
- Business
- Ridgeway Physio
- Needs
- Fix online booking form notification emails
- Deadline
- Today
- Budget
- Not mentioned
- Contact
- 555-0142
Suggested next step
Call Sam at 555-0142 today to troubleshoot the booking form email issue.
Draft reply (review before sending)
Hello Sam, thank you for reaching out. I am sorry to hear that the booking notification emails are not working, especially with a full clinic tomorrow. I am looking into this right now and will call you at 555-0142 as soon as I have an update. [Your name]
Sample: Spammy pitch
Dear Website Owner, we GUARANTEE #1 Google ranking and 10,000 high-quality backlinks for only $49!!! Limited time offer, act now. Reply YES to claim your SEO package today. To stop receiving these offers reply STOP.
This is an unsolicited automated spam message with no real time pressure.
Summary
The sender is offering guaranteed SEO rankings and backlinks for $49. This is an unsolicited commercial offer.
Key details
- Name
- Not mentioned
- Business
- Not mentioned
- Needs
- Not mentioned
- Deadline
- Not mentioned
- Budget
- Not mentioned
- Contact
- Not mentioned
Suggested next step
Mark as spam and do not reply.
Draft reply (review before sending)
No reply drafted (marked as spam).
Build notes: what broke and what I changed
- The planned model wasn't available. I planned to use Gemini 2.5 Flash, but the API key returned "no longer available to new users." I switched to
gemini-3.5-flash(the API currently reports the version it serves asgemini-3.6-flash) with thinking set to its minimal level (about 2–3 seconds per run), with Gemini 3.5 Flash-Lite as the fallback. - The newest model was too slow for a demo. The latest Flash model either returned "high demand" errors or took close to a minute during testing. For this job, speed matters more than having the newest model.
- Free tier rules shaped the design. Google's terms say free-tier content may be reviewed and free-tier apps can't be offered in the UK, Switzerland or the EEA. That's why the page has a clear "don't paste private info" note and the Worker turns those regions away. A client build would use a paid tier.
- The first rate limiter didn't hold. I started with Cloudflare's built-in rate limiting plus KV counters. In testing, a burst of requests sailed past the 5-a-minute limit: both are eventually consistent, so counts lag behind fast requests. I moved the counters into a small Durable Object, which handles one request at a time per visitor, and the limit then held in testing.
- Fallbacks happen. One of the example runs below (the "something is broken" sample) was answered by the Flash-Lite fallback, because the main model didn't return a usable answer at that moment. The page shows which model answered every run.
- Limits before AI. The Worker checks origin, rate limits and message length before it calls the AI, so abuse costs as little as possible.
The Worker source lives in the site's repository under workers/triage/, with no secrets in it. The API key is stored as an encrypted Worker secret.