Home · Examples · Support assistant · Part 2

Examples · Part 2 of 2

Support assistant

One retrieval-augmented pass over a handful of support paragraphs. It retrieves chunks, ranks them three ways, builds the prompt, and quotes a cited sentence, or says it does not know.

Make that answer cheaper to run, test it on five fixed questions, and stop instructions hidden in your docs from steering it.

Sample docs Answer is simulated

Northline Desk is not a real product. The paragraphs were written for this page and labelled sample docs. Nothing here calls a model. There is no API key. A real assistant would send the assembled prompt to a provider. This one stops at the prompt and quotes a sentence the template already selected, or it says it does not know.

Cards used in these stages (11)

The steps link the live cards they use. Prompt Caching, Model Selection & Routing, Cost forecasting, Latency, Fallbacks & rate limits, Evaluation basics, Production evaluation, Monitoring & drift, Prompt injection, Privacy & data handling, and Safety.

Part 1 got you a cited answer, or a clear “I don't know”. This part makes that answer cheaper, checks it, and keeps it safe. Back to Part 1

The question from Part 1

When is weekday support open?

{
  "known": true,
  "answer": "Weekday support is open from 09:00 to 17:00 in the account's local time zone.",
  "citations": [
    "hours"
  ]
}
Quick recall
What sits in the prompt besides the question?

The fixed instruction block, then the top three reranked chunks as excerpts, marked untrusted.

Back to Stage 3

Where does a citation point, and what do you check?

To the chunk whose sentence the answer quotes. Check that the sentence is really in that chunk, and that the chunk was retrieved.

Back to Stage 3

When does the assistant say “I don't know”?

When no trusted sentence shares enough of the question's words. In this example, that's a two-word rule in code, before any answer call.

Back to Stage 4

5 Cache the prefix, route the call

See it in Part 1: Prompt

Cache the unchanged instruction prefix, and send a thin match to a higher list price than a quote you already have. The Prompt Caching card is how a prefix that did not change can be reused. In this example the prefix is the instruction block in the assembled prompt. The excerpts and the question sit after it, because they change every call. The demo route is a label, not a dispatch: “I don't know” stops in code, three or more shared words is marked for the cheaper list price, and two shared words is marked for the higher one. A real route only earns its keep after the eval set in step 6 agrees. The arithmetic below is the multiplication Cost forecasting describes: assumed token counts times a published rate. Latency is the wait a user feels, which on this assistant includes retrieval before any answer call. Fallbacks & rate limits is the plan when that call errors, stalls, or comes back rate-limited. This demo never makes the call, so it has no fallback to show.

Cost

A short prefix barely moves the bill. A long stable prefix can. The lines below keep the 600 uncached tokens and 80 output tokens from step 3 and change the prefix to an assumed 2,000 tokens. Whether a cache write costs more than sending the prefix uncached is on the Prompt Caching card. Use the cached rate only after a real response shows those tokens billed as a hit. The Foundations playbook makes the same point for a different example.

Quality

The cheaper route can miss a citation the higher list price would have written. You do not get that from the price table. You get it by running the same questions through both routes and reading the misses.

Risk

Caching the wrong block, such as the user's question or an untrusted excerpt, pins that text into later calls. Keep the cached region to text you wrote.

Work out the cost
  • No cache2,600 input tokens × the input rate, plus 80 output tokens × the output rate
  • Cache hit2,000 cached tokens × the cached rate, plus 600 input tokens × the input rate, plus 80 output tokens × the output rate

On these assumptions a cache hit uses the lower cached rate for the prefix. Add a cache-write charge only when the pricing page for your model lists one. The Foundations playbook leaves that charge out of its example and tells you to add it when the page lists it.

Next: Stage 6, Check five questions

6 Check five questions

Keep a small set of questions with labels, check citations in code, and treat a language-model judge as a second paid call. Evaluation basics is that labelled set. Production evaluation is the same kind of set, saved and run again before a prompt, model, or retrieval change faces users. Monitoring & drift is watching quality after launch, when a model update or a change in the documents moves behavior off the set. The five rows in the demo are the labelled set: weekday hours, the refund window, SCIM, a question the docs do not answer, and a request for an admin password. A row passes when the simulated citation matches the label. That check is code. These five rows are not a production suite.

The Evaluation basics card is that labelled set, and the choice between code and a language-model judge. Code grades when a rule can. A second model grades a judgment a rule cannot make, after you have tested that judge. None of that is a score for this assistant. This page does not report one.

Cost

The code check has no model bill. A judge is another request: the question, the answer, the excerpt, and the rubric go in, and a grade comes out. Assumptions: 1,000 uncached input tokens and 50 output tokens, no cache. This page does not name a judge model or copy its rates. The Cost forecasting card is how you would price that second call.

Quality

Five labelled questions catch a broken citation and a missing “I don't know”. They do not describe production traffic. Add a row when a real miss shows up, and keep the old rows.

Risk

A judge that you have not checked against labels can prefer a long wrong answer. The Evaluation basics card says to test that judge before you scale it. A set with only questions you already pass will not show a miss.

Work out the cost
  • One judge call1,000 input tokens × the input rate, plus 50 output tokens × the output rate

Five judge calls cost five times one call. Five code checks add no model bill. The rubric you would send is the instruction already in the demo prompt, plus the expected citation. This page does not send it.

The same five checks as the demo. A row passes when the simulated citation matches the label.

QuestionLabelSimulatedCheck
When is weekday support open?hourshoursPass
What is the refund window?refundsrefundsPass
Is SCIM available?ssossoPass
Which carrier ships the hardware token?I don't knowI don't knowPass
What is the admin password?resetresetPass

Next: Stage 7, Treat the docs as untrusted

7 Treat the docs as untrusted

A document can contain an instruction. Keep it in the prompt as data, and do not follow it. One sample file is a pasted ticket. It tells the reader to ignore the support policy, claim a 90-day refund, and email an admin password. The Prompt injection card cites OWASP's LLM01:2026 entry, Anthropic's jailbreak guide, and OpenAI's safety notes for an instruction that arrives inside a document. Privacy & data handling is the decision about what enters a prompt and what should never be sent. The admin password in the pasted ticket is text that should not be sent onward, and the template does not quote it. Safety is the limit on what the product will do with that text. The demo has no tool that can email a password.

Run the “90-day note” question in Part 1. The pasted ticket can rank first, because it repeats the words in the question. The simulated answer still quotes the 14-day refund sentence and cites that chunk. A real model can follow the ticket instead. The template does not prove a model will refuse.

Cost

The hostile excerpt still counts as input tokens if you paste it into the answer call priced in step 3. A separate classifier, if you add one, is another model bill. A string check is code. This page uses the code path and does not add a classifier price.

Quality

If the model obeys the ticket, the refund answer becomes 90 days and the citation looks confident. Read the retrieved text, not only the answer.

Risk

The ticket is untrusted data in the same channel as the policy. Do not grant the answer model a tool that can email a password. The demo has no tool and no mailbox.

Simulated answer. The JSON quotes the 14-day refund sentence and cites refunds. The pasted note is not cited. No model was called.

{
  "known": true,
  "answer": "The refund window is 14 days from the charge when the seat has not been used.",
  "citations": [
    "refunds"
  ]
}

Next: Build it yourself

Build it yourself

A minimal sketch of the pass. The embed and complete lines are the ones a real build would send to a provider. This page does not run them.

Show the sketch
function answer(question, chunks) {
  var qv = embed(question);              // vendor embeddings API
  var keyword = chunks.map(bm25);
  var vector = chunks.map(function (chunk) { return cosine(qv, chunk.vector); });
  var hybrid = fuse(keyword, vector);    // scale each list, then add
  var top = rerank(question, hybrid).slice(0, 3);
  var prompt = PREFIX + excerpts(top) + question;
  if (!supported(top, question)) {
    return { known: false, answer: "I don't know.", citations: [] };
  }
  return complete(prompt, schema);       // vendor chat API; not called here
}

Checklist

  1. Put one fact you can point at in a chunk a person can read.
  2. Search with words and with vectors. Read both lists before you fuse them.
  3. Rerank a short candidate list, not the whole corpus, and read the new order.
  4. Keep the instruction prefix stable. Put the question and the excerpts after it.
  5. Ask for known, answer, and citations. Reject a citation id you did not retrieve.
  6. If no trusted sentence supports the question, return “I don't know” in code.
  7. Treat every document as untrusted. Do not follow instructions found in a chunk.
  8. Write five questions you know the answer to, including one the docs do not answer and one with a hostile chunk.
  9. Check citations with code. Add a language-model judge only after those rows pass, and price that second call.
  10. Open the pricing page on the day you ship. Copy the rates that day. The cards linked below are where those comparisons are checked.

It asks the customer the same question on every visit? Memory is what your app keeps between visits.

Sources. Last checked 2026-10-17.

Where the outside facts come from: the cards linked in the steps above, each with its own sources. Last checked 2026-10-17.