Build one behavior before adding another prompt: when Claude returns pause_turn, your application should preserve the work already performed and make a controlled continuation. It should not tell the user the task is finished, restart the original request, or send an invented tool result.
This is a practical implementation problem for teams using Claude through an API gateway. A basic chat integration can appear healthy while a longer server-tool workflow exposes a missing state in the application. The model is available, authentication works, and ordinary answers render. The failure appears only when a task takes more than one response to complete.
The workshop below treats continuation as a small state machine. It is written for backend developers implementing research assistants, document workflows, or other services that use supported Claude server tools. It does not assume that every Claude relay supports those tools. Native capability must be confirmed for the selected route.
Workshop goal: preserve a turn across response boundaries
Start with a simple product requirement: a user submits one research task and receives either a reviewed result or an honest unfinished status. Behind that one user action, the application may make several model requests.
Give the user action a stable task identifier. Give each outbound model request its own attempt identifier. This makes it possible to explain that the task is still the same even when the request count increases. It also keeps your progress display from creating a new conversation every time the API returns.
The existing Claude gateway evaluation guide helps establish the route's starting requirements. For this workshop, the important additional requirement is preservation of native response blocks and termination information throughout a continued server-tool turn.
Establish which component is supposed to act next
Claude's response can stop for different reasons. The official stop-reason guide defines their meaning. Your controller should branch on the returned value before deciding whether to display a final answer, continue, or transfer control elsewhere.
| Returned reason | Controller action in this workshop |
|---|---|
pause_turn | Prepare a bounded continuation |
end_turn | Pass the result to application validation |
tool_use | Hand control to the client-tool handler |
max_tokens | Mark the output-limit case for its own recovery policy |
| Anything else | Use an explicit handler or retain an unresolved state |
This table is deliberately not a universal list of all possible values. Unknown values should be visible to maintainers rather than automatically treated as successful completion.
If the actual problem is an output limit or interrupted text, use the separate Claude truncated-response guide. A paused server-tool turn has a different next action; increasing every request's output allowance is not a general continuation strategy.
Preserve structure before you build a display string
A renderer often wants one plain string. A continuation controller needs the structured conversation. Maintain those as separate representations.
Keep the response content blocks in their original order. Derive the display text from a copy, and do not replace the stored blocks with that display text. If the interface hides a block that is not meant for the user, hiding it must not delete it from the continuation record.
This separation also benefits applications that display evidence. The native Claude citations article covers a different feature whose structure can likewise be lost through aggressive flattening. The general application design is useful here: presentation transformations should not overwrite protocol state.
The Messages API reference defines the request and response structures. Store your adapter version alongside the task so you can reproduce how those structures were handled after a deployment changes your serializer.
Implement one continuation step first
Anthropic's server-tools documentation specifies continuing with the paused assistant content, keeping the tool definitions, and retaining a returned container identifier when applicable. Earlier paused responses must remain in order.
The following Python function prepares that next request. It operates on JSON-compatible dictionaries from a completed native Messages response. It performs no network call and is not a complete agent runner. Your API adapter supplies the dictionaries and sends the returned request using the documented authentication and endpoint.
from copy import deepcopy
def prepare_continuation(current_request, response, used, limit=3):
if response.get("stop_reason") != "pause_turn":
raise ValueError("This handler only accepts pause_turn")
if used >= limit:
raise RuntimeError("Continuation limit reached; retain task for review")
if not isinstance(response.get("content"), list):
raise ValueError("Missing structured response content")
next_request = deepcopy(current_request)
next_request["messages"].append({
"role": "assistant",
"content": deepcopy(response["content"]),
})
container = response.get("container")
if isinstance(container, dict) and container.get("id"):
next_request["container"] = container["id"]
# Existing model, system instructions, tools, and other settings survive.
return next_request, used + 1
# Synthetic fixture: tests local state handling, not live provider execution.
request = {
"model": "ACCOUNT_ENABLED_CLAUDE_MODEL",
"max_tokens": 1000,
"messages": [{"role": "user", "content": "Prepare the research brief."}],
"tools": [{"type": "web_search_20250305", "name": "web_search"}],
}
paused = {"stop_reason": "pause_turn", "content": [{"type": "text", "text": "Working."}]}
next_request, used = prepare_continuation(request, paused, used=0)
assert len(request["messages"]) == 1
assert len(next_request["messages"]) == 2
assert next_request["tools"] == request["tools"]The fixture uses an intentionally configurable model placeholder. It demonstrates copying and appending state; it does not claim that the artificial response could be reproduced with that exact prompt. Use real responses from an enabled server-tool route for your integration test.
A single-step function is easier to inspect than a large automatic loop. Verify its input and output first, then place it inside your task worker. Keep transport retry policy outside this function because a network failure and a completed paused response are different events.
Make persistence the boundary between steps
Before sending a continuation, save the received response and the proposed next state through your application's protected task store. Record which response has been consumed by the controller. Only one worker should be allowed to advance that task version.
A practical implementation can use a database transaction and a version column. The worker reads version seven, prepares version eight, and updates only if the stored version is still seven. If another worker already advanced the record, the stale worker stops rather than issuing another continuation.
This is an application-side coordination mechanism. It does not establish provider-side idempotency, and it cannot prove that a timed-out outbound request never executed. Treat an uncertain network outcome explicitly instead of blindly resending the same step.
For broader background on duplicate requests, see the API retry and duplicate-call article. The relevant lesson for this controller is to separate one business task from its individual model attempts.
Decide what “bounded” means for your product
A continuation limit should express a product constraint. A short customer interaction may allow only a small number of additional steps; an overnight research task may tolerate more. Choose a maximum count, an overall task deadline, and an accounting limit appropriate to the application.
These controls should agree with the message shown to the user. If the task reaches its deadline, do not display “completed” merely because the last response contains some prose. Preserve the progress and explain that the requested work was not fully completed within the available budget.
Count the whole task, not only the most recent response. Input can grow as the conversation grows, and additional tool activity can add charges. Use the current provider and gateway pricing rules when estimating cost; there is no universal free-continuation rule.
The existing Claude token-counting guide can help with request planning. Its preflight measurements are not a replacement for recording the usage actually reported by completed attempts.
Keep client tools on their own branch
Server tools and client tools have different execution owners. The official tool-use explanation describes that division. Your application should not manufacture a client tool_result merely because it sees server-tool activity.
For a response that requests a client tool, transfer control to the handler responsible for validating arguments, checking permissions, executing the approved operation, and returning its result in the appropriate format. Do not let the pause handler perform those actions accidentally.
This matters in enterprise systems where a tool can change a record or trigger an external action. A model requesting work is not the same as an application authorizing it. Keep that business decision in the tool handler even if the surrounding conversation otherwise continues automatically.
Mixed workflows deserve a test of their own. Passing a server-only example does not prove that a task combining hosted research tools and your internal customer database will behave correctly through every adapter.
Add streaming only after the state transitions are clear
Developers often try to debug event assembly, rendering, and continuation in the same loop. Start with completed response objects. Once those transitions work, integrate your stream assembler and verify that it produces the same response representation.
Follow the Claude streaming guide for event handling. Do not start a continuation simply because a text block ended; the controller needs the completed message and its termination information. If the stream breaks before that state is available, keep it in a transport-failure branch.
Consult the Claude error reference when recording failures and identifiers for support. Avoid exposing raw error payloads to end users without reviewing them. The product message can remain simple while the authorized diagnostic record retains useful detail.
Exercise the controller with fixtures before spending on inference
Create local fixtures for a normal finish, one pause followed by a finish, repeated pauses reaching the limit, a missing content array, and a client-tool handoff. Include two competing workers attempting to advance the same task version.
For each fixture, specify the expected next action. The most important assertion is often that no new API request should be sent. For example, a stale worker or an exhausted continuation budget should stop locally.
Then run a small integration test with the selected Claude route. Preserve the actual blocks returned by that route and compare the continuation your adapter emits. Confirm that you can complete the workflow through the gateway, not merely through a direct-provider account using different credentials.
Passing these tests creates a useful engineering deliverable: evidence that the application handles this specific native behavior. It is more meaningful than a broad claim that two APIs are “fully compatible.”
Give the user a task they can understand
A good progress interface can say “Research is continuing” and retain the same task link. It does not need to expose pause_turn, container identifiers, or request counters to every user. Those details belong in diagnostics unless they help the user make a decision.
If the user cancels, stop scheduling new continuations and record cancellation separately from a successful answer. Any already-running request needs its own handling; a local cancel button does not prove upstream execution stopped.
When the final result passes validation, display the deliverable and any evidence your application supports. The user should see one coherent task, while the engineering team can inspect the sequence that produced it.
Start with one supported Claude workflow
Open Treerouter to confirm the current Claude route and whether your required server tools and continuation fields are supported. Register to run one bounded research task only after those requirements match the available interface. Keep the first trial small enough to inspect every transition.
The result you want is concrete: a paused turn that continues without losing its previous blocks, a worker that avoids duplicate advancement, and an unfinished task that never masquerades as a completed answer. That is a practical reason to adopt an API relay for a Claude application—and a clear condition for deciding whether a particular route fits your product.






