every model spec’d & versioned · harness ✓ greenchangelog →

Writing · MCP & AI assistants

Designing an Assistant That Cites Its Spec Version

The prompt patterns, response templates, and refusal behaviors that make an AI assistant’s numeric answers reproducible.

By Worthune Staff · 2026-08-14

A financial assistant that cites its spec version has a different relationship with its user than one that does not. The relationship is the reason the design decisions below matter.

A financial assistant produces numeric answers on demand. The user asks a question, the assistant replies, and the number in the reply guides a decision. The question this piece answers is how to design the assistant so the number can be trusted and traced. The mechanism is deterministic-model tool use plus deliberate reply construction. The design decisions are prompt patterns, response templates, and refusal patterns. None of these is exotic; all of them have to be in place together for the assistant to earn the citation it displays.

The prompt pattern

The assistant’s system prompt establishes three postures. First, any question whose correctness depends on a constant or a formula must be answered through a tool call, not through natural-language generation. Second, the reply must cite the spec version of the tool that produced the answer, in a form the user can act on. Third, when a tool call fails because inputs are out of domain, the assistant surfaces the specific failure rather than substituting a plausible guess.

The three postures translate into concrete prompt instructions. The tool-use posture is a rule the model can apply consistently only if it is stated in the system prompt, not implied. The citation posture requires a response template the model fills in each time the answer includes a computed number. The refusal posture requires the model to know the difference between a validation failure and a subject-matter question, so that a refusal is specific and helpful rather than generic and evasive.

The response template

The assistant’s reply is not free-form. When the reply contains a computed number, the reply follows a small template. The number appears in its natural sentence position. A brief clause names the model and the spec version. A closing sentence names the assumptions the model made that the user should know about.

A concrete example clarifies. If the user asks whether it makes sense to refinance a specific mortgage, the assistant invokes the refinance model with the inputs the user supplied, receives the envelope, and constructs a reply. The reply might read: refinancing at the new rate produces a break-even in thirty-one months, computed with the refinance model, spec version 1.0.0. Because you plan to move in twenty-four months, the horizon-adjusted result indicates the refinance is not worth doing under the current assumptions.

The template does three things. It puts the number in a sentence the user can read at pace. It names the model and the spec version, so a user or reviewer who wants to verify can. It names the assumption the horizon input reflects, so the user sees where the recommendation came from. One precision matters here: in the envelope, assumptions means the model’s declared constraint notes plus its spec-version line — the move horizon is an input echoed back, not a model assumption, and the reply’s closing clause is the assistant restating that input, not quoting the assumptions field.

What the response envelope carries

The assistant does not see or invent the envelope; it receives it from the tool. A refinance response envelope contains an ok flag, the model name, the spec version, links to the model’s machine contract and human-readable spec (contractUrl and specUrl), the caller’s inputs echoed back, the outputs, any sentinel annotations, the assumptions the model version declared, the facts rows the model consulted with their period and source name, a cryptographic record over the model, spec version, inputs, and outputs, and a disclaimer. The assistant uses this envelope both to construct the citation and to preserve the audit trail. The full envelope should be stored alongside the conversation; the summary in the reply is the user-facing view. A complete real envelope, annotated field by field, is in the quickstart (/writing/quickstart-annotated).

Envelope fieldWhat the assistant does with itWhere it lands
modelNames it in the citation clauseIn the reply
specVersionNames it in the citation clauseIn the reply
inputsEchoes them in the reply when clarifying what was computedIn the reply and in storage
outputsProvides the numeric answerIn the reply
sentinelsRenders as plain-language messages, never as raw stringsIn the reply, when triggered
assumptionsSurfaces in the reply’s closing clauseIn the reply
factsAvailable on user request
not always in the reply bodyBehind a ‘show your work’ surface
recordStored with the conversationIn storage
contractUrl and specUrlLinks the citation to the published contract and specBehind the ‘show your work’ surface
disclaimerDisplayed once per session or per surfaceIn the UI

The refusal pattern

Tool calls fail. A negative interest rate is out of domain. A closing-cost value exceeding the principal is out of domain. An age above the model’s valid range is out of domain. In each case, the tool returns a specific error rather than a computed answer. The assistant’s job is to surface the failure in a way the user can act on.

The refusal pattern has three parts. Name the specific input that failed. Name the valid range. Ask the user whether they meant a different value. This is different from the generic refusal that many assistants produce (I cannot help with that) and different from the guess that many assistants substitute (the answer is probably around X). A good refusal is specific, actionable, and non-defensive; it treats the user as capable of correcting the input rather than as a problem to be managed.

A refusal is a feature, not a limitation. The piece Approximation vs. Computation (/writing/approximation-vs-computation) develops the argument for refusals in more depth; the design point for this piece is that the refusal pattern is authored, not left to the model’s discretion.

Handling sentinel outputs

Some models return sentinel values rather than errors when a scenario has no positive answer. The refinance model, for example, returns an Infinity sentinel when the new monthly payment is not lower than the old one, which means there is no break-even under the model’s current assumptions. The FIRE model uses an age-one-hundred sentinel to indicate that a user’s trajectory does not reach financial independence before that age under the given inputs. The emergency-fund model uses a two-hundred-forty-month sentinel to indicate that a savings plan does not reach its target within twenty years.

The assistant’s response template treats each sentinel as a specific message rather than a raw value. Infinity becomes under the current assumptions, refinancing does not pay for itself before you move. Age one hundred becomes under the current savings rate and expected return, the plan does not reach the target before a plausible working horizon. Two-hundred-forty months becomes the current savings rate does not reach the target within twenty years. In each case, the message names both the sentinel condition and the inputs that produced it, so the user understands what to adjust.

The audit surface behind the reply

The user sees the reply. A compliance reviewer, a future user, or the caller’s own risk team sees the audit surface behind the reply. The surface has three artifacts. The stored envelope, which lets the exact answer be recomputed. The conversation transcript, which shows what the user asked and what the assistant replied. The tool-call trace, which shows the specific tool invocations the assistant made, with inputs and outputs.

The audit surface is not what the user reads; it is what the reply is grounded in. A well-designed assistant makes the surface retrievable on demand but does not force it into the reply. Users who want the details can ask; users who do not are served by the reply alone. Both are served well because the underlying artifacts exist and are stored.

The show-your-work surface

Between the user’s reply and the full audit surface sits an intermediate view. The show-your-work surface is a caller-designed UI element that exposes the tool-call trace to the user in a readable form. The user sees a small link or icon; clicking it opens a panel showing the model name, the spec version, the inputs the assistant sent, the outputs it received, the facts rows referenced, and the assumptions. The panel is retrievable per reply, so a user reviewing an earlier answer sees the same information they would have seen at the time.

Assistants without a show-your-work surface still work; the show-your-work surface is the accelerant that turns the assistant from a black box into a glass box. Sophisticated users who reach for it find the assistant more trustworthy. Casual users who never open it are served by the plain reply. The surface serves both audiences without complicating the primary flow for either.

What this design refuses to do

The design deliberately does not include a fallback path for questions that require a computation the tools do not support. A financial assistant that answers every question is either useful or wrong. This design accepts that some questions do not have answers today and surfaces that fact honestly. When a user asks a question the tool set does not cover, the assistant says so, names what would be needed to answer, and stops. This is a scope discipline, not a limitation of the technology; it is what keeps the citations the assistant does produce meaningful.

The citation is a promise. The refusal, the response template, and the audit surface are what keep it.

The maintenance cycle

Model specs change. When they do, the assistant’s reply construction still works, but the spec version cited moves. Callers who pin the assistant to a specific spec version see stable behavior; callers who track the latest version see updated behavior with each release. Neither is wrong; both are defensible design choices. What is not defensible is silence about which choice was made. The response template should reflect the caller’s versioning posture: pinned versions surface the pin as an assumption; tracking versions surface the current version as a fact. The user understanding what version produced their answer is the whole point of the design.

Sources

  1. [1] Model Context Protocol specification. https://modelcontextprotocol.io
  2. [2] Approximation vs. Computation. https://worthune.com/writing/approximation-vs-computation