Skip to content
OrtmannConsulting
Back to all projects

Customer service, construction chemicals

From a 114-widget phone menu to a voice assistant

Callers say what they need in their own words instead of tapping through three menu levels. The language model is never allowed to name a destination — it picks from a list, and the phone system dials.

Year
2026
Services
Artificial intelligence · Communications
Area
Contact centre
Role
In-house, employed

Delivered in an employed role for an internal department, not under an external consulting contract. The organisation is not named.

114 → 18Widgets in the call flow
5Turns before a humanafter which it always goes to reception
1.2 sBudget for the caller-name lookup

The situation

The predecessor is checked into the project folder: a menu tree of 114 widgets with 10 keypad menus, nested up to three levels deep. Someone trying to reach a specific customer service team heard a main menu, then a brand menu, and in one branch a third.

What triggered the project is documented nowhere — no tickets, no abandonment figures, no brief. The only motivation recorded in writing is a single project note: callers should be able to say what they need instead of navigating. Whether misrouting, drop-off or switchboard load drove it would be reconstruction on my part.

The approach

Calls enter the existing call flow, and the checks already running there — blocked numbers, business hours, direct dial — still run first, untouched. Only calls that would previously have hit the old menu reach the assistant.

The phone system then opens an audio session to a small Node.js service. Speech-to-text and text-to-speech stay with the platform; the service sees text and owns the conversation. It greets the caller by first name if a lookup against the customer database answers within 1.2 seconds — otherwise unnamed, with the name slipped in once it arrives. Every greeting states that the caller is speaking to an automated assistant; a test enforces this, because Article 50 of the EU AI Act requires it.

Each turn goes to a language model whose system prompt is assembled per call from a typed configuration: departments and their descriptions, brand names, and known speech-recognition mishearings of those brand names. Once the model understands the request it stops replying in prose and calls one of four tools.

Where it could have gone the other way

The model is never allowed to name a destination. It picks from a list, and the platform dials.

This could have gone the other way — you can let the model return a phone number or queue name directly. Instead the tool definitions are built per call, with destination parameters declared as enumerations drawn from the country configuration. The model cannot choose anything that does not exist. Its answer is then re-validated against that same configuration, and any mismatch routes to reception.

The phone numbers never reach the model at all. It emits an abstract key such as finance_payroll, which the call flow resolves itself.

The same instinct runs throughout: five turns maximum before handing to a human, and every failure path ending at reception. The accepted price is that the assistant can never be cleverer than its configuration, and a new destination needs a config change and a deploy.

The result

The call flow shrank from 114 widgets to 18. The conversation service is around 1,870 lines of TypeScript, covered by 38 tests. Every call is written to the reporting database with its transcript, where agents rate each decision correct or incorrect — the basis for improvement is produced by running the thing.

Honest about status: one country is live. The design is explicitly multi-country, but only one configuration is registered. The operations document sets an internal target of 80–95% of calls routed without falling back to reception; at the point this was written, that was a target, not a measurement.

Deliberately open: the improvement loop is manual. A weekly review reads the telemetry, spots new mishearings and unhandled intents, and feeds them back as configuration edits. Nothing tunes itself — and reception remains the safety net by design, not the exception.

Stack

  • TypeScript / Node.js
  • Azure OpenAI
  • Twilio ConversationRelay
  • Azure App Service
  • SQL Server

More projects

Group customer service, construction chemicals

2026
11Countries on one platform

One contact centre for eleven countries — one platform, not eleven islands

Customer service across eleven countries over voice and SMS, with data from SAP, Salesforce and the product system surfaced directly in the agent workspace. Country differences are configuration, not separate installations.

  • Twilio Flex
  • Twilio TaskRouter
  • Twilio Studio
  • SAP

Sales & inside sales, construction chemicals

2026
1 + 3Orchestrator and specialist agents

One orchestrator, three specialist agents for product questions

Instead of one agent with three knowledge sources, a parent agent routes to three specialists — one each for ERP article data, product content and SharePoint documents.

  • Microsoft Copilot Studio
  • Azure AI Search
  • Azure Functions
  • SharePoint

A similar process at your company?

30 minutes, free, no sales pitch. You describe what is costing you time — I tell you honestly whether automation is worth it.