azyware
B2B SaaS platform for field-service businesses ■ APR 2026

An in-app copilot that made a field-service SaaS the tool users open first

Built a context-aware copilot inside an existing SaaS product: natural-language reporting, scheduling actions and drafting, metered per tenant and sold as a premium plan.

Context

The client sells a scheduling and job-management platform to field-service businesses: HVAC contractors, pest control, electrical firms, mostly in the United States, with a growing base in India. The product is mature, with a large data model covering customers, jobs, technicians, invoices and parts. Like most SaaS companies in the last two years, they had shipped an AI chat widget. It answered questions from the help centre. Usage fell to near zero within a month of launch, and the sales team had stopped mentioning it.

The product leadership wanted something different: a feature customers would pay more for, that reduced churn among small businesses who found the product powerful but hard to use, and that could ship without a rewrite of a backend they had spent six years building.

The problem to solve

The failure of the first chatbot was instructive. It had no idea which customer, job or screen the user was looking at, so every question had to be fully specified, and it could not do anything, only explain. Users learned faster to click through the UI than to type. A copilot had to reverse both of those: it had to know the context, and it had to act.

There was also a commercial design question. The client wanted the copilot on a premium plan, which meant per-tenant usage had to be metered and billed, and the AI cost per account had to be predictable enough to price.

Approach

We ran Sprint Zero first. In ten days we mapped the product's API surface, sat in on support calls, and worked with the product team to write down the ten jobs a copilot would be asked to do most often, ranked by how much time they saved. The top three were unglamorous: build a report from a plain-English question, reschedule a set of jobs when a technician called in sick, and draft the customer message that follows an estimate. Those three became the scope of the first release.

  • A context layer that passes the current account, user role, open record and screen to the copilot on every request, so questions can be short.
  • An action framework where each copilot action maps to an existing, permission-checked API call. The copilot cannot do anything the user could not do with clicks.
  • Retrieval over the tenant's own data (jobs, customers, notes) and over the help centre, kept strictly per tenant.
  • Routing between a frontier model for planning and drafting and a smaller model for classification and extraction, to keep cost per request low.
  • Streaming responses with a visible stop button, inline confidence notes and a clear hand-off back to the normal UI when a request is out of scope.
  • Per-tenant metering written to the existing Stripe billing, with soft limits and an admin view of usage.

What we built

The copilot lives in a right-hand panel opened with a keyboard shortcut or a button in the top bar. It is built as React components dropped into the client's existing front end, talking to a new Node.js AI service that sits beside their backend and calls it through the same authenticated API the UI uses. No data model changes were needed.

Reporting works through a semantic layer we wrote over the client's core tables: named metrics like revenue per technician and first-time fix rate, canonical joins, and named time periods. A question becomes a validated read-only query, and the answer comes back as a table or chart with the definition of each metric shown on hover. Scheduling actions are planned by the model, shown to the user as a proposed set of changes, and executed only on confirmation, one API call per change. Drafting uses the account's own tone settings and the history of the customer in question.

An evaluation suite runs on every release: a golden set of two hundred real questions and requests gathered from support tickets, scored on whether the copilot produced the right report, proposed the right changes or drafted a message the product team would send. Prompts are versioned and every request is traced, so a regression can be located to a prompt or model change within minutes.

Delivery

Nine weeks from Sprint Zero to a private beta with twenty accounts chosen by the customer success team, including several that had flagged churn risk. Beta feedback drove two changes that would have been expensive to guess: the report builder needed an obvious way to save a question as a recurring report, and the scheduling action needed to show technician travel time in the proposal. General availability at week twelve, on a new plan tier, with the existing chat widget retired.

Outcomes

The copilot is used weekly by a large share of accounts on the new tier, which is the number the product team watches most closely; the previous chatbot never got past a handful. The report builder absorbed a class of support tickets that had previously needed a customer success call. Customer success reports that several churn-risk accounts from the beta cohort renewed, citing the copilot, and the sales team now demos it first.

AI cost per account settled well inside the plan's margin after routing was tuned, and the billing team has a usage dashboard they did not have to build.

What we measured

  • Weekly active copilot users per tenant
  • Actions executed versus answers only
  • Report requests handled without a support ticket
  • Eval score per release on the golden set
  • AI cost per account per month
  • Retention of the beta cohort at 90 days

Architecture in brief

The copilot is deliberately a thin layer. The AI service holds prompts, routing rules, the semantic model for reporting and the evaluation harness; it holds no customer data of its own. Every read goes through the client's API with the user's token, every write is a proposal until the user confirms it, and every request is traced end to end in Langfuse with the prompt version, model, latency and token cost attached. That design made three things simple that are usually hard: security review, because there was no new data store to review; cost control, because routing decisions are visible per request; and rollback, because a bad prompt is a version pin away from the previous one.

The React components are published as a small internal package so the client's front-end team can place the copilot on new screens without touching the AI service. Two new screens have shipped with the copilot since general availability without our involvement, which was the point.

What we learned

The single decision that mattered was making every action go through the existing permission-checked API. It kept the copilot trustworthy, it kept the build inside the client's architecture, and it meant security review took a week rather than a quarter. The second was scope: three jobs done well beat twenty done vaguely, and the beta told us exactly which job to add next.

We continue to work with the client on a monthly retainer, adding one copilot job per release cycle.

"We had a chatbot nobody used. Now we have a copilot that our customers mention on renewal calls. The difference was that it can actually do things in the product."
VP Product, SaaS client

Client details are anonymised. Figures are described qualitatively and are available under NDA on a call.