np-2026-08-r4, the newest and
the default, np-2026-08-r3, and np-2026-07-r2, which a caller had to pin
explicitly starting from when the default moved to r4; see
release notes. np-2026-07-r1
stays resolvable for work that cites it and is not a label to start on.
This page describes what each label does, in terms you can see in a
response. It does not rank them by quality.
What differs, on the wire
Everything in this table is observable in a response you can produce yourself.
Row two is the one that decides most migrations for a workload that leans
toward standing down: see the stand-down
case, where r2 returns nothing and r3
and r4 return your whole context instead, neither charged for it. It is not
the only outcome on this page, though: the canonical request
below is a case where all three
labels find something worth selecting, and select different amounts of it.
Whether either pattern holds across your traffic, and what it costs there, is
a question only your traffic can answer, which is what the
evaluation step is for.
selection_recall and records_admitted are additive response fields that
np-2026-08-r3 and np-2026-08-r4 emit and np-2026-07-r2 does not;
np-2026-08-r4 adds four more top-level fields. A client that follows the
rule about
ignoring unrecognised fields
needs no change to accept them.The same request under all three labels
This is the canonical billing-dispute request, unchanged except forbudget.operating_point. It is a 30-record request now:
the same billing dispute, plus support-desk distractors, enlarged specifically
so a reader could see all three labels engage on it rather than only r2. Run
it yourself and you will get these numbers.
r-008, r-009); r3 and r4 select the same five records as each other, in
the same order, for the same token arithmetic: those two plus the refund
policy and its exceptions (r-004, r-005) and a prior agent turn
(r-021). All three are charged at the full rate, because all three engaged.
r3 and r4 agree here down to the byte count, unlike on the stand-down
example below, where they also agree
with each other but differ from r2 in kind, not just in count. Do not read
“r3 and r4 selected the same records” as a general rule: it is a property of
this request, not a guarantee. Evaluate on your own
traffic rather than assuming it
transfers.
format_metrics.attempted_recall_rungs holds one entry on both.
Their selection_recall blocks otherwise carry the shape the wire-differences
table above describes, at version: "npsr-2026-08-r1"
on r3 and "npsr-2026-08-r2" on r4:
And a request where all three agree
Forty filler records and one that answers the question, at a 600-token budget. Build it yourself:n-001 and nothing else. All three report
records_selected: 1, tokens_before: 2418, tokens_saved: 2360 and
reduction_ratio: 0.9760132340777502, and all three engage rather than fall
back, at charge_multiplier: "1.0". The selected set and the token arithmetic
are identical across the three. The responses also differ in the additive
fields r3 and r4 add, in selected[].reason, selected[].score and
gate.reason, and r4 inserts a newline in both selected[].excerpt and
rendered_context. The reason strings are open-ended, and none of these
differences changes the selected record.
We include this deliberately. It is the case a “the newer label is stronger at
long sparse retrieval” story would predict a difference on, and there is none.
Do not pick a label on a story; pick it on your own traffic.
A stand-down is a correct outcome
The most common surprise on a first integration is a response that saved nothing. Usually nothing is wrong. Needlepath selects when there is a selection worth making. Two ordinary situations produce no savings:Your context already fits
Your context already fits
If everything you sent fits comfortably inside
max_context_tokens, there is
no pressure to relieve, and cutting would only lose you information for no
gain. You get your context back. The
three-record example does exactly this.Nothing stood out
Nothing stood out
If no record scores meaningfully above the others against your task, there is
no defensible subset to choose. Returning an arbitrary one would be worse than
returning all of them.
What that looks like under each label
Three small records, a 4000-token budget, and nothing under pressure. This is the three-record example, sent unchanged to all three labels. One of the three is sent withimportance: 0.0, the lowest
priority the signal has; it comes back on r3 and r4 exactly like the other two.
importance: 0.0. A
full-context fallback does not filter by importance; nothing is dropped for
any reason on that path. None of the three is charged: stood_down on r2 and
pass_through on r3 and r4 both carry charge_multiplier: "0". All three
hand you a context you can send. It is still worth measuring on your own
traffic before switching: a fallback that changes the token total is charged,
and how often that happens is a property of your workload.
Both are 200 responses. Neither is an error, and neither means the integration
is broken. Read them like this:
If most of your traffic stands down, that is a signal about the workload
rather than a fault: you are probably calling on contexts that already fit. The
homepage has the fit criteria. Measure it with
shadow mode before you tune anything.
Evaluating a newer label on your own traffic
Nothing below requires a code change beyond the value of one string.1
Mirror real traffic, do not switch it
Keep production pinned to the label it runs today. Send a copy of the
same requests with
budget.operating_point set to the label you are
evaluating, and discard the result. This is exactly the shadow mode pattern,
with the label as the only variable. Wrap it so a failure cannot touch the
real call.Both calls are metered, and each is billed according to its own receipt’s
charge_multiplier. Sample if that matters: a fixed fraction of requests,
chosen by a stable uniform hash of request_id rather than by content, keeps
the comparison representative and reduces the cost in proportion.2
Compare the pairs, not the aggregates
Log both responses against the same
request_id and compare per request:An aggregate savings figure will not tell you whether an answer degraded. The
per request dropped-record list will.
3
Spot-check the disagreements
Pull the requests where the two labels selected different records and read
them. That set is normally small, and it is the entire evidence base for the
decision.
4
Switch one string
When you are satisfied, change
budget.operating_point to the label you
evaluated in production. Nothing else in the request or the response
handling changes.Rolling back
Setbudget.operating_point back to the label production ran before the
switch: whatever label you pinned production to before you started evaluating
a new one. The warning below covers the case where there was nothing pinned to
go back to; the default itself has moved once already (np-2026-07-r2 to
np-2026-08-r4), which is exactly the scenario it describes.
That is the whole procedure, and it works because labels are immutable: the
label you left applies today the same configuration it applied when you left
it, so going back is not a migration, it is a one-word revert. There is no deprecation to race and no
deadline attached to any published label. Every published label stays resolvable.
What rollback restores is the configuration, which is the thing that changed
when you switched labels. It does not rewind the engine build, and it does not
need to: see
what a label pins.
Next
Operating points
What a label pins, what it cannot, and why it is opaque.
Shadow mode
The measurement pattern this page’s evaluation step is built on.
How billing works
What each
usage.outcome costs.Errors
Reading a stand-down in full.