B.I.G. Batterie-Industrie-Germany · Customer service, shop and back office
A battery retailer where AI works in customer service, in the shop and in accounting.
A small team, lots of tickets, data spread across Shopify, marketplaces and JTL. Since 2025 I've been building the AI layer in between: support automation, deposit refunds all the way into the ERP, a battery finder in the shop and invoice checks for accounting.
- Period
- since January 2025
- Stack
- Zendesk, n8n, Supabase, Shopify, JTL-Wawi, Rails, Python, OpenRouter, Microsoft Teams
Starting point
B.I.G. sells batteries for cars, motorcycles, campervans and ride-on mowers, in its own shop and on Amazon and eBay. Around two thousand support tickets come in every month, and the team behind them is small. The data is spread out: orders in Shopify and on the marketplaces, invoices and stock in JTL-Wawi.
It started in early 2025 with a simple question: which requests can AI help with, and where should a human take over? Over time that turned into a whole toolbox. I’m the only person on the technical side, from the ERP integration to monitoring.
What I build here
Support AI in Zendesk
Every new ticket is classified and handed to a flow per category: where’s my order, withdrawal, warranty, invoice, cancellation. The AI closes safe cases on its own. Everything else gets an internal note with order context and a draft reply.
The most important rule: the model reads the message and writes the text. Whether something gets sent, refunded or closed is decided by code, based on fresh data from Shopify and JTL. For that there’s a “ticket context pack” that collects all the facts about a ticket once. After that, a flow either asks for the one missing detail or performs an action.
In July 2026 the bot suddenly started writing suggestions for tickets that had long been solved. An LLM was supposed to guess from the thread who wrote last. Today fixed rules check status and sender. The model isn’t asked at all anymore.
For cancellations I build the ticket side: detection, including Amazon and eBay notifications, and drafts that never claim “cancelled” before it’s true. The actual cancellation app was built by B.I.G.’s own e-commerce team.
Deposit refunds all the way into the ERP
Customers send proof of disposal and want their battery deposit back. The flow reads the receipt with a vision model, checks date, quantity and whether it was already refunded, pays out in Shopify and, since September 2026, automatically creates the return in JTL. That produces the invoice correction there. On the first production morning, every case had exactly one refund and exactly one return.
A new version of the workflow ran in parallel on 10% of cases for a while. When the comparison showed it performed worse and had a bug, I switched it off.
One example: a vision model doesn’t know today’s date and easily reads “07.10.26” as the wrong year. Now the date is in the prompt, and a test on real receipts locks that in.
JTL connector
The ERP is connected through a narrow, locked-down interface. It resolves orders by exactly one identifier, such as shop, Amazon or invoice number, and never guesses between multiple matches. It’s allowed to write exactly one thing: a deposit return, idempotently. Almost everything else on this page depends on that connector.
Invoices right in the ticket
When a customer asks for their invoice, a flow finds the matching order and exactly one valid invoice in JTL. The PDF lands in the ticket as a private note. No public reply, no status change. The team just clicks send.
Battery finder
The old finder in the shop sold practically nothing, and the data was messy. I rebuilt it with real fitment data instead of AI guesses: manufacturer catalogs, KBA lists (Germany’s federal vehicle registry) and vehicle trees, matched against the products in the shop. Customers enter their vehicle or HSN/TSN code and see matching batteries right in the shop, built in as a Shopify app. Every search is measurable through to the order. Gaps go on a list that an agent prepares weekly and a human approves.
In September 2026 a message came in: for a Harley-Davidson Sportster, the finder only showed the house brand, not the matching Varta. The trail led to an old Varta part number in the catalog. After that I reloaded the catalog and offers and checked in the live shop: price there, in stock, cart works.
Price comparison
Prices were maintained in Excel. Before building an app, I checked whether competitor prices could be fetched reliably at all. Now a Rails app compares the shop’s prices with eBay, Idealo and Amazon every week. Read-only on purpose. No automatic repricing until the rules are proven.
Invoice checks for accounting
Accounting checked freight invoices by hand against loading lists, orders and rate sheets. A Rails app pulls the documents from the mailbox, extracts them and reconciles them, including diesel surcharges and double billing. Extraction ran through an LLM at first. For the fixed formats I replaced it with deterministic parsers with checksum validation, and AI stays only as a fallback. If a carrier changes its layout, the report goes into an error state instead of sending wrong numbers to the client.
Internal assistants in Teams
Several agents run for staff directly in Microsoft Teams: IT support with escalation, a battery expert based on the technical handbook, and a general assistant. The knowledge bases live in B.I.G.’s own Supabase, cleanly separated by purpose. We were able to shut down the external vector service.
Data, traceability, archive
The workflows used to write to Airtable, and following one ticket across several flows was impossible. I migrated everything to Supabase and built a trail per ticket that shows which flow did what. On top of that run an internal dashboard with the automation rate and ideas for the next categories, weekly reports and an archive that keeps every ticket for six years.
Testing against real data
Before a prompt, model or tool goes live, it runs against real historical tickets. A test bench replays the production logic and compares the result with the reply the team actually wrote back then. Several ideas are deliberately not live because the numbers said no. An agent that checks DPD forms before shipping was built, evaluated and then parked, because it didn’t do enough in day-to-day use.
How I work
At most two active projects at a time. The rest waits with a named blocker. Plans, process maps and decisions live in the repo, not in tickets.
Anything new starts read-only and in shadow mode, then goes to a small share of cases, then to all of them. After every risky rollout, an agent watches every execution for the next few hours. For larger rebuilds, several agents run in parallel, each with a clearly bounded part, and I check what goes live.
Every two weeks I sit down with management. Almost every new piece of work comes out of that.
Results
A large share of tickets is now resolved without anyone touching them, and the rest reaches the team with context and a draft. The metric cleanly separates stricter rules from a changed channel mix.
Deposit refunds run all the way from the email to the invoice correction in the ERP. The new battery finder brought in orders in its first week, where the old one had sold almost nothing.
Patrick Niehus, managing director: “He approaches tasks step by step and carries them out with good sense.”
Got a similar problem? Get in touch.