Careeroza
Max Tokens and Stop Sequences
Two Ways Generation Ends Early
- max_tokens: a hard limit on how many tokens the model may write. It is required in the Claude API. If the limit is hit,
stop_reasonis"max_tokens"and the text is cut off mid-sentence. - stop sequences: strings that end generation as soon as they appear (for example
"\n\nCustomer:").stop_reasonbecomes"stop_sequence". - Normal finish:
stop_reasonis"end_turn".
Simulated Generation
Example
A stand-in model "writes" a fixed reply token by token; the loop shows how each limit stops it:
reply_tokens = ["Your", " order", " ships", " today", ".", "\n", "Customer", ":", " thanks"]
def generate(max_tokens, stop_sequences=()):
text = ""
for i, tok in enumerate(reply_tokens):
if i == max_tokens:
return text, "max_tokens"
text += tok
for s in stop_sequences:
if s in text:
return text[: text.index(s)], "stop_sequence"
return text, "end_turn"
for args in [(3, ()), (50, ("\nCustomer:",)), (50, ())]:
text, reason = generate(*args)
print(f"max_tokens={args[0]:<3} stop={args[1]!r:18} -> {text!r} ({reason})")Output
max_tokens=3 stop=() -> 'Your order ships' (max_tokens)
max_tokens=50 stop=('\nCustomer:',) -> 'Your order ships today.' (stop_sequence)
max_tokens=50 stop=() -> 'Your order ships today.\nCustomer: thanks' (end_turn)In the Claude API
response = client.messages.create(
model="claude-sonnet-5-5",
max_tokens=300,
stop_sequences=["</answer>"],
messages=[{"role": "user", "content": "Answer inside <answer> tags: what is ShopEase's return window?"}],
)
print(response.stop_reason, response.stop_sequence)
if response.stop_reason == "max_tokens":
print("Reply was cut off - raise max_tokens or ask for a shorter answer")Run it
python stop_demo.pyExample output
stop_sequence </answer>