## Consider all effort levels ## Ask for user-facing progress updates ## Batch independent tool calls in agent loops ## Keep the conversation history append-only ## Writing density ## Formatting in chat ## Quoting retrieved sources ## Finish the whole task ## Tell the model what to preserve in compaction summaries ## Keep changes and tests to what the task asks for ## Search triggering at low effort ## Reduce safeguard false positives ## Prefer targeted edits over whole-file rewrites ## Leave room for long outputs at xhigh and max effort ## Let the lead agent keep working while subagents run ## Give vision work tools to crop and zoom
The whole hunk
890 lines, new pageA whole new page. There's nothing to diff it against, so here is what it says.
---
title: Prompting Claude Fable 5.1
url: https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1
description: Behavioral differences and prompting patterns for Claude Fable 5.1 and Claude Mythos 5.1, covering effort, progress updates, tool-call batching, conversation history, writing style, formatting, task completion, compaction summaries, scope and test coverage, search triggering, safeguard false positives, file edits, long outputs, subagents, and vision.
---
For the model's capabilities, API changes, pricing, and availability, see [What's new in Claude Fable 5.1](https://platform.claude.com/docs/en/models/fable-5-1/whats-new-fable-5-1). For techniques that apply across Claude models, see [Prompting best practices](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices).
Your existing Claude Fable 5 prompts should perform well on Claude Fable 5.1 without changes, but a handful of behavioral differences are worth knowing about. Start with the section that matches what you observe:
* Unsure which effort level to run, or latency and cost are higher than the task warrants: [Consider all effort levels](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1#consider-all-effort-levels)
* Little or no text between tool calls: [Ask for user-facing progress updates](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1#ask-for-user-facing-progress-updates)
* One tool call per turn in agent loops: [Batch independent tool calls in agent loops](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1#batch-independent-tool-calls-in-agent-loops)
* Requests fail with `bound to a different conversation`, or your harness edits earlier turns between requests: [Keep the conversation history append-only](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1#keep-the-conversation-history-append-only)
* Prose runs long and dense: [Writing density](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1#writing-density)
* Chat replies carry less structure than the content needs: [Formatting in chat](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1#formatting-in-chat)
* Summaries reproduce source wording without marking it as a quotation: [Quoting retrieved sources](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1#quoting-retrieved-sources)
* Turn ends before the work is done, or the model asks permission for work you already requested: [Finish the whole task](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1#finish-the-whole-task)
* Client-side compaction summaries drop constraints, decisions, or exact details: [Tell the model what to preserve in compaction summaries](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1#tell-the-model-what-to-preserve-in-compaction-summaries)
* Unrequested fixes or extensions, or more committed test files than the task called for: [Keep changes and tests to what the task asks for](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1#keep-changes-and-tests-to-what-the-task-asks-for)
* Answers from memory instead of searching at low effort: [Search triggering at low effort](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1#search-triggering-at-low-effort)
* Benign coding requests return `stop_reason: "refusal"`: [Reduce safeguard false positives](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1#reduce-safeguard-false-positives)
* Whole files rewritten for small changes: [Prefer targeted edits over whole-file rewrites](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1#prefer-targeted-edits-over-whole-file-rewrites)
* Long deliverables at `xhigh` or `max` effort take a long time or hit `max_tokens`: [Leave room for long outputs at xhigh and max effort](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1#leave-room-for-long-outputs-at-xhigh-and-max-effort)
* Lead agent idles while subagents run: [Let the lead agent keep working while subagents run](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1#let-the-lead-agent-keep-working-while-subagents-run)
* Answers about charts and dense images miss detail: [Give vision work tools to crop and zoom](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1#give-vision-work-tools-to-crop-and-zoom)
<Note>
Claude Fable 5.1 runs safety classifiers and can return `stop_reason: "refusal"`. See [Refusals, fallback, and billing](https://platform.claude.com/docs/en/models/fable-5-1/whats-new-fable-5-1#refusals-fallback-and-billing) and [Reduce safeguard false positives](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1#reduce-safeguard-false-positives).
</Note>
## Consider all effort levels
Start at the default [effort](https://platform.claude.com/docs/en/build-with-claude/effort) level, `high`, then test the other levels (`low`, `medium`, `xhigh`, and `max`) against your own evals. Effort is the primary control for trading off intelligence, latency, and cost on Claude Fable 5.1. Re-run the sweep even if you already ran one on Claude Fable 5: effort level names don't correspond to the same amount of thinking across models.
Claude Fable 5.1's capability gains over Claude Fable 5 show up across effort levels and are largest at the higher settings. At `medium`, results roughly match Claude Fable 5 at lower cost, so step down to `medium` or `low` where your evals show quality holds. At `low`, Claude Fable 5.1 is often competitive with Claude Opus and Claude Sonnet models on cost per task while scoring higher, so include it in the comparison wherever you'd otherwise run a smaller model at a higher effort level.
Two effort-specific behaviors have their own sections: at `low`, Claude Fable 5.1 calls search and retrieval tools less often (see [Search triggering at low effort](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1#search-triggering-at-low-effort)), and at `xhigh` and `max` it can think for longer before writing a long deliverable (see [Leave room for long outputs at xhigh and max effort](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1#leave-room-for-long-outputs-at-xhigh-and-max-effort)).
## Ask for user-facing progress updates
Claude Fable 5.1's default behavior is to write fewer user-facing updates during long tool-calling turns than Claude Fable 5 does. This becomes more pronounced at higher effort and in longer tool chains. Users see the agent go quiet for minutes at a time, or a final message that covers only the last step rather than the whole task.
First, check that your client receives progress updates at all. The model's short notes between tool calls, what it just found and what it's doing next, come back as [progress-update `thinking` blocks](https://platform.claude.com/docs/en/build-with-claude/thinking#progress-updates), and those blocks are empty under the default `thinking.display` of `"omitted"`. Set `display: "updates"` (beta, `thinking-display-updates-2026-08-18` header) and render each non-empty `thinking` block as a status line, or set `"summarized"` to receive them along with summarized reasoning. If you aren't requesting them, the model's updates may simply not be reaching your users.
Second, audit your prompt for instructions that suppress narration. Some earlier models were eager to give updates while working, which led to system prompt lines such as "hold all findings for the final response." Remove lines like that before adding anything.
If you still want more updates, for example when pair programming or in other human-in-the-loop work, add a short system prompt line that says when you want user-facing text from the model and what each update should contain:
```text wrap
Before you start, say in a line what you're about to do; brief updates while you work help the user follow along. Close with a short recap that stands on its own — what you found, what you did, and what's next — so a reader who only sees the last message has the full picture.
```
If your product collapses or hides tool output, tell the model. Otherwise it may run commands to "show" the user output that your UI never displays. Deliver the note in a [turn-scoped system message](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages) (`clear_at: "next_user_message"`, beta):
```text wrap
Only you see that command's output — the user's terminal shows at most a few lines of it. If the user needs to read any of it, put it in your reply.
```
## Batch independent tool calls in agent loops
Claude Fable 5.1 usually issues parallel tool calls as expected: when a request names several things to fetch, it issues those calls in parallel. The exception is coding and computer-use loops where the next independent calls are implied by the task rather than explicitly requested (custom coding agents, bash-and-editor harnesses, computer use): there it may issue them one per turn instead. This doesn't affect answer quality, but each extra turn costs tokens, a round trip, and wall-clock time. A one-sentence nudge at the end of the current request addresses it:
```text wrap
First privately list what you need next; then request every item that doesn't depend on another's result in this one response.
```
Each time you send tool results back, append it after that user message as a [turn-scoped system message](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages): a `role: "system"` entry in `messages` with `clear_at: "next_user_message"`. Once a later user message exists, the API clears the earlier copies, so the model reads only the newest one. Turn-scoped system messages are in beta and require the [beta header](https://platform.claude.com/docs/en/api/beta-headers) `mid-conversation-system-clear-at-2026-08-21`. Without the beta, place the sentence in a text block after the `tool_result` blocks in the same user message instead.
Append a fresh copy each turn and leave the earlier copies where they are, byte-for-byte. They stay in the array, but once cleared the model doesn't see them and they cost no input tokens. Deleting or rewriting them is an edit to earlier turns: it restarts the [prompt cache](https://platform.claude.com/docs/en/build-with-claude/prompt-caching) from that point and invalidates the thinking blocks that came after them (see [Keep the conversation history append-only](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1#keep-the-conversation-history-append-only)).
The following loop shows this placement. Each assistant turn goes back exactly as returned, each user turn carries only the tool results, and a fresh turn-scoped copy of the nudge follows it.
<CodeGroup exclude="shell">
```python Python
import anthropic
from anthropic.types.beta import (
BetaMessageParam,
BetaToolParam,
BetaToolResultBlockParam,
)
client = anthropic.Anthropic()
BATCH_NUDGE = (
"First privately list what you need next; then request every item "
"that doesn't depend on another's result in this one response."
)
# In-memory files stand in for a working directory so the sample runs anywhere.
FILES = {
"pyproject.toml": """\
[project]
name = "demo"
version = "0.1.0"
description = "Demo project for the batching example"
""",
"README.md": """\
# demo
A small demo project. Run `demo --help` for usage.
""",
}
tools: list[BetaToolParam] = [
{
"name": "read_file",
"description": "Read a UTF-8 text file from the working directory.",
"input_schema": {
"type": "object",
"properties": {"path": {"type": "string"}},
"required": ["path"],
},
}
]
messages: list[BetaMessageParam] = [
{"role": "user", "content": "Summarize pyproject.toml and README.md."}
]
while True:
response = client.beta.messages.create(
model="claude-fable-5-1",
max_tokens=16000,
betas=["mid-conversation-system-clear-at-2026-08-21"],
tools=tools,
messages=messages,
)
# Append the assistant turn exactly as returned, thinking blocks included.
messages.append({"role": "assistant", "content": response.content})
if response.stop_reason != "tool_use":
break
tool_results: list[BetaToolResultBlockParam] = []
for block in response.content:
if block.type == "tool_use":
path = str(block.input["path"])
if path in FILES:
tool_results.append(
{
"type": "tool_result",
"tool_use_id": block.id,
"content": FILES[path],
}
)
else:
tool_results.append(
{
"type": "tool_result",
"tool_use_id": block.id,
"content": f"File not found: {path}",
"is_error": True,
}
)
# Send the tool results as the user turn, then a fresh copy of the nudge as a
# turn-scoped system message. Leave earlier copies in place: the API clears them,
# so the model sees only the newest one.
messages.append({"role": "user", "content": tool_results})
messages.append(
{"role": "system", "content": BATCH_NUDGE, "clear_at": "next_user_message"}
)
print(next((block.text for block in response.content if block.type == "text"), ""))
```
```typescript TypeScript
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
const BATCH_NUDGE =
"First privately list what you need next; then request every item " +
"that doesn't depend on another's result in this one response.";
// In-memory files stand in for a working directory so the sample runs anywhere.
const FILES = new Map<string, string>([
[
"pyproject.toml",
`[project]
name = "demo"
version = "0.1.0"
description = "Demo project for the batching example"
`,
],
[
"README.md",
`# demo
A small demo project. Run \`demo --help\` for usage.
`,
],
]);
const tools: Anthropic.Beta.Messages.BetaTool[] = [
{
name: "read_file",
description: "Read a UTF-8 text file from the working directory.",
input_schema: {
type: "object",
properties: { path: { type: "string" } },
required: ["path"],
},
},
];
const messages: Anthropic.Beta.Messages.BetaMessageParam[] = [
{ role: "user", content: "Summarize pyproject.toml and README.md." },
];
let response: Anthropic.Beta.Messages.BetaMessage;
while (true) {
response = await client.beta.messages.create({
model: "claude-fable-5-1",
max_tokens: 16000,
betas: ["mid-conversation-system-clear-at-2026-08-21"],
tools,
messages,
});
// Append the assistant turn exactly as returned, thinking blocks included.
messages.push({ role: "assistant", content: response.content });
if (response.stop_reason !== "tool_use") {
break;
}
const toolResults: Anthropic.Beta.Messages.BetaToolResultBlockParam[] = [];
for (const block of response.content) {
if (block.type !== "tool_use") {
continue;
}
const { input } = block;
const path =
typeof input === "object" &&
input !== null &&
"path" in input &&
typeof input.path === "string"
? input.path
: "";
const text = FILES.get(path);
if (text === undefined) {
toolResults.push({
type: "tool_result",
tool_use_id: block.id,
content: `File not found: ${path}`,
is_error: true,
});
continue;
}
toolResults.push({
type: "tool_result",
tool_use_id: block.id,
content: text,
});
}
// Send the tool results as the user turn, then a fresh copy of the nudge as a
// turn-scoped system message. Leave earlier copies in place: the API clears them,
// so the model sees only the newest one.
messages.push({ role: "user", content: toolResults });
messages.push({
role: "system",
content: BATCH_NUDGE,
clear_at: "next_user_message",
});
}
const finalText = response.content.find((block) => block.type === "text");
console.log(finalText?.text);
```
```csharp C#
using System.Text.Json;
using Anthropic;
using Anthropic.Models.Beta.Messages;
AnthropicClient client = new();
const string BatchNudge =
"First privately list what you need next; then request every item "
+ "that doesn't depend on another's result in this one response.";
// In-memory files stand in for a working directory so the sample runs anywhere.
Dictionary<string, string> files = new()
{
["pyproject.toml"] = """
[project]
name = "demo"
version = "0.1.0"
description = "Demo project for the batching example"
""",
["README.md"] = """
# demo
A small demo project. Run `demo --help` for usage.
""",
};
List<BetaToolUnion> tools =
[
new BetaTool
{
Name = "read_file",
Description = "Read a UTF-8 text file from the working directory.",
InputSchema = new InputSchema
{
Properties = new Dictionary<string, JsonElement>
{
["path"] = JsonSerializer.SerializeToElement(new { type = "string" }),
},
Required = ["path"],
Cut at 300 lines. The page has the rest.