Appendix B · section 6 of 32
ask/setup.ts
From Talking to a Model.
import type Anthropic from "@anthropic-ai/sdk";
// The one place the model identifiers live. When Anthropic releases a newer
// model, these are the only lines in the whole project that change.
export const ANSWER_MODEL = "claude-opus-5-5";
// The small, fast model the pipeline's side jobs run on: rewording a
// question, ranking a shortlist. Each is a short reply nobody reads, and the
// price is a fortieth of the answering model's.
export const SMALL_MODEL = "claude-haiku-5-5";
// How long a side job may take. The SDK's own default is ten minutes with two
// retries, and a learner's question would wait that long on one hung call.
export const SIDE_JOB_TIMEOUT_MS = 5000;
// Every script from here on calls this before it does anything else.
export function requireApiKey(): void {
if (!process.env.ANTHROPIC_API_KEY) {
console.error(
"ANTHROPIC_API_KEY is not set. Export it and run this again.",
);
process.exit(1);
}
}
// The text of a reply, from whichever blocks carry text. A response can
// carry a thinking block ahead of its text, so `content[0]` is not the answer.
export function textOf(response: Anthropic.Message): string {
return response.content
.filter((block): block is Anthropic.TextBlock => block.type === "text")
.map((block) => block.text)
.join("");
}