Let's talk
Menu

AI systems / Conversation

A useful assistant, not a widget.

Drag or use arrow keys to orbit

AI chatbots

Customer and internal assistants grounded in your content and connected to the actions people actually need.

What we build

Useful from
day one.

RAGLLMsTool callingAnalytics

Grounded answers

Responses use approved sources and cite the evidence behind them.

Actions beyond chat

The assistant can look up orders, create tickets, or hand work to a human with context.

Operational feedback

Unanswered questions and failure patterns become visible inputs for improvement.

The route to production

Clear steps.
Visible progress.

01

Discover

We map the real workflow, risks, users, and success measure before choosing an implementation.

02

Build

Working software lands in visible increments, with the hardest assumptions tested first.

03

Prove

We validate against production-shaped data, failure paths, performance, and real use.

04

Ship

Deployment, monitoring, documentation, and a clean handover are part of the build.

View all services ↗

Verified client reviews

In their words.

“I recommend him due to his thoroughness and quality.”
Jordan GreggNew City, USA · 4.7 ★
“Fantastic and easy to communicate with!”
CreativeZeth DesignsChicago, USA · 5.0 ★

Before you ask

Questions,
answered.

What can an assistant like this actually resolve?

Less than a demo suggests, and the gap is knowable before you build. On the first support bot we were called in to rescue, we exported a thousand tickets and sorted them by intent: fewer than a fifth were answerable from documentation at all. The rest were lookups against Shopify, Stripe, a subscriptions table and a carrier API, plus a judgment call about whether the customer gets money back. Sorting your own queue by intent first tells you whether you need retrieval, tools, or a better help centre.

Should we build a custom assistant or use an off-the-shelf platform?

Our rule of thumb is that if the bot only talks, buy it; if the bot needs to do, build it. Hosted platforms are genuinely good now and will have a marketing or FAQ bot live in an afternoon for a predictable fee, and building that from scratch would waste money and weeks. Custom earns its cost the moment the assistant has to take real actions inside your systems, when data control is a hard requirement, or when the conversation is part of the product rather than a widget bolted onto it.

Can you just point it at our website or help centre?

That is the default move and it fails in two specific ways. Crawled pages carry the same navigation, footer and cookie banner in every chunk — on the sites we have measured that chrome is 60 to 80 percent of the tokens on a page — so the index collapses toward a single point and a cancellation question can retrieve the careers page. And documentation describes the happy path while resolved tickets describe reality. We build the index from resolved threads, agent macros and versioned policy documents with effective dates, not scraped HTML.

How do you stop it inventing answers?

Refusal is a feature you build, not a setting you enable. We put a floor on the reranker score, tuned against an evaluation set, and short-circuit below it: no generation call at all, just a scripted line and a route to a human. Answers are constrained to the retrieved passages and render citations a reader can open and check. On one build for a medical device distributor, 11 percent of questions hit a hard-refusal rule, and that 11 percent is why legal signed the launch.

Can the assistant do things, not just answer questions?

Yes, and for most support queues that is where the value is. Each action is a typed function with a narrow contract — an order lookup returning six fields, rather than open access to a database. Writes such as refunds, cancellations and address changes sit behind explicit confirmation, a value cap, an idempotency key so a retry cannot pay twice, and an audit row. Retrieval answers policy questions; tools answer account questions, and account questions are most of the volume.

How do you stop it showing one customer another customer's data?

By never letting the model choose whose data it reads. The customer identifier comes from the authenticated session and is injected server-side into every tool call, and if the model emits one the tool layer discards it. On the retrieval side, every chunk carries the group IDs allowed to read its source and the search runs with a metadata filter built from the caller's resolved groups, so nothing unauthorised is retrieved in the first place. Telling the model to respect permissions in the prompt is a suggestion, not access control.

What happens when it does not know the answer?

It hands over, and the handover carries weight. We hard-code the exits: billing disputes, account access and security issues, an explicit request for a human, the same intent raised twice without resolution, and retrieval confidence under a calibrated threshold. The ticket that lands in your helpdesk includes the full transcript, every tool call and its result, and a one-line summary of what was already attempted, so nobody asks for the order number a second time. Customers forgive a bot that does not know things; they do not forgive one that traps them.

Is deflection rate the number to judge it on?

No, and it is the number most vendors lead with. Deflection usually means a conversation ended without a human touching it, which scores your worst outcomes as wins — the customer who got three paragraphs of generic billing copy, closed the widget and filed a chargeback counts as contained. We inherited one deployment reporting 68 percent containment where honest resolution was near 30. Measure resolution verified by no follow-up on that topic, reopen rate on bot-closed threads, and how many minutes a rep burns re-establishing context.

How fast does it have to be?

A chat widget competes with the back button, so our budget is a first token under 900 milliseconds. The fashionable architecture blows it before you notice: rewrite the query with a model, embed, retrieve, rerank with a second model call, then generate — four round trips before one character reaches the visitor. We inherited an agency-built widget that took 6.2 seconds to start talking and lost 38 percent of sessions before the first token landed. Keep the hot path short, stream from the first token, and cache the handful of questions that are a third of your traffic.

What does keeping it working after launch involve?

Mostly the data, not the model. Ingestion is a recurring sync with deletions reconciled, because a soft-deleted page keeps answering questions for months otherwise. A fixed set of real questions runs on every prompt, content or model change, since the failure mode here is silent regression — someone edits one line to fix a complaint and quietly breaks nine answers that worked yesterday. And every question the assistant could not answer goes into a weekly review, which is the highest-signal content backlog your team will get.

From the journal

Further reading.

Start with a paragraph, a Figma, or a Loom.

Build this properly.Reply within one business day · one clear scope · one fixed number