Use Stop Sequences
What a Stop Sequence Is
A stop sequence is a piece of text that tells Claude to stop generating as soon as it produces that text. You pass one or more stop sequences with the stop_sequences parameter:
from anthropic import Anthropic
client = Anthropic()
message = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
stop_sequences=["END"],
messages=[{"role": "user", "content": "Write one sentence about Python, then write END, then a second sentence."}],
)
print(message.stop_reason) # stop_sequence
print(message.stop_sequence) # END
print("".join(b.text for b in message.content if b.type == "text"))
stop_sequence
END
Python is a versatile, readable programming language.
Generation stopped exactly where END would have appeared. The second sentence was never generated.
How Stop Sequences Behave
| Behavior | Detail |
|---|---|
| Exact text match | Generation stops when the generated text contains one of the sequences exactly. Matching is case-sensitive: END does not match end. |
| The match is not included | The stop sequence itself is not part of the returned text. |
stop_reason is "stop_sequence" | This is a normal, intentional ending (Lesson 20). |
stop_sequence tells you which one matched | When you pass several sequences, message.stop_sequence contains the one that ended generation. Otherwise it is None. |
| You only pay for what was generated | Stopping early reduces output tokens. |
If generation ends for any other reason, for example naturally (end_turn) or at the limit (max_tokens), stop_sequence is None, and the full text is returned as usual.
Why Use Stop Sequences
| Use case | How a stop sequence helps |
|---|---|
| Get only the first part of a structured answer | Stop at the marker that begins the next part |
| Prevent the model from writing the other side of a dialogue | Stop at the other speaker's label, such as "Candidate:" |
| End at a closing delimiter | Stop at a closing tag, such as "</answer>" |
| Limit the number of items | Stop when the next item number would begin |
| Save output tokens | Nothing after the stop point is generated |
Stop sequences work best when your prompt establishes a format with clear markers, so the stop point is predictable.
Example: Stop at a Closing Tag
When you ask for an answer inside tags, stopping at the closing tag removes anything Claude might add after it:
message = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
stop_sequences=["</answer>"],
messages=[{
"role": "user",
"content": "What is the capital of Japan? Write your answer inside <answer></answer> tags.",
}],
)
text = "".join(b.text for b in message.content if b.type == "text")
answer = text.split("<answer>", 1)[-1].strip()
print(answer) # Tokyo
Because the closing tag is the stop sequence, the text ends with <answer>Tokyo. Splitting on the opening tag and taking the last part extracts the answer.
Example: Limit the Number of Items
message = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
stop_sequences=["4."],
messages=[{"role": "user", "content": "List Python web frameworks as a numbered list, one per line."}],
)
print("".join(b.text for b in message.content if b.type == "text").strip())
1. Django
2. Flask
3. FastAPI
Generation stops when Claude starts the fourth item. However, "4." would also match text such as "Python 3.4." inside an item. Choose stop sequences that cannot appear in normal content, for example "\n4.", which only matches at the start of a line.
Tip: if you simply want three items, asking for exactly three items is often the better approach (Lesson 38). Use stop sequences when the format is fixed and you want a hard guarantee.
Example: Prevent the Model from Speaking for Others
In dialogue formats, a model can continue writing both sides of a conversation. A stop sequence ends its turn where the other speaker would begin:
system = (
"You are an interviewer for a junior Python developer role. Ask one question per turn. "
"Format each turn as 'Interviewer: <question>'."
)
message = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
system=system,
stop_sequences=["Candidate:"],
messages=[{"role": "user", "content": "Start the interview."}],
)
Even if the model began to write a candidate's answer, generation would stop at Candidate:, so your application controls who speaks next.
Choosing Good Stop Sequences
| Guideline | Why |
|---|---|
| Use markers that cannot appear in normal content | Prevents stopping too early inside the real answer |
| Establish the marker in the prompt or system prompt | Claude produces the marker reliably when the format is clear |
| Include line breaks when position matters | "\n4." only matches at the start of a line |
| Keep the list short | Each sequence is another way generation can end unexpectedly |
| Test with real inputs | Inputs that contain your markers can trigger early stops |
Stop Sequences vs. Other Tools
| Goal | Better tool |
|---|---|
| Shorter answers in general | Length instructions (Lesson 38) |
| Guaranteed machine-readable data | Structured outputs (Lesson 36) |
| A hard ceiling on output size | max_tokens (Lesson 13) |
| Stopping at a specific point in a known format | Stop sequences |
Practical Example: A Section Extractor
This example asks Claude to write a structured lesson outline, but uses stop sequences to generate only the section the user asked for. Every section after it is never generated, which saves output tokens.
"""section_extractor.py: generate only the requested section of a structured answer."""
from anthropic import Anthropic
from anthropic.types import Message
client = Anthropic()
SECTIONS = ["CONCEPT", "SYNTAX", "EXAMPLE", "MISTAKES"]
SYSTEM = """You write short programming lesson notes in exactly this format:
=== CONCEPT ===
(2-3 sentences)
=== SYNTAX ===
(a code block showing the syntax)
=== EXAMPLE ===
(a short example and its output)
=== MISTAKES ===
(2 common mistakes)
Always include all four sections in this order."""
def get_text(message: Message) -> str:
return "".join(block.text for block in message.content if block.type == "text")
def generate_until(topic: str, section: str) -> tuple[str, Message]:
"""Generate the notes up to and including `section`, and stop before the next one."""
index = SECTIONS.index(section)
following = SECTIONS[index + 1:]
stops = [f"=== {name} ===" for name in following]
request = {
"model": "claude-opus-5-5",
"max_tokens": 2048,
"system": SYSTEM,
"messages": [{"role": "user", "content": f"Topic: {topic}"}],
}
if stops:
request["stop_sequences"] = stops
message = client.messages.create(**request)
text = get_text(message)
part = text.split(f"=== {section} ===", 1)[-1].strip()
return part, message
if __name__ == "__main__":
part, message = generate_until("Python list comprehensions", "SYNTAX")
print(part)
print(f"\n[stop_reason={message.stop_reason}, stop_sequence={message.stop_sequence!r}, "
f"output_tokens={message.usage.output_tokens}]")
Example output:
```python
[expression for item in iterable if condition]
```
[stop_reason=stop_sequence, stop_sequence='=== EXAMPLE ===', output_tokens=95]
How It Works
- The system prompt defines a strict format with unique section markers (
=== NAME ===). These markers are unlikely to appear in normal content, which makes them safe stop sequences. generate_until()builds the stop sequences from the following sections. ForSYNTAX, the stops are theEXAMPLEandMISTAKESmarkers, so generation ends as soon as the next section begins.- Only add
stop_sequenceswhen there are any. For the last section,followingis empty, and the parameter is left out entirely (Lesson 22). text.split(f"=== {section} ===", 1)[-1]removes everything before the requested section, including the earlier sections that had to be generated first.- The usage line confirms the saving. Only the sections up to
SYNTAXwere generated, andstop_sequenceshows exactly which marker ended the response.
Note that sections before the requested one are still generated. Stop sequences save tokens only after the stop point. To generate a later section alone, ask for it directly in the prompt.
Common Mistakes
Stop Sequences That Appear in Normal Content
What happens: generation stops too early, for example "." stops after the first sentence, and "4." stops at "version 3.4."
Fix: use distinctive markers, and include line breaks or delimiters where position matters.
Expecting the Stop Sequence in the Output
What happens: code that looks for the closing marker in the text does not find it.
Fix: remember that the matched sequence is excluded. Use message.stop_sequence to see which one matched.
Not Establishing the Marker in the Prompt
What happens: Claude never produces the marker, so the stop sequence never triggers.
Fix: define the format and markers clearly in the prompt or system prompt.
Case or Spacing Mismatches
What happens: "END" does not match "End", and "=== EXAMPLE ===" does not match "===EXAMPLE===".
Fix: use exactly the marker text you specified in the prompt.
Using Stop Sequences Instead of Structured Outputs
What happens: parsing still depends on Claude following a text format.
Fix: use structured outputs when you need guaranteed machine-readable data.
Best Practices
- Define a clear format with unique markers, and use those markers as stop sequences.
- Check
stop_reasonandstop_sequenceto know why and where generation ended. - Remember that the match is excluded, and add it back if your format needs it.
- Use line breaks in stop sequences when matches should only occur at the start of a line.
- Combine stop sequences with a sensible
max_tokensas a safety net. - Test with inputs that might contain your markers.
Exercise
- Use
generate_until()for each of the four sections. How dooutput_tokenschange as you request later sections? - Rewrite the numbered-list example to use
"\n4."as the stop sequence, and test it with a prompt that might mention "Python 3.4". - Modify the interviewer example to run a 3-question interview in a loop, where your code supplies the candidate's answers as user messages.
- Explain why
generate_until()cannot avoid generating the sections before the requested one, and how you would change the prompt to generate only theMISTAKESsection.
Step 1: output tokens increase as later sections are requested, because every earlier section is generated first. Requesting MISTAKES produces roughly the full notes, while requesting CONCEPT stops after the first section.
Step 4: generation always proceeds from the beginning of the response, and stop sequences can only end it early. They cannot skip text that comes first. To generate only the mistakes, ask for them directly, for example: "List 2 common mistakes with Python list comprehensions, in the same style as the MISTAKES section." Use stop sequences to cut off what comes after the part you need.