Skip to main content

Lab 4 answers

Q1. What does display control?

Visibility only. Thinking happens and is billed identically under every setting; the raw chain of thought is never exposed on any model. "summarized" returns a readable summary in the thinking blocks; "omitted" — the default on this model family — leaves the text empty.

The bad first-run UX: with the default, a streaming client sees thinking events with no content, then nothing at all for however long reasoning takes, then a burst of text. To a user that is indistinguishable from a hung request. Teams commonly "fix" this by disabling thinking, which costs them quality; the actual fix is one parameter.

Q2. Why finalMessage() over a hand-rolled promise?

finalMessage() handles completion, error, and abort internally and resolves or rejects appropriately in all three. A hand-rolled new Promise(res => stream.on("message", res)) handles only the happy path: on an upstream error or an abort, the message event never fires, the promise never settles, and the request hangs until something else times it out. You would then need to wire .on("error") and .on("abort") yourself and get the race between them right.

General principle: don't reimplement SDK helpers. They exist because the edge cases are not obvious.

Q3. Which header, and what else buffers?

X-Accel-Buffering: no is the one that stops nginx (and several other proxies that honor it) from buffering the response body.

Cache-Control: no-transform is there for a different reason: it tells intermediaries not to modify the payload — some CDNs and mobile carrier proxies compress or rewrite bodies, which breaks SSE framing.

Other layers that can buffer: CDNs (Cloudflare and friends buffer non-streaming content types), API gateways and load balancers, corporate HTTP proxies, and — on the client — curl without -N and any fetch wrapper that calls res.text() instead of reading the stream.

Q4. The rule for a client integrator.

Once the response is a stream, a 200 status means "generation started," not "generation succeeded" — you must handle an in-band error event.

If a client only checks res.ok, an upstream failure halfway through delivers a partial reply with no error surfaced. In this domain that means a half-written message to a customer, presented to the agent as complete. This is the single most commonly missed piece of streaming integration.

Q5. What continues without the abort?

The upstream request to the Anthropic API keeps generating to completion. You are billed for every output token, and your process holds the connection and its memory the whole time. Under load — a UI that fires a request per keystroke, or users who navigate away from slow responses — this becomes a large and completely invisible line item, because nothing errors and nothing logs.