Skip to content

requireContent

function requireContent<T>(
provider,
chunks,
opts?
): AsyncGenerator<T>;

Defined in: core/src/watchdog.ts:212

Reject a turn that completed without an answer.

A stream that ends with no text and no tool call is a failure wearing a success’s clothes: stop_reason: end_turn with zero content blocks, which the vendors emit under load, or a thinking block that ate the whole max_tokens. Nothing throws, so nothing retries. The caller simply shows a person an empty answer, and the only trace is a bill.

Reasoning is not an answer. It still streams the moment it arrives, so a reader can watch the model think, but a turn that only thought has said nothing. Counting it as content is how a review capped at 2,048 tokens on a high-effort model passed this guard 22 times in a row in production: every token went to thinking, the answer was an empty string, and the app’s JSON parse failed on it with nothing to say why.

Classified by what fixes it. A length finish is the caller’s own cap: invalid, so nothing retries it into the same cap and no backup model is cooled down for it. The fix is a larger maxTokens or a lower effort. Any other empty turn is overload, because that is both true and useful: it is theirs and temporary, so it is transient (the same model, retried, usually answers) and backup-eligible (a model that keeps doing it should be walked away from). Until something streams, the empty frames are held back, so the retry rule still holds: retry only while nothing was emitted.

Type Parameter
T extends ProviderChunk
Parameter Type
provider string
chunks AsyncIterable<T>
opts { afterToolResult?: boolean; }
opts.afterToolResult? boolean

AsyncGenerator<T>