← Blog

Chat agents

Chat agents for vet clinics: 1,920 weekly rebookings

1,920 inbox threads a week, a 12-year-old Animana practice system, and one rule that mattered more than the 40-second median: never auto-reply to a euthanasie thread.

Jacob Molkenboer· Founder · A Brand New Company· 13 Jun 2026· 10 min
Linen ledger open with chartreuse ribbon, brass bell, wax-sealed card, leather collar on ivory paper.

Monday morning at a Tilburg vet group. Three vestigingen, 33 people on the roster, and the front desk has 312 emails waiting before the first consult of the day. Most are the same question rephrased forty different ways: can we move Floortje's vaccination from Thursday to Friday after four, Bram heeft koorts kan ik vandaag nog terecht, mijn kat is doodziek graag vanavond inslapen. The senior assistent who used to triage the inbox had left in March. The interim was drowning by week two.

That was the state of things when we started. The brief: handle the appointment-rebooking churn without breaking the Animana calendar, route the urgent conversations to a real person inside two minutes, and don't make a single mistake on euthanasie threads.

The number that mattered

1,920 inbound threads per week across the three locations. Roughly 78% of them touch the calendar in some way: rebook, cancel, confirm, ask about availability. The rest split between medication questions (route to the vet on call), invoicing questions (route to the practice manager), and pet-bereavement messages that need a careful human reply.

Before the agent, the front desk handled this with a shared Outlook inbox and a printed copy of each vestiging's day sheet. The interim assistent estimated she spent 4.5 hours a day inside the inbox. Two of those hours were just opening Animana, finding the patient, scrolling to the right calendar, and pasting confirmation text back into Outlook.

Why Animana made this harder than expected

Animana is the Dutch veterinary practice-management system most clinics here run. It is now owned by IDEXX and has been in the field for over a decade. The clinical workflow is good. The public API is not. IDEXX publishes very little about programmatic access for third parties, and what does exist is gated behind a partner programme aimed at integrators of lab and imaging hardware.

For a small studio building an inbox agent, that left two options. Either screen-scrape the Animana web client, which is brittle and breaks every release. Or treat Animana as the source of truth and write to it through a thin RPA layer while keeping a synced read replica of the calendar in our own store. We picked the second.

We talked to two other Dutch clinics during scoping. Both had tried to build something similar and both had hit the same wall: there is no maintained Animana SDK in any language, and the partner-API path needs an established hardware-vendor relationship with IDEXX that takes months to set up. For a project that had to be live in six weeks, neither route was a real option. Knowing this in advance saved us about a fortnight of false starts.

Warning

If you're building any kind of agent against a legacy PMS, get the read path right before you touch the write path. We spent two weeks just on calendar sync before the agent could write a single confirmation back. Skipping that step is how you end up with double-booked surgical slots.

How the agent reads a rebooking thread

A rebooking thread usually arrives in one of three shapes. The clear ask: "Kan de afspraak van Bram dinsdag om 14:00 verzet worden naar woensdag?". The vague ask: "Kunnen we even kijken voor volgende week?". The mixed ask: a rebooking question with a clinical worry attached, which is the dangerous one.

The agent classifies every inbound message into one of seven intents before it does anything else. Three of those intents (rebook, confirm, cancel) are safe to act on. Two (medication, invoicing) get handed to the right human queue with a templated cover note. The last two (clinical_urgent and bereavement_or_euthanasia) never get an automated reply at all. They get flagged, surfaced to a senior assistent on duty, and the owner gets a short human-written acknowledgement within fifteen minutes.

Once intent is clear, the agent extracts entities: patient name, owner, requested window, vestiging if mentioned. It then queries our calendar replica for slots that match the practice's preference rules. The rules are not glamorous. Don't put a nail clip in the same slot as a post-op check. Don't book a new puppy first-shot at five on a Friday because the vet who handles puppies isn't on then. Don't book a cat consult at 13:00 in the Berkel-Enschot vestiging because that's the dog-only afternoon.

There are also length rules the agent has to respect. A vaccination consult is 15 minutes; a behavioural consult is 45. A first-visit puppy needs a full hour because the owner gets a vaccination plan, microchip paperwork, and a nutrition handout. The agent encodes all of these so it never proposes a 30-minute slot for a consult that actually needs an hour, and never wastes an hour on something that needs fifteen minutes.

The agent then proposes two slots, writes back in Dutch, and waits. If the owner confirms, the agent writes the appointment into Animana through the RPA path, double-checks by re-reading the calendar, and only then closes the thread.

The 40-second median, broken down

Median time from inbound message to confirmed slot is 40 seconds. The breakdown is unromantic.

  • Intent classification and entity extraction: 2 seconds.
  • Calendar query against the read replica: under 1 second.
  • Slot ranking against the practice rules: 1 second.
  • Reply drafting in Dutch: 4 to 7 seconds.
  • Waiting for the owner to reply with a yes: 18 to 30 seconds (the only step that really varies).
  • RPA write to Animana and verification read: 6 seconds.

The 40-second median is not the agent being clever. It's the agent not being slow. The previous setup was 14 minutes median because a human had to context-switch between Outlook, Animana, and the printed day sheet for every single message.

Routing euthanasie-flagged conversations

This is the part we lost sleep over. Around 11 to 14 messages a week mention euthanasie, inslapen, or a phrase like "we hebben besloten dat het tijd is". Every one of those needs a human, fast, and the wrong automated reply would be a brand-ending mistake.

The flag is intentionally over-eager. We catch the explicit Dutch terms, the polite euphemisms, and the soft signals (a thread that mentions a 14-year-old dog and the word "lijden" in the same message). False positives go to a senior assistent who can clear them in ten seconds. False negatives are the failure mode we cannot accept.

When the flag fires, three things happen in parallel. The conversation is locked from any automated reply. A push notification goes to the senior assistent currently on duty (the rota lives in Google Calendar, which is much easier to read than Animana). And a short, hand-written-feeling Dutch acknowledgement is sent inside fifteen minutes, drafted by the agent but reviewed and sent by the assistent. The KNMvD guidance on owner communication around euthanasie is clear that the first reply sets the tone for the whole appointment. We wanted that first reply to come from a person who'd read the message.

Takeaway

An inbox agent is only as good as the conversations it knows to stay out of. Flagging the euthanasie thread correctly matters more than answering the vaccination thread quickly.

What broke in the first two weeks

Four things, in roughly the order they hurt.

The first was vestiging ambiguity. The group has three locations and owners often don't say which one they normally visit. Early on, the agent would propose slots at whichever location had the soonest opening, and we ended up with a handful of owners showing up in Tilburg-Noord when their patient file lived in Berkel-Enschot. We fixed it by joining against the patient's last-visited location in Animana before proposing any slot, and by asking explicitly when the patient was new.

The second was Animana session expiry. The RPA layer holds a logged-in session, and Animana invalidates it on a schedule that's not documented anywhere we could find. We watched five appointment writes fail silently on a Thursday afternoon. We added a heartbeat read every 90 seconds and a re-login routine that triggers on any 302 to the login page.

The third was tone. The first week, the Dutch replies read as polite but slightly stiff. Owners noticed. We rewrote the system prompt to lean on the actual phrasing the senior assistent used in her last six months of inbox replies, scraped from the archive with her permission. The next week's owner-satisfaction score went up by a margin none of us expected.

The fourth was Dutch typos and dialect. Owners write inbox messages from phones, often half-Dutch and half-Flemish, often with autocorrect making things worse. "Affspraak" for "afspraak", "vacintie" for "vaccinatie", "enthuanise" for "euthanasie". The euthanasie misspelling was the one that frightened us. We added a fuzzy-match layer over the flag terms and shadow-reviewed every flagged-or-not decision for a fortnight before we trusted the classifier to act on its own judgment.

What the team got back

The interim assistent went from 4.5 hours a day in the inbox to about 40 minutes. She now spends that time on the bereavement-and-euthanasie queue, which is the work that actually needs her. The practice manager stopped getting calendar complaints. The two vets who used to lose Wednesday afternoons to "can you just check the calendar real quick" got Wednesday afternoons back.

The number we cared about more than the 40 seconds: zero double-bookings in the first eleven weeks of operation, against an average of three to five per week before.

What we'd do differently

We'd start with the calendar read sync earlier. We treated it as plumbing and it turned out to be the load-bearing wall of the whole system. If your PMS is older than five years and lacks a real API, plan for two weeks of plumbing before you write a single line of agent logic.

We'd also instrument the euthanasie flag from day one rather than week three. We got lucky that no edge case slipped through. We shouldn't have had to be lucky.

When we built the chat agent for the Tilburg vet group, the thing we ran into was that the Animana calendar drift between the read replica and the live system was wider than the docs suggested. We ended up solving it with a 90-second reconciliation loop and a write-verify-read pattern on every appointment. If you're staring at a similar inbox problem against a legacy system of your own, that pattern (and a few others) is what our AI agents work is built on.

The smallest thing you could do today: open your shared inbox, count how many of the last 100 threads are the same question rephrased. That number is your agent's first job.

Key takeaway

An inbox agent is only as good as the conversations it knows to stay out of. Flag the euthanasie thread before you optimise for the rebooking thread.

FAQ

Why not just use Animana's own appointment widget?

It exists but it doesn't read free-text Dutch emails, doesn't classify intent, and can't route a euthanasie thread to a human. It's a form, not an inbox agent.

Is screen-scraping Animana safe long-term?

Not really. We use a thin RPA path for writes and a synced read replica for queries, with a heartbeat that catches session expiry. Every Animana release gets a smoke test before deploy.

How do you stop the agent from auto-replying to an emergency?

Seven-intent classifier with two intents (clinical_urgent and bereavement_or_euthanasia) hard-blocked from automated replies. Flag is over-eager by design. False positives are cheap; false negatives are not.

What happens if the agent proposes a slot that the vet then cancels?

The reconciliation loop re-reads Animana every 90 seconds and re-confirms with the owner if a proposed slot disappears before they reply. We never close a thread on an unverified write.

Could a smaller clinic afford this?

The euthanasie-routing piece is worth building at any clinic size. The full rebooking pipeline pays back fastest above about 600 weekly threads, where a human inbox role is already strained.

ai agentschat agentsautomationcase studyworkflowintegrations

Building something?

Start a project