Fable 5 Prompt Guide

By Chris Boyd ·

Now that Fable 5 is finally available to the public and here to stay, the first thing worth saying is the least intuitive: most of the prompt you already have is working against you.

If you are migrating from Opus 4.8 or an earlier model, your prompts are probably tuned in the wrong direction. They enumerate steps. They spell out procedure. They wrap the model in guardrails that made sense when the model needed hand-holding to stay on task. Fable 5 does not need most of that, and worse - it is measurably better without it. The prescriptive scaffolding that rescued output quality on older models now suppresses it.

The through-line for this entire guide: with Fable 5, you say less, not more. State the goal. State the constraints. State the boundaries. Then stop enumerating the steps and let it work. This post covers the API surface that changed, the prompt patterns that actually move the needle, and a before/after you can lift into your own code today.

The API surface changed. Fail closed on the differences.

Before any prompting philosophy, get the parameters right, because several of the knobs you reach for by reflex now return a 400.

  • Model ID is claude-fable-5. 1M token context, 128K max output.
  • Thinking is always on. There is no thinking parameter to set. Omit it. An explicit {"type": "disabled"} returns a 400, and budget_tokens is gone - also a 400. You do not budget thinking anymore; the model decides.
  • Depth is controlled by output_config.effort: low, medium, high, xhigh, max.
  • temperature, top_p, top_k are removed. They 400. You steer with prompting now, not sampling knobs.
  • Assistant prefill is not supported. If you were prefilling to force a JSON shape or a leading token, use structured outputs via output_config.format instead.
  • The raw chain of thought is never returned. display: "summarized" gives you a readable summary; the default omits it and you get empty thinking text.

Here is the shape of a correct request:

resp = client.messages.create(
    model="claude-fable-5",
    max_tokens=128000,
    output_config={
        "effort": "medium",          # sweep this; do not pin to max
        "display": "summarized",     # readable thinking summary, or omit for none
        # "format": {...}            # structured outputs - replaces prefill
    },
    # NO thinking param - always on
    # NO temperature / top_p / top_k - all 400
    fallbacks=[{"model": "claude-opus-4-8"}],  # reroute refusals; see below
    system=SYSTEM,
    messages=messages,
)

The migration reflex is to slap effort: "max" on everything and move on. Resist it. The docs are explicit that lower effort still often beats older models running at their ceiling, and higher effort is where turns stretch from seconds into many minutes. Sweep effort against your own eval before you pin it. Most production traffic does not need max, and the ones that do will tell you in the eval numbers, not in your gut.

Handle refusal before you read content

Fable 5 runs safety classifiers on offensive cybersecurity techniques, biology and life sciences content, and - worth flagging for prompt authors - extraction of its own summarized thinking. When one fires, the API returns stop_reason: "refusal". Benign work in those domains can trip it too, so this is not a rare edge case you can defer.

The failure mode that bites people: they parse content first and crash or emit garbage because they never checked why the turn stopped. Check stop_reason before you read content. The fix for keeping pipelines alive is the fallbacks parameter, which reroutes a declined request to Opus 4.8 server-side.

if resp.stop_reason == "refusal":
    # do NOT read resp.content - route to fallback / log / surface to user
    handle_refused(resp)
else:
    text = resp.content[0].text

On consumer surfaces the fallback ships built in. On the API it is opt-in - a declined request just stops unless you passed fallbacks. Set it and forget it beats discovering it in an incident.

Turns are long. This is a systems problem, not a prompt problem.

A single hard request can run many minutes at higher effort, and autonomous runs can extend for hours. This is one of the largest shifts teams hit, and it lands in your infrastructure, not your prompt.

Synchronous request/response blocking for minutes will time out at the load balancer, the client, or both. Before you migrate, revisit three things: client timeouts (raise them, and stop assuming a fast p95), streaming (stream so the connection stays warm and the user sees motion), and progress UX (design for a task that is genuinely still working at minute six, not one that has hung). For anything long-horizon, restructure the harness to poll asynchronously or fire on a webhook rather than holding a blocking call open. If your architecture assumes a model reply is a fast function call, that assumption is now a bug.

The prompt patterns that actually move the needle

Everything above is table stakes. This is where output quality is won or lost. Each pattern below comes with the reason it works, because "do this" without the mechanism is how you get cargo-cult prompts that stop working the moment the task shifts.

1. Make it verify progress against real tool results, not assumed ones

On long runs, models can report a step as done based on what they intended to happen rather than what the tool actually returned. Fable 5's own testing found that instructing it to ground progress claims in real tool output nearly eliminated false status reports. The mechanism: a status claim asserted from intention is a guess; a status claim checked against a returned exit code or a re-read file is a verification. You are forcing the second.

Put this in the system prompt:

Before reporting any step as complete, confirm it against the actual
tool result - the command's exit code, the file's contents on re-read,
the test runner's output. Do not report success from expected behavior.
If you cannot verify a step, say so and say why.

This is the single highest-leverage line for anyone running Fable 5 as an agent. False "done" reports are what turn a long autonomous run into a long autonomous run you cannot trust.

2. Let it delegate to sub-agents - don't suppress delegation

Fable 5 is significantly more dependable at dispatching and sustaining parallel sub-agents, and at managing ongoing communication with long-running ones. Older prompts often contain the opposite instruction - "do this yourself," "do not spawn additional agents" - written to stop weaker models from fanning out and losing the thread. On Fable 5 that instruction leaves capability on the table.

If your harness exposes a sub-agent or task-dispatch tool, tell it delegation is available and let it decide the fan-out, asynchronously:

You can dispatch parallel sub-agents for independent subtasks. Delegate
work that can run concurrently, keep track of what each one is doing,
and reconcile their results before you report back. You do not need to
do every step in a single thread.

The mechanism: delegation is a planning decision, and Fable 5 is now good enough at planning that constraining the plan hurts more than it protects. Remove the old suppression and give it the tool.

3. Give it a place to write things down

Long runs blow past what fits comfortably in working context. A scratchpad - a file, a memory tool, a notes buffer it can append to and re-read - lets the model externalize state instead of trying to hold the entire task in context and drifting as it fills up. The mechanism is straightforward: durable notes it can re-read are more reliable than context it has to keep resident, and re-reading its own notes is a form of self-verification.

You have a working file at ./NOTES.md. Use it to record decisions,
open questions, and what you have verified. Re-read it before major
steps. Treat it as your source of truth over your own recollection.

4. State the boundaries - what NOT to do

Because Fable 5 follows instructions tightly and stays in scope, boundaries are cheap and effective. If there are files it must not touch, systems it must not call, or classes of change it must not make, say so directly. This is not the same as enumerating steps - you are not telling it how to work, you are telling it where the walls are and then letting it move freely inside them.

Constraints:
- Do not modify anything under /infra or /deploy.
- Do not change public API signatures.
- Do not add new third-party dependencies without flagging first.
Within those limits, use your judgment on approach.

The mechanism: a well-drawn boundary replaces a hundred lines of procedural "do this, then this" and gives the model room to find a better path than the one you would have scripted.

5. Give the reason, not just the request

State why you want something and Fable 5 makes better calls at every fork the instruction did not anticipate. "Return JSON" tells it the format. "Return JSON because it feeds a strict downstream parser that rejects trailing prose" tells it the format and that a chatty preamble will break the pipeline - so it suppresses the preamble you never explicitly forbade. The mechanism: the reason lets the model generalize your intent to cases you did not enumerate, which is exactly what you want from a model that is now good at navigating ambiguity.

Before / after: de-prescribing a prompt

Here is a real migration. The "before" is a system prompt written for an older model - heavy on procedure, defensive, step-by-step. The "after" is the same job de-prescribed for Fable 5.

Before (tuned for an older model):

You are a code migration assistant. Follow these steps exactly and in
order. Do not skip any step.
1. Open each file in the src/ directory one at a time.
2. For each file, find all uses of the old logging API.
3. Replace each one with the new logging API, one call at a time.
4. Do not attempt more than one file at once.
5. Do not use any other tools or agents.
6. After each file, print the file name and the number of changes.
7. When done, print "MIGRATION COMPLETE".
Be careful and go slowly.

After (de-prescribed for Fable 5):

Migrate the codebase from the old logging API to the new one. The goal
is that no source file imports or calls the deprecated logger, and the
test suite still passes.

Why: we are removing the old logging dependency next sprint, so any
remaining call site becomes a build break.

Constraints:
- Do not change log message contents or levels.
- Do not touch anything outside src/.

Verify each file against the test runner before you consider it done,
and confirm the deprecated import is actually gone by re-reading the
file. You may work files in parallel. Keep a running list of what
you have changed and what still fails, and report that list at the end.

What changed and why: the step list is gone because enumerating steps caps the model at your plan. The single-file, no-parallelism, no-tools clamps are gone because they suppress exactly the delegation and concurrency Fable 5 is good at. In their place: the goal, the reason (which lets it handle call sites the steps never mentioned), the boundaries, and grounded verification. Shorter prompt, better result. That is the whole migration in miniature.

Lines worth quoting

  • With Fable 5 you say less, not more: state the goal and the constraints, then stop enumerating the steps.
  • Prompts tuned for older models are usually too prescriptive, and the prescription now costs us output quality.
  • Don't pin effort to max by reflex - lower effort often beats last generation's ceiling, and we should sweep it against our own eval.
  • Check stop_reason: "refusal" before you read content, and wire the Opus 4.8 fallback so a declined request never breaks the pipeline.
  • Fable 5 turns run for minutes to hours - that's a timeout, streaming, and progress-UX decision, not a prompt tweak.
  • Tell it to verify progress against real tool results, not assumed ones - Anthropic's own testing found that nearly eliminated false "done" reports.

This post draws on Anthropic's official Fable 5 prompting documentation. For authoritative, current parameters and behavior, treat platform.claude.com as the source of truth.