Tutorial: Show the Serving Tier Beside Every AI Draft
Last Tuesday a reviewer approved an AI draft in four seconds. The draft had quietly dropped a refund clause. Nobody in that room knew which model had answered, or whose server ran it. Was the reviewer careless? Not really. She had no evidence to weigh.
That is a design failure, not a people failure. The interface asked her to trust a draft while hiding where the draft came from. So let me ask you something. If your product cannot say which tier served a request, what exactly is your reviewer approving?
This tutorial builds that missing evidence, end to end. You will run a probe, render a tier strip, write stop conditions, and check accessibility. Each stage ends with a verification step you can actually execute.
A word on the tool I use throughout. MonkeyCode is an open-source AI coding project you can try in the browser or self-host. Its outreach brief advertises free model access and a free server option, plus a ten-million-token allowance. I treat all three as claims to verify, not facts to design around. That is the whole point of the harness below.
Disclosure: This article was prepared as part of MonkeyCode's product outreach.
Stage 0: Write the claims file first
Before touching code, write down what you were told. Mine looks like this.
mkdir -p claims && cat > claims/free-tier.md <<'EOF' # Free tier claims (unverified) - free model access | source: outreach brief | checked: never - free server option | source: outreach brief | checked: never - 10,000,000 token grant | source: outreach brief | checked: never - open source repository | source: outreach brief | checked: never EOF One line per claim, with a source and a check status. The token number is the one I trust least, because quotas move quietly. Write it down anyway. An unverified number in a file is honest; an unverified number in a slide is a bug.
Verify: cat claims/free-tier.md shows four lines, each with checked: never. If any claim has no source, delete it.
Stage 1: Probe the endpoint once
Now get one real response and record what the wire gives you. Node 20 has fetch, so no dependencies.
// probe.mjs — run: TIER=free node probe.mjs const base = process.env.MC_BASE_URL; // from the project docs, not guessed const key = process.env.MC_API_KEY; const model = process.env.MC_MODEL; // never hardcode a model name const tier = process.env.TIER ?? 'unknown'; if (!base || !key || !model) { console.error('missing MC_BASE_URL / MC_API_KEY / MC_MODEL'); process.exit(2); } const t0 = Date.now(); const res = await fetch(`${base}/chat/completions`, { method: 'POST', headers: { 'content-type': 'application/json', authorization: `Bearer ${key}` }, body: JSON.stringify({ model, messages: [{ role: 'user', content: 'Summarize this clause in one line: refunds within 14 days.' }], max_tokens: 120 }) }); const body = await res.json().catch(() => ({})); console.log(JSON.stringify({ tier, http: res.status, model_returned: body.model ?? 'unknown', finish_reason: body.choices?.[0]?.finish_reason ?? 'unknown', usage: body.usage ?? 'unknown', ms: Date.now() - t0 }, null, 2)); The endpoint shape above assumes an OpenAI-compatible route. Check the project docs before you trust it. If the shape differs, fix the script, not the log format.
Verify: run it twice. You want a finish_reason and a model_returned string. If either is unknown, keep it as unknown in your UI later. Guessing is how the refund clause disappears.
Stage 2: Render the tier receipt
Here is the pattern. Put it directly under the draft, above the approve button.
┌ Draft: refund policy summary ─────────────────────┐ │ ...text... │ ├ Serving tier ─────────────────────────────────────┤ │ tier free (hosted) │ │ model <model_returned, or "unknown"> │ │ finished stop | length | unknown │ │ latency 1.9s │ │ context complete | truncated | unknown │ │ [ Hand back to me ] [ Approve ] [ Return ] │ └───────────────────────────────────────────────────┘ Six fields, no decoration. truncated and unknown are first-class values. A strip that can only say "success" is theatre, and your reviewers will learn to ignore it.
Use plain language in the visible label. "Free shared model" beats "tier_0" every time. Reviewers are not reading your enum.
Verify: force each of the three context values with a fixture and screenshot all three. If you cannot produce unknown on demand, you cannot produce it in production either.
Stage 3: Write stop conditions before the study
A receipt is worthless without a rule for when it stops the flow. Run five scenarios with five people, and give each a stop condition.
| Scenario | What you inject | Measure | Stop condition |
|---|---|---|---|
| Context overflow | 40-page doc | Did they notice truncated? | Two misses in a row |
| Rate limit | HTTP 429 | Did they retry or escalate? | Silent auto-retry seen |
| Slow reply | 12s delay | Did they approve blind? | Any approval before it renders |
| Refusal | Model declines | Could they recover in one step? | Rage click on Approve |
| Mid-task failure | Drop the response | Did hand-back work? | Draft lost, no copy |
Record clicks, not opinions. When two participants approve a truncated draft, stop the study and fix the strip. Do not finish the sample to be polite.
Verify: after each session, check you have one timestamped event for every stop condition you wrote down.
Stage 4: Draw the recovery path
request ─▶ tier receipt ─▶ reviewer │ │ unknown/truncated ├─ approve ─▶ publish │ ├─ return ─▶ edit ▼ └─ hand back ─▶ human writes hand back to human The hand-back must be one click, and it must keep the draft. If returning a draft costs typing, people approve instead. That is a design decision, not a training problem.
Verify: with the network throttled to offline, click hand back. The draft text must survive.
Stage 5: Check accessibility
The strip carries a decision, so it must be reachable and readable.
Test it with a screen reader in one pass. Confirm the tier is announced as text, not color alone. Confirm truncated is in the accessible name, not only in an icon. Confirm the hand-back button is first in tab order after the draft. Confirm error text is tied with aria-describedby, never placeholder-only. Confirm contrast of the strip at 200% zoom.
One more check people forget. Read the strip aloud. If it sounds like a log line, rewrite it for humans.
Verify: tab from the draft to hand-back without a mouse. If focus skips it, you have a blocking bug.
Stage 6: Decide with evidence, not vibes
The table below is my rule for designing around a free tier. It is a proposal, not a finding.
| Evidence you hold | Design around free tier? |
|---|---|
| Receipt renders tier, model, finish reason | Conditional yes |
unknown states are visible and testable | Conditional yes |
| Hand-back works offline, keeps draft | Yes |
| Stop conditions met, no misses | Yes |
| Quota still unverified for your volume | No, spike first |
| Receipt exists only in logs, not UI | No |
If the last row is true for you, stop. Logs are for you. The receipt is for the person who clicks.
Limitations, and who should skip this
This harness measures interface honesty, not model quality. It will not tell you whether a free model writes good refund copy. It will only tell you whether your reviewer knew what she was reading.
Skip it if you have no human approval step, or if no draft leaves the system. Skip it if you cannot read your provider's response fields at all. And skip the token arithmetic entirely until someone with the account confirms the current grant.
Want a place to run the probe against something real? MonkeyCode's free model access and free server option make a reasonable test bench, and the project is open source. Try it, then read your receipt out loud. If it cannot say which tier answered, your reviewer is still guessing.

