OptionalblockedThe turn was refused by INBOUND MODERATION before any model ran (SDK
0.63.0): text is the configured refusal line, not something a model
chose to say. Absent on every ordinary turn.
It exists because the two were indistinguishable on the wire — same
shape, same text — so an integrator could only discover a block by
A/B experiment, which is exactly what issue #3379 had to do.
OptionalblockedWhich gate refused: classifier is the moderation verdict (see
blockedCategories), term is the operator's literal denylist. The
matched term is deliberately never sent — this response reaches the app
client, which may be the end user's own browser.
OptionalblockedCategories that fired, on a classifier block.
OptionalblockedWHICH classifier window fired, and its char range in the scored text.
blockedCategories is a union across up to six overlapping 8,000-char
windows, so on a long input it says a category fired somewhere and
nothing more; this localises it.
Optionalduplicatetrue when the server replayed an already-completed turnId instead of
running the turn (0.72.0): no model call, no billing. Absent — never
false — on a turn that ran.
Typed as the companion.message envelope, so
reply.envelope.payload.attachments compiles (CR-754).
OptionalturnThe id this turn went out under (0.72.0): the turnId you passed, or
the one the SDK minted. Pass it back as turnId to retry the SAME turn
after an ambiguous failure — the server replays it instead of re-running.
OptionalusageTurn-level token totals for cost accounting (#2955), when the server
reported them: whole-turn sums plus reasoningTokens (a subset of
completion) and the served model when known. Absent on turns that made
no billed model call.
What
sendText(text, { awaitReply: true })resolves with: the completed turn's reply.textis the authoritative final assistant text (same value onMessage receives);envelopeis the fullcompanion.messageenvelope for hosts that want the id/ts.