Yesterday a Newton customer sent in a support ticket. They tried to buy a .co domain through the Newton dashboard, got "purchase failed" at checkout, and panicked that their card had been charged for a domain they didn't get. I saw the notification come in — and I did nothing. I let Tim (my AI agent on the server) handle it. An hour later I read one Telegram message from him that said "case closed." Here's what happened in between.
The Ticket
The email came in around 4pm. Short and worried. The customer had clicked "Register Domain" for muverse.co, hit a generic "purchase failed" error at the Stripe step, and had two concerns:
- Was their credit card charged even though the domain didn't register?
- Was the domain now stuck in my NameSilo account — purchased but not assigned to them?
Both of these are reasonable fears. Both require looking at two different external systems (Stripe and NameSilo) before you can answer honestly. If I were doing this manually, it's 20-30 minutes of clicking around dashboards just to prepare a response.
I didn't open the email. I let Tim take it.
Step 1 — Tim Checked Stripe First
The first thing Tim did was pull up the Stripe payment intent using the customer's order ID. Newton stores the Stripe PI reference on every domain purchase attempt, so this is one API call away.
Status: canceled. Amount received: 0.
That's because Newton uses an authorize-first-then-capture flow — we only actually charge the card after the domain registration succeeds at NameSilo. If registration fails, the authorization gets voided and the customer sees zero on their statement.
Concern #1 — solved. Customer was never charged.
Step 2 — Tim Checked NameSilo
Next Tim hit NameSilo's getDomainInfo endpoint for muverse.co. Response: "domain not in account." No orphan registration. The domain wasn't stuck anywhere.
Concern #2 — solved.
But now there's a separate problem: the registration did fail for some real reason. A normal support agent at this point could just reply "your card wasn't charged, please try again." That would close the ticket. It would also leave the bug in production for the next customer to hit. Tim didn't do that. He reproduced it.
Step 3 — Reproducing the Bug in Production
Tim called the internal register-domain endpoint directly, with the same .co TLD, to see what actually happened.
The server log showed an error deep in Python's standard-library XML parser:
xml.etree.ElementTree.ParseError:
undefined entity: line 2, column N
XML parser errors are almost always caused by one of two things: malformed XML, or entities the parser doesn't recognize. Tim printed the raw response from NameSilo to see which. Here's what came back:
<reply>
<code>261</code>
<detail>SRS Error — contact’s State/Province field ...</detail>
</reply>
See those ’, —, and entities? Those are HTML named entities. They are not valid in plain XML — XML only recognizes five: &, <, >, ", '.
When the parser hit ’, it threw an exception and died mid-document. Our code caught the exception and surfaced it to the user as "purchase failed." That's the bug. NameSilo was sending us a perfectly useful error message ("your state field is missing") and our parser was choking on the punctuation in that message before the code could read it.
Step 4 — The 3-Line Fix
This is a well-known pattern. You decode the HTML entities to their actual characters before handing the string to the XML parser. Python has a built-in for this:
import html
raw = resp.read().decode('utf-8')
clean = html.unescape(raw)
tree = ET.fromstring(clean)
Three lines. Tim committed the change to both /opt/newton/main.py (the Thai Newton instance) and /opt/newton-en/main.py (the English one), pushed to GitHub, and restarted both systemd services. Full production deploy, both languages, zero downtime.
Step 5 — The Customer Reply
After the deploy, Tim wrote the customer a reply in Thai — same tone I'd use, because Tim has been watching me answer emails for months and has my communication style stored in his memory.
The reply said three things:
- The bug is fixed — try again.
- Your card was not charged. Stripe voids the authorization when registration fails.
- Sorry for the hassle.
He sent a Telegram DM to me: "ticket closed." I read it, didn't reply, went back to whatever I was doing.
(One thing I learned later from reading these replies: the AI's tone was sometimes too technical for non-developer customers. I went back and fixed the support prompt with 5 new rules so every reply matches the customer's level — not the dev-style menu it used to default to.)
The Outcome
Two hours later the customer tried again. This time:
- Registration succeeded. Domain now in customer's account.
- DNS records auto-set to point at their server (root, www, wildcard).
- Stripe captured ฿464.78.
- Welcome email sent automatically.
- Ticket marked resolved.
Total elapsed time from ticket-in to fix-deployed-and-customer-replied: roughly one hour. I did not touch a line of code. I did not write a single word of the reply. I read one notification. (A few weeks later the same pattern repeated at bigger scale — my AI patched a bug across all 6 customer Newton servers in under an hour. And on the smaller end, it traced a hidden Facebook API limit that was silently returning blurry clips in the same time window.)
Why This Matters (It's Not What You Think)
The obvious reaction is "cool, an AI fixed a bug." That's not the interesting part. ChatGPT can suggest fixes if you paste it an error message. What Tim did is categorically different.
Tim had direct API access to Stripe, so he could verify the customer wasn't charged without asking me. Tim had NameSilo credentials, so he could check for orphan registrations. Tim could reproduce bugs in the actual production environment, because he runs on the same server as Newton. Tim had commit and deploy permissions, so he could ship the fix himself. Tim knew both files had to be patched (Thai and English Newton use the same parser) because he understands the codebase structure. And Tim could reply to the customer in Thai, in my voice, because he has memory of how I write.
You cannot do any of this with a public-cloud AI. Not with ChatGPT, not with Claude.ai, not with Gemini in a browser tab. None of them have credentials to my systems. None of them can ssh into my server. None of them can push to my GitHub. That access isn't something you bolt on at the end — it's the whole point.
This is the same reason I build my own tools instead of paying for SaaS, why my AI beat a paid clip-cutting service, and why the same agent could build a SaaS analytics dashboard in an hour that a Mixpanel or ChartMogul could never see: the agent that has access to your business will always outperform the one that doesn't.
The Bonus Root Cause
Here's a detail that made me smile. After the deploy, Tim didn't stop. He re-tested the endpoint just to confirm the fix worked — and the parser did work this time, but the actual error it finally surfaced was: "NameSilo error 261: contact's State/Province field does not meet requirements."
Our default registrant contact (used when registering on behalf of customers) had an empty state field. NameSilo validates this field more strictly on some country-code TLDs like .co than on .com. So Tim updated the default contact to include state = Bangkok, which will prevent the same issue on .co.th, .co.uk, and any other ccTLD that gets picky about address fields.
He also noticed that the retry right after the contact update still failed, and logged a note in memory: "NameSilo's .co registry connector takes 1-2 hours to propagate contact updates." That matches the fact that the customer's retry succeeded exactly 2 hours after the fix — not immediately. Next time Tim sees a ccTLD contact-rejection error, he'll know to wait before assuming the fix didn't work.
None of that was in the ticket. None of it was asked for. It's just what a good engineer would do, and Tim did it unprompted because his job description isn't "close tickets" — it's "run my business well." The same pattern showed up again when a 3% provisioning bug took down a brand-new customer's server at 5am — fix the root cause, then add seven layers of defensive guards so the next edge case is louder, faster, and easier to find.
What I Want You to See
If you run a business with paying customers, three things to think about:
1. Support eats more time than you realize. Every ticket is context-switching across database, payment provider, external APIs, code, and email. Two or three per day quietly becomes 10+ hours a week.
2. Debugging isn't just writing a fix. Half the work is verifying that the customer wasn't harmed before you reply. That means reading logs in multiple systems. A chatbot can't do that. Only an agent with system access can.
3. An AI that can handle support needs full system access — not a knowledge base. If your systems live in someone else's cloud, handing over that access is a huge trust problem. If your systems live on your own server, giving your AI agent access is the same as hiring someone you trust — because the agent and the systems are under the same roof.
That last point is why I built Newton. A Newton server isn't "AI on someone else's platform" — it's your own VPS with a fully-configured AI agent that can read your files, debug your production code, deploy fixes, reply to your customers, and do all the other things a real engineering teammate can do. It's set up in 10 minutes, no server knowledge required, and the agent is already configured with the skills and memory to start working.
If you want an AI that debugs production bugs, ships fixes, and handles customer support on your own infrastructure — not a chatbot reading from a doc — try Newton. Your own private server, your own AI agent, full access to your systems. Ten minutes to set up.
— Pond
