Claude API Prompt Chaining Tutorial
What prompt chaining is and why you need it
Prompt chaining means breaking a complex task into a sequence of smaller Claude API calls, where the output of one call becomes the input for the next. Instead of asking Claude to "research, summarize, and write a report" in one giant prompt, you split it into three focused steps: extract facts, summarize them, then draft the report. Each step gets a smaller, clearer context window, which usually produces more accurate and more controllable output.
This matters because single mega-prompts tend to fail silently. Claude will do its best to satisfy a multi-part instruction, but accuracy drops as the task grows, and you lose the ability to inspect or correct intermediate results. Chaining gives you checkpoints: you can validate, cache, or retry each stage independently, log what happened at each step, and swap one stage's model or prompt without touching the rest of the pipeline.
Below is a practical tutorial for building a prompt chain against the Claude API, including code, error handling, and patterns that scale beyond toy examples.
When to chain instead of using one prompt
Chaining is worth the extra complexity when:
- The task has distinct phases — extraction, transformation, formatting, validation.
- Intermediate output needs structure — e.g. a JSON object that feeds the next step programmatically.
- You need different behavior per step — one step benefits from a low temperature for factual extraction, another from a higher temperature for creative writing.
- The input is too large for one pass — you summarize chunks first, then synthesize.
If the task is simple and single-shot, don't chain — it just adds latency and cost for no benefit.
Basic chain: extract, then transform
The simplest chain is two calls where step 2 depends on step 1's output. Here's a minimal example using plain HTTPS calls (swap in the Anthropic API or SubToAPI — the request shape is the same style of messages payload):
async function callClaude(messages) {
const res = await fetch("https://api.subtoapi.app/v1/messages", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SUBTOAPI_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "claude-sonnet-4",
max_tokens: 1024,
messages,
}),
});
const data = await res.json();
return data.content[0].text;
}
async function chain(rawText) {
// Step 1: extract structured facts
const facts = await callClaude([
{
role: "user",
content: `Extract all named entities and dates from this text as JSON:\n\n${rawText}`,
},
]);
// Step 2: use step 1's output as input
const summary = await callClaude([
{
role: "user",
content: `Using this extracted data, write a two-sentence summary:\n\n${facts}`,
},
]);
return summary;
}
Each step is a normal call to the messages endpoint — the chaining logic lives entirely in your application code, not in Claude itself. That's the key mental model: Claude has no memory between separate API calls unless you explicitly pass prior output back in.
Keeping state across a longer chain
For chains with three or more steps, pass a running object instead of raw strings so you can log and debug each stage:
async function runPipeline(input) {
const state = { input };
state.entities = await callClaude([
{ role: "user", content: `List key entities in: ${state.input}` },
]);
state.draft = await callClaude([
{ role: "user", content: `Write a draft report using these entities: ${state.entities}` },
]);
state.final = await callClaude([
{ role: "user", content: `Edit this draft for clarity and tone: ${state.draft}` },
]);
return state;
}
Returning the full state object, not just the final result, makes debugging much easier — if step 2 produces garbage, you can see exactly what step 1 handed it.
Validating output between steps
Chains break when a step returns something the next step can't parse. Always validate structured output before passing it on:
function parseOrRetry(raw) {
try {
return JSON.parse(raw);
} catch {
throw new Error("Step output was not valid JSON — add stricter formatting instructions");
}
}
If you're extracting structured data between steps, it's often more reliable to use tool use for that step instead of asking Claude to format JSON in plain text. A tool call forces a schema, which removes an entire class of parsing failures from your chain.
Streaming inside a chain
Streaming is useful on the final, user-facing step of a chain, where you want tokens to appear as they're generated, but it adds complexity on intermediate steps where you just need the full text to pass forward. A common pattern:
- Intermediate steps: non-streaming calls, since you need the complete output before moving on.
- Final step: streamed response to the client, so the user sees output immediately instead of waiting for the whole pipeline to finish.
const finalRes = await fetch("https://api.subtoapi.app/v1/messages", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SUBTOAPI_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "claude-sonnet-4",
max_tokens: 1024,
stream: true,
messages: [{ role: "user", content: finalPrompt }],
}),
});
Handling failures mid-chain
A chain is only as reliable as its weakest step. Build in:
- Retries with backoff on transient API errors (rate limits, timeouts), not on logic errors.
- Timeouts per step, so one slow call doesn't hang the whole pipeline.
- Short-circuit on empty or malformed output rather than feeding garbage into the next prompt.
- Logging per step — model, prompt, token usage, latency — so you can tell which stage is costing the most or failing the most.
If you're running chains in production, having per-key usage metadata matters here: when a chain fails or gets expensive, you want to know which step and which API key caused it. SubToAPI's dashboard exposes usage per key for exactly this kind of debugging, which is harder to get from raw Anthropic billing alone. See pricing for plan details, or start with a free trial at signup.
A note on cost and latency
Every step in a chain is a full round trip — API latency, token cost, and failure surface all multiply by the number of steps. Before adding a step, ask whether it genuinely improves accuracy or is just splitting work that one well-structured prompt could handle. A three-step chain that's twice as accurate is worth the extra 2x latency; a five-step chain that's marginally better than a two-step one usually isn't.
Questions
Does Claude remember previous steps automatically? No. Each API call is stateless unless you include prior messages or output in the new request. Chaining is entirely managed in your application code.
Should every step use the same model? Not necessarily. Cheaper or faster models can handle simple extraction steps, while a stronger model handles the final synthesis or writing step — this keeps chain cost down without sacrificing final quality.
How many steps is too many for a prompt chain? There's no fixed limit, but beyond 4–5 steps latency and cost compound quickly. If you're past that, consider whether a single well-structured prompt with tool use could replace several steps.