Skip to content
skyl

Reading a Response

What comes back, what it means, and what it cost.

A *skyl.Response carries the assistant's turn, why generation stopped, what it cost, and — always — the provider's untouched body. This chapter covers each, including the parts where providers disagree and skyl has to normalise.

In this chapter

  • Every field on Response, and which ones are always populated
  • How to get text, tool calls, or both
  • What each stop reason means and which are provider-specific
  • Why cached tokens are a breakdown of your input, not an addition to it
  • Why the model that answered may not be the one you asked for
  • How to reach anything skyl does not model

The response object#

resp, err := client.Complete(ctx, req)

resp.ID          // the provider's identifier, when it gives one
resp.Provider    // "anthropic"
resp.Model       // the model that ACTUALLY answered
resp.Message     // the assistant's turn, ready to append
resp.StopReason  // why generation ended
resp.Usage       // token consumption
resp.Raw         // the untouched provider body — ALWAYS populated
resp, err := client.Complete(ctx, req)

resp.ID          // the provider's identifier, when it gives one
resp.Provider    // "anthropic"
resp.Model       // the model that ACTUALLY answered
resp.Message     // the assistant's turn, ready to append
resp.StopReason  // why generation ended
resp.Usage       // token consumption
resp.Raw         // the untouched provider body — ALWAYS populated

Read The Response Object for every field in detail, including which are best-effort.

Read more →

Text and tool calls#

Read Text and Tool Calls for the difference between Text() and Message.Parts, and why reasoning content is not in either.

Read more →

Stop reasons#

ConstantValueMeaningProvider values
StopEndTurnend_turnThe model finished naturally.end_turn, stop, STOP
StopMaxTokensmax_tokensThe output hit Request.MaxTokens. The response is truncated — treat it as incomplete.max_tokens, length, MAX_TOKENS, model_context_window_exceeded
StopToolUsetool_useThe model wants a tool run. Execute the calls and send the results back.tool_use, tool_calls, function_call
StopStopSequencestop_sequenceA sequence from Request.Stop was produced. Only ever comes from Anthropic — OpenAI reports a stop-sequence hit as plain "stop", so it arrives as StopEndTurn.stop_sequence (Anthropic only)
StopRefusalrefusalThe model or its safety classifiers declined. Content may be empty or partial; do not retry the same request.refusal, content_filter, SAFETY, RECITATION, BLOCKLIST, PROHIBITED_CONTENT, SPII
StopUnknownunknownThe provider reported something skyl does not model. Read Response.Raw.anything else, including pause_turn, OTHER, MALFORMED_FUNCTION_CALL

Read Stop Reasons for the two that are effectively provider-specific, and how to handle a truncated answer.

Read more →

Token usage#

Read Token Usage and Caching — this is the page that stops your cost report being wrong by the size of your cache.

Read more →

Which model answered#

Read Which Model Actually Answered for why resp.Model is read from the response rather than echoed.

Read more →

Raw provider JSON#

Read Reading Raw Provider JSON for the escape hatch that means nothing a provider sends is ever lost.

Read more →

What’s next?

Start with The Response Object. If you are chasing a cost discrepancy, go straight to Token Usage and Caching — it is almost certainly the inclusion semantics.

Edit this page on GitHub