Skip to main content
A user can stop the assistant while it works. Stop ends the turn cleanly. Nothing new starts. A write that already started finishes and its result is kept. A model reply or a read in progress is cut short: text already streamed is kept, and the step gets a result that says it was stopped. The conversation stays ready for the next message.
Stop is served only when turn control is on for your environment. You can tell it is on in two ways: the conversation detail response carries the turn key, or the conversation frame of a turn stream carries "turn_control": true. Until then the Stop and turn routes answer 404 not_found. Show Stop only after you have seen one of the two, and never call these routes before that.

Terms

  • A turn is one user message and the work the assistant does for it. A turn can span several requests.
  • A segment is one request’s part of a turn: the stream you read until its turn_end frame.
  • A turn is at rest when its status is completed, stopped or failed. Nothing more happens to it.
  • A turn is stopping when Stop was pressed and the turn has not come to rest yet, for example because a write that already started is finishing. The platform does not store this status. It reads it from the stop request and the turn’s state.

Show Stop

Show one button. It replaces Send while the assistant works, in the same place and at the same size.
  • Show Stop from the moment you send a message until the turn is at rest.
  • Keep showing it while the turn waits for a client tool result or for an approval. Stop works in every status that is not at rest.
  • If the user presses Stop before you know the turn id, keep the press. Send Stop as soon as the conversation frame gives you turn_id.
  • Show Send again once the turn is at rest.

Call Stop

POST /api/v1/conversation-instances/{instance_slug}/conversations/{conversation_id}/turns/{turn_id}/stop Credential: an organization API key, or a scoped key with conversations:use. The body carries the same end_user as the turn.
Stop answers within two seconds with the turn:
  • On a turn that was not at rest, status is stopped when Stop ended it, or stopping when a write that already started still has to finish. A turn already at rest is returned unchanged, whatever its status (completed, stopped or failed).
  • Stop is safe to repeat. On a turn at rest it changes nothing and returns the turn as it is.
  • Stop works on an archived conversation.
  • A turn that started before turn control was on has no record. Stop on it answers 404 turn_not_found.

While the turn is stopping

  • Change the button to a disabled “Stopping” state. Do not show Send yet.
  • Keep reading the stream if you have one open. It ends with turn_end and stop_reason: "stopped".
  • Without an open stream, read the turn every two seconds until it is at rest: GET /api/v1/conversation-instances/{instance_slug}/conversations/{conversation_id}/turns/{turn_id}?end_user=... It answers {"turn": {...}} in the same shape as Stop. The read changes nothing.
  • If the turn reads stopping for more than three seconds, call Stop again. A repeat ends the turn when nothing else holds it, for example after a lost signal. A write that is still running keeps the turn stopping until it finishes, so keep reading until the turn is at rest before you show Send.

Read a stopped turn

The turn object

The transcript

  • Text the assistant streamed before the stop is kept as the reply’s text, when it passes the instance’s output checks. Show it with a short “Stopped” line under it.
  • Every step that started gets a stored result. Show it as a stopped step. The result says what is known:
A server step that finished before the stop keeps its real result.
  • The model sees the same stored results on the next message, so it can tell the user what is known about each stopped step.

After a reload

Conversation detail carries two keys while turn control is on:
  • turn is the latest turn of the version the conversation serves, or null when that turn has no record. Use it to decide whether to show Stop or Send.
  • turns lists every turn with a message in the returned transcript window that did not end normally, oldest first: [{"id": "...", "status": "stopped", "stop_reason": "stopped"}]. It is an empty list when there is none. Each message carries its turn_id, so mark the last message of each listed turn as stopped.
The version switch answer carries both keys too.

What Stop does not do

  • It does not undo a step that ran.
  • It never cuts a write. A write that already started finishes, and its result is kept.
  • It cancels no run. A run the assistant submitted keeps going and its own status shows that. Runs your own tools started are yours to cancel. See Client tools.

Edit a message while a turn runs

Send the edit with stop_active_turn: true:
  • The platform stops the running turn, then starts the reply to the edited message as a new version, in the same request.
  • The old version keeps its stopped work. The user can switch back to it.
  • Without stop_active_turn, an edit while a turn runs answers 409 as it always has.
  • If the running turn does not come to rest within 10 seconds, the request answers 409 turn_in_progress. The stop stays recorded. Send the edit again once the turn is at rest.
  • Disable Save while the request is in flight. A repeat after a success is a new edit.
  • A version switch while the latest turn is not at rest answers 409 turn_active. Disable the version switcher while the assistant works.

Late results

Your app may finish a step after the turn stopped. Post its result as usual, with tool_results on the turns route.
  • The platform keeps it. The result replaces the step’s stored placeholder once. No model call follows.
  • The answer is a short stream: a conversation frame, then turn_end with the turn’s stop_reason. This is not an error.
  • A second post for the same step is ignored, with the same answer.
  • Only a step that may have run takes a late result. A step stored as “It did not run” never does.
  • The platform matches a late post against the conversation’s five most recent turns that did not end normally.
  • If the post answers 409 turn_in_progress, a newer turn holds the conversation. Retry with backoff for up to 60 seconds, then keep the result and retry later.

Lost turns

The platform ends a turn nobody can finish, so a conversation never gets stuck:
  • A lost handoff: your app took client tool calls and posted no results within 10 minutes. The turn rests as failed with stop_reason: "handoff_lost". Its open steps get the “No result was recorded.” result. The next message is accepted. A result posted later is kept as a late result.
  • A lost segment: the segment running the turn died, for example in a deploy. The next request ends the turn as failed with stop_reason: "segment_lost", with the same result on its open steps.

Errors

Turns and streaming

Frames, turn states, and stop reasons.

Stop a turn (API reference)

The generated endpoint contract.
Last modified on September 29, 2026