Claudio.Messages.Request (Claudio v0.7.0)

View Source

Builder for constructing Messages API requests.

Example

alias Claudio.Messages.Request

Request.new("claude-opus-5-5")
|> Request.add_message(:user, "Hello!")
|> Request.set_system("You are a helpful assistant")
|> Request.set_max_tokens(1024)
|> Request.to_map()

Caching options

Cache breakpoints are GA (no beta header). ttl: is "5m" (default) or "1h"; anything else raises ArgumentError.

Summary

Functions

Adds the advisor tool (advisor_20260301; declares advisor-tool-2026-03-01): the model can consult model mid-task. Replaying advisor blocks later also needs the beta — add_message/3 declares it.

Adds the client-side, schema-less bash tool (bash_20250124). You execute the returned tool_use locally and send back a tool_result. Do not add an input_schema — the schema is built into the model.

Adds a beta feature flag the request requires.

Adds the browser use client toolset (browser_toolset_20260801, GA, no beta). Same mechanics and options as add_computer_toolset/2, with toolset_name "browser".

Adds a clear_thinking_20251015 context edit (declares context-management-2025-06-27). It is always placed first in edits — the API rejects it anywhere else.

Adds a clear_tool_uses_20250919 context edit (declares context-management-2025-06-27): once the trigger is reached, the API clears older tool results from the prompt it sends to the model. Your stored history is unchanged.

Adds the server-side code_execution tool. GA — no beta header. Pairs with set_container/2 for container reuse and the Files API (container_upload blocks). Results arrive as bash_code_execution_tool_result / text_editor_code_execution_tool_result blocks.

Adds a compact_20260112 edit — threshold compaction (declares compact-2026-01-12). When the input passes the trigger, the API summarizes the conversation into a compaction block at the start of the reply; everything before that block is ignored on later turns. Keep this edit on every later request that replays the block (the API rejects a replayed threshold block without it); see apply_compaction/2.

Adds the computer tool (computer_20250124) for desktop control, and declares the required computer-use-2025-01-24 beta header (via add_beta/2, so the send path attaches it automatically).

Adds the computer use client toolset (computer_toolset_20260801, GA, no beta) — the computer tool Claude Opus 5.5 accepts. Each action arrives as its own tool_use whose name is the member ("screenshot", "left_click", …) and whose toolset_name is "computer"; every tool_result must echo toolset_name (Claudio.Tools.create_tool_result/4). See Claudio.Agent for a loop that does this.

Adds a server for the MCP connector (mcp-client-2025-11-20).

Adds the client-side memory tool (memory_20250818). GA — no beta header.

Adds a message to the conversation.

Adds a text message whose content block carries a cache_control breakpoint.

Adds a text message with a document from the Files API.

Adds a text message with an image from a base64-encoded string.

Adds a text message with an image from a URL.

Adds a tool with strict schema validation enabled (strict: true).

Appends a mid-conversation role: "system" message (GA — no beta header).

Adds the client-side, schema-less text editor tool (text_editor_20250728, name str_replace_based_edit_tool). Client-executed like bash.

Adds a tool definition.

Adds a tool search tool (GA, no beta) so tools added with defer_loading: true are found on demand: :regex (tool_search_tool_regex_20251119) or :bm25 (tool_search_tool_bm25_20251119).

Adds a tool definition with prompt caching enabled.

Adds a tool with fine-grained ("eager") input streaming enabled.

Adds the server-side web_fetch tool. GA — no beta header.

Adds the server-side web_search tool. GA — no beta header.

Continues a conversation from a compaction summary, for either kind of compaction.

Turns up-front thinking off, replacing any previous thinking config.

Enables adaptive thinking (thinking: %{"type" => "adaptive"}), replacing any previous thinking config. The model decides how much to think; steer it with set_effort/2.

Asks for cache diagnostics (GA, no beta): the response's diagnostics explains a prompt-cache miss against previous_message_id (the id of an earlier response in the same conversation). It is nil when there is nothing to compare or no divergence was found, and %{"cache_miss_reason" => nil} when the comparison was still pending. Not sent by Claudio.Messages.count_tokens/2 when given a Request (that endpoint rejects it).

Enables streaming responses.

Enables extended thinking with optional budget.

Creates a new request builder with the specified model.

Asks for an on-demand summary of the conversation so far (top-level compaction: %{"type" => "summarize"}; declares compact-2026-09-04). The reply is only a signed compaction block with stop_reason: :compaction; continue with apply_compaction/2. The API rejects this combined with context_management, stop_sequences, output_config.format, a forced tool_choice, or a last assistant turn ending in an unanswered tool_use — those are left to its 400. To drop context-management edits set earlier, use %{request | context_management: nil} (set_context_management/2 takes a map, and %{} would still be sent).

Returns the list of beta feature flags this request requires.

Builds a search_result content block for RAG / grounded citations.

Sets a top-level cache_control breakpoint, auto-placed on the last cacheable block of the request (server-side). The simplest way to cache the request prefix when you don't need per-block placement. GA — no beta header.

Sets container identifier for tool reuse.

Sets the raw context_management map, replacing any previous one (including edits added by add_clear_tool_uses/2, add_clear_thinking/2, add_compaction/2; betas they declared stay). Always declares context-management-2025-06-27; also declares compact-2026-01-12 when edits holds a compact_20260112 edit (the API rejects it otherwise). Prefer the builders.

Sets output_config.effort — how much the model thinks and spends overall. GA, no beta header. Merges into output_config.

Sets fallbacks — server-side retry of a refused request on another model (beta; declares server-side-fallback-2026-07-01).

Sets inference_geo — where the request is processed (:global or :us; GA, no beta). Without it the workspace default applies. :us is billed at 1.1× standard pricing. Not sent by Claudio.Messages.count_tokens/2 when given a Request (that endpoint rejects it). The response's usage.inference_geo reports where it ran.

Sets the maximum number of tokens to generate.

Sets request metadata.

Sets the raw output_config map.

Requests structured JSON output matching schema (a JSON Schema map).

Sets service tier for capacity selection.

Sets speed (:fast or :standard). Fast mode is an access-gated research preview. Always declares the fast-mode-2026-02-01 beta — the API rejects the speed field without it, even for :standard. The response's usage.speed reports the speed used.

Sets custom stop sequences.

Sets the system prompt.

Sets the system prompt with prompt caching enabled.

Sets an advisory token budget for the whole task (output_config.task_budget = %{"type" => "tokens", "total" => total}) and declares the task-budgets-2026-03-13 beta. Merges into output_config; calling it again replaces the budget. max_tokens stays the hard cap.

Sets the temperature (0.0-1.0).

Sets thinking.block_binding.prefix_mismatch_behavior (:error or :drop_block) on the thinking config already set — adaptive or a raw enable_thinking/2 "enabled" map — and declares thinking-binding-controls-2026-08-01. Raises if no thinking config is set. A later thinking setter replaces the whole map (the beta stays declared). The API rejects block_binding on "disabled" thinking.

Sets tool choice strategy.

Sets top_k for sampling from top K options.

Sets top_p for nucleus sampling (0.0-1.0).

Converts the request to a map suitable for the API.

Types

content()

@type content() :: String.t() | [map()]

role()

@type role() :: :user | :assistant

t()

@type t() :: %Claudio.Messages.Request{
  betas: [String.t()],
  cache_control: map() | nil,
  compaction: map() | nil,
  container: String.t() | map() | nil,
  context_management: map() | nil,
  diagnostics: map() | nil,
  fallbacks: String.t() | [map()] | nil,
  inference_geo: String.t() | nil,
  max_tokens: integer() | nil,
  mcp_servers: [map()] | nil,
  messages: [map()],
  metadata: map() | nil,
  model: String.t(),
  output_config: map() | nil,
  service_tier: String.t() | nil,
  speed: String.t() | nil,
  stop_sequences: [String.t()] | nil,
  stream: boolean() | nil,
  system: String.t() | list() | nil,
  temperature: float() | nil,
  thinking: map() | nil,
  tool_choice: map() | nil,
  tools: [map()] | nil,
  top_k: integer() | nil,
  top_p: float() | nil
}

tool_choice()

@type tool_choice() :: :auto | :any | {:tool, String.t()} | :none

Functions

add_advisor_tool(request, model, opts \\ [])

@spec add_advisor_tool(t(), String.t(), keyword()) :: t()

Adds the advisor tool (advisor_20260301; declares advisor-tool-2026-03-01): the model can consult model mid-task. Replaying advisor blocks later also needs the beta — add_message/3 declares it.

Options

  • :max_uses — advisor calls per request
  • :max_tokens — advisor output cap (API minimum 1024)
  • :caching — "5m" or "1h": caches the advisor's context

add_bash_tool(request)

@spec add_bash_tool(t()) :: t()

Adds the client-side, schema-less bash tool (bash_20250124). You execute the returned tool_use locally and send back a tool_result. Do not add an input_schema — the schema is built into the model.

add_beta(request, beta)

@spec add_beta(t(), String.t()) :: t()

Adds a beta feature flag the request requires.

Beta flags are merged into the anthropic-beta request header at send time (see Claudio.Client.with_betas/2). Use this to opt into beta-gated features the library does not model with a dedicated setter.

Duplicates are ignored; insertion order is preserved.

Example

Request.new("claude-opus-4-8")
|> Request.add_beta("context-management-2025-06-27")

add_browser_toolset(request, opts \\ [])

@spec add_browser_toolset(
  t(),
  keyword()
) :: t()

Adds the browser use client toolset (browser_toolset_20260801, GA, no beta). Same mechanics and options as add_computer_toolset/2, with toolset_name "browser".

add_clear_thinking(request, opts \\ [])

@spec add_clear_thinking(
  t(),
  keyword()
) :: t()

Adds a clear_thinking_20251015 context edit (declares context-management-2025-06-27). It is always placed first in edits — the API rejects it anywhere else.

Options

  • :keep — :all, or a positive number of recent assistant turns whose thinking is kept. Omitted: the model's default.

add_clear_tool_uses(request, opts \\ [])

@spec add_clear_tool_uses(
  t(),
  keyword()
) :: t()

Adds a clear_tool_uses_20250919 context edit (declares context-management-2025-06-27): once the trigger is reached, the API clears older tool results from the prompt it sends to the model. Your stored history is unchanged.

Options (each omitted option is left to the API default)

  • :trigger — {:input_tokens, n} or {:tool_uses, n}
  • :keep — number of most recent tool uses to keep
  • :clear_at_least — minimum input tokens to clear (makes the cache invalidation worth it)
  • :exclude_tools — tool names never cleared
  • :clear_tool_inputs — true, false, or a list of tool names whose inputs are cleared too

Example

Request.new("claude-opus-5-5")
|> Request.add_clear_tool_uses(trigger: {:input_tokens, 100_000}, keep: 3)

add_code_execution_tool(request, opts \\ [])

@spec add_code_execution_tool(
  t(),
  keyword()
) :: t()

Adds the server-side code_execution tool. GA — no beta header. Pairs with set_container/2 for container reuse and the Files API (container_upload blocks). Results arrive as bash_code_execution_tool_result / text_editor_code_execution_tool_result blocks.

Options

  • :version — :"20260521" (default), :"20260120", or :"20250825". 20260521 and 20260120 run the same runtime (REPL persistence and programmatic tool calling); 20260521 also tells Claude about the 90-second per-cell limit. Use :"20250825" to turn those features off.

add_compaction(request, opts \\ [])

@spec add_compaction(
  t(),
  keyword()
) :: t()

Adds a compact_20260112 edit — threshold compaction (declares compact-2026-01-12). When the input passes the trigger, the API summarizes the conversation into a compaction block at the start of the reply; everything before that block is ignored on later turns. Keep this edit on every later request that replays the block (the API rejects a replayed threshold block without it); see apply_compaction/2.

Options (each omitted option is left to the API default)

  • :trigger — input tokens that trigger compaction (API default 150000, minimum 50000)
  • :pause_after_compaction — true returns right after the summary (stop_reason: :compaction)
  • :instructions — summarization instructions

add_computer_tool(request, display_width_px, display_height_px, opts \\ [])

@spec add_computer_tool(t(), pos_integer(), pos_integer(), keyword()) :: t()

Adds the computer tool (computer_20250124) for desktop control, and declares the required computer-use-2025-01-24 beta header (via add_beta/2, so the send path attaches it automatically).

Client-side: Claude requests screenshots / mouse / keyboard actions that your application executes. Typically paired with add_bash_tool/1 and add_text_editor_tool/2.

Options

  • :display_number — X11 display number for the environment.
  • :version — :"20251124" for computer_20251124 (declares computer-use-2025-11-24). Claude Opus 5.5 accepts only the toolset: use add_computer_toolset/2.

add_computer_toolset(request, opts \\ [])

@spec add_computer_toolset(
  t(),
  keyword()
) :: t()

Adds the computer use client toolset (computer_toolset_20260801, GA, no beta) — the computer tool Claude Opus 5.5 accepts. Each action arrives as its own tool_use whose name is the member ("screenshot", "left_click", …) and whose toolset_name is "computer"; every tool_result must echo toolset_name (Claudio.Tools.create_tool_result/4). See Claudio.Agent for a loop that does this.

Options

  • :configs — %{member => %{enabled: boolean, defer_loading: boolean}}
  • :cache_control — cache breakpoint on the entry

add_mcp_server(request, server)

@spec add_mcp_server(t(), Claudio.MCP.ServerConfig.t() | map()) :: t()

Adds a server for the MCP connector (mcp-client-2025-11-20).

Emits both halves the API requires: the server entry in mcp_servers and an mcp_toolset entry in tools referencing it by name. Declares the mcp-client-2025-11-20 beta via add_beta/2.

Accepts a Claudio.MCP.ServerConfig or a raw map; a legacy tool_configuration key in a raw map is translated onto the toolset with a deprecation warning. If tools already holds an mcp_toolset for that server name (the API allows one per server), no second toolset is added — unless the new one carries default_config/configs, which would be lost, so that raises ArgumentError. Add hand-built toolsets before calling this, or the request will carry two. Server names must be unique; adding a second server with an existing name raises ArgumentError.

Request.new("claude-opus-5-5")
|> Request.add_mcp_server(
  Claudio.MCP.ServerConfig.new("my_server", "https://mcp.example.com/sse")
)

add_memory_tool(request)

@spec add_memory_tool(t()) :: t()

Adds the client-side memory tool (memory_20250818). GA — no beta header.

Claude issues view / create / str_replace / insert / delete / rename commands scoped to a /memories directory; you execute them locally. Confine every operation to /memories and reject path traversal. Pairs with set_context_management/2 for long-running agents.

add_message(request, role, content)

@spec add_message(t(), role(), content()) :: t()

Adds a message to the conversation.

Content can be:

  • A string for simple text messages
  • A list of content blocks for multimodal messages (text, images, documents)

A list content holding a fallback block (from Response.to_assistant_content/1) declares server-side-fallback-2026-07-01, which the API requires to accept it.

A compaction block declares its replay beta: compact-2026-09-04 when it carries a signature (on-demand), else compact-2026-01-12 (threshold — which also needs the compact_20260112 edit on the request; see add_compaction/2).

Advisor blocks (advisor_tool_result, or a server_tool_use named "advisor") declare advisor-tool-2026-03-01.

MCP blocks (mcp_tool_use, mcp_tool_result) declare mcp-client-2025-11-20, so a history holding an MCP call can be replayed on a turn without add_mcp_server/2.

Examples

# Simple text message
Request.new("claude-opus-5-5")
|> Request.add_message(:user, "What is the weather?")

# Multimodal message with image
Request.new("claude-opus-5-5")
|> Request.add_message(:user, [
  %{"type" => "image", "source" => %{
    "type" => "base64",
    "media_type" => "image/jpeg",
    "data" => base64_image
  }},
  %{"type" => "text", "text" => "What's in this image?"}
])

add_message_with_cache(request, role, text, opts \\ [])

@spec add_message_with_cache(t(), role(), String.t(), keyword()) :: t()

Adds a text message whose content block carries a cache_control breakpoint.

Use for the "growing conversation prefix" caching pattern — mark the last stable turn so the prefix up to it is cached. GA — no beta header. Up to 4 cache_control breakpoints are allowed per request (not enforced here).

Options

  • :ttl — cache duration, "5m" (default) or "1h"

Example

Request.new("claude-opus-4-8")
|> Request.add_message_with_cache(:user, "Large shared context...", ttl: "1h")
|> Request.add_message(:user, "The actual question")

add_message_with_document(request, role, text, file_id, opts \\ [])

@spec add_message_with_document(t(), role(), String.t(), String.t(), keyword()) :: t()

Adds a text message with a document from the Files API.

Options

  • :citations - When true, enables citations on the document ("citations" => %{"enabled" => true}). The API requires citations to be enabled on all-or-none of the documents in a request. Incompatible with structured outputs (set_output_config/2) — the API returns 400.
  • :title - Optional document title (length-limited; not cited from).
  • :context - Optional document metadata passed to the model but not cited from.

Examples

Request.new("claude-opus-5-5")
|> Request.add_message_with_document(:user, "Summarize this document", "file_abc123")

Request.new("claude-opus-4-8")
|> Request.add_message_with_document(:user, "Summarize", "file_abc123",
  citations: true,
  title: "Q4 Report"
)

add_message_with_image(request, role, text, base64_data, media_type \\ nil)

@spec add_message_with_image(
  t(),
  role(),
  String.t(),
  String.t(),
  String.t() | keyword() | nil
) :: t()

Adds a text message with an image from a base64-encoded string.

Without media_type, PNG, GIF, WebP and JPEG are detected from the data's leading bytes (a mismatched type is a 400); anything unrecognized is sent as "image/jpeg".

The fifth argument may be a string "image/png", a keyword list [media_type: "image/png"], or nil / an empty keyword list [] for auto-detection.

Example

Request.new("claude-opus-5-5")
|> Request.add_message_with_image(:user, "What's in this image?", base64_data, "image/jpeg")

# or with keyword option
Request.new("claude-opus-5-5")
|> Request.add_message_with_image(:user, "What's in this image?", base64_data, media_type: "image/png")

add_message_with_image_url(request, role, text, image_url)

@spec add_message_with_image_url(t(), role(), String.t(), String.t()) :: t()

Adds a text message with an image from a URL.

Example

Request.new("claude-opus-5-5")
|> Request.add_message_with_image_url(:user, "What's in this image?", "https://example.com/image.jpg")

add_strict_tool(request, tool)

@spec add_strict_tool(t(), map()) :: t()

Adds a tool with strict schema validation enabled (strict: true).

Guarantees the model's tool_use.input validates exactly against the schema. The schema must use "additionalProperties" => false and list "required". GA — no beta header. (strict is a plain tool field; add_tool/2 also passes it through if you set it yourself.)

add_system_message(request, content, opts \\ [])

@spec add_system_message(t(), String.t() | [map()], keyword()) :: t()

Appends a mid-conversation role: "system" message (GA — no beta header).

content is a string or a list of content blocks, passed through unchanged. Where the message may sit (after a user turn, not first when it carries content, …) is checked by the API, not here.

Options

  • :clear_at — :next_user_message (the message stops rendering once a later user message exists) or :never. Declares the mid-conversation-system-clear-at-2026-08-21 beta.
  • :effort — :low … :max: per-message effort from the next user turn on ("output_config" => %{"effort" => ...}). Declares the mid-conversation-output-config-2026-07-01 beta. With content: [] this is an effort-only message, which the API accepts anywhere, including first.

Raises ArgumentError for combinations the API always rejects: clear_at: :next_user_message with :effort, and [] content without :effort.

Example

Request.new("claude-opus-5-5")
|> Request.add_system_message([], effort: :low)
|> Request.add_message(:user, "Name a primary color.")
|> Request.add_system_message("Answer in one word.", clear_at: :next_user_message)

add_text_editor_tool(request, opts \\ [])

@spec add_text_editor_tool(
  t(),
  keyword()
) :: t()

Adds the client-side, schema-less text editor tool (text_editor_20250728, name str_replace_based_edit_tool). Client-executed like bash.

Options

  • :max_characters — cap view-command output length.

add_tool(request, tool, opts \\ [])

@spec add_tool(t(), map(), keyword()) :: t()

Adds a tool definition.

Example

tool = %{
  "name" => "get_weather",
  "description" => "Get weather for a location",
  "input_schema" => %{
    "type" => "object",
    "properties" => %{
      "location" => %{"type" => "string"}
    },
    "required" => ["location"]
  }
}

Request.new("claude-opus-5-5")
|> Request.add_tool(tool)

Options

  • :defer_loading — true keeps the tool out of the initial prompt until a tool search tool (add_tool_search_tool/2) returns a reference to it. At least one tool must stay non-deferred.
  • :allowed_callers — who may call the tool: :direct (the model; the default when omitted), :code_execution (code inside a code_execution_20260120+ sandbox — programmatic tool calling), or a raw string.

add_tool_search_tool(request, variant)

@spec add_tool_search_tool(t(), :regex | :bm25) :: t()

Adds a tool search tool (GA, no beta) so tools added with defer_loading: true are found on demand: :regex (tool_search_tool_regex_20251119) or :bm25 (tool_search_tool_bm25_20251119).

add_tool_with_cache(request, tool, opts \\ [])

@spec add_tool_with_cache(t(), map(), keyword()) :: t()

Adds a tool definition with prompt caching enabled.

Useful when you have many tool definitions and want to cache them.

Example

tool = %{
  "name" => "get_weather",
  "description" => "Get weather for a location",
  "input_schema" => %{"type" => "object", "properties" => %{}}
}

Request.new("claude-opus-5-5")
|> Request.add_tool_with_cache(tool)

add_tool_with_eager_streaming(request, tool)

@spec add_tool_with_eager_streaming(t(), map()) :: t()

Adds a tool with fine-grained ("eager") input streaming enabled.

Sets eager_input_streaming: true so the tool's input_json_delta chunks stream as they are generated. GA — not a beta feature; use the regular streaming path (enable_streaming/1).

add_web_fetch_tool(request, opts \\ [])

@spec add_web_fetch_tool(
  t(),
  keyword()
) :: t()

Adds the server-side web_fetch tool. GA — no beta header.

Options

  • :version — :basic for web_fetch_20250910, otherwise the default web_fetch_20260209 (dynamic filtering). A full type string is also accepted.
  • :max_uses — cap the number of fetches per request.
  • :allowed_domains / :blocked_domains — domain filtering (lists).
  • :citations — true enables citations on fetched content.
  • :max_content_tokens — approximate cap on fetched content size.
  • :response_inclusion — "excluded" drops the nested server_tool_use and result block pairs whose result was consumed by a completed code execution call in the same turn; the API default is "full". Requires version: :"20260318" or later; passed through verbatim.
  • :allowed_callers — [:direct], [:code_execution] or raw strings (see add_tool/3).

Unlike web search (URLs Claude finds), web fetch can only retrieve URLs that already appeared in the conversation.

add_web_search_tool(request, opts \\ [])

@spec add_web_search_tool(
  t(),
  keyword()
) :: t()

Adds the server-side web_search tool. GA — no beta header.

Options

  • :version — :basic for web_search_20250305, otherwise the default web_search_20260209 (dynamic filtering on 4.6+). A full type string is also accepted.
  • :max_uses — cap the number of searches per request.
  • :allowed_domains / :blocked_domains — domain filtering (lists).
  • :user_location — approximate-location map for localized results.
  • :response_inclusion — "excluded" drops the nested server_tool_use and result block pairs whose result was consumed by a completed code execution call in the same turn; the API default is "full". Requires version: :"20260318" or later; passed through verbatim.
  • :allowed_callers — [:direct], [:code_execution] or raw strings (see add_tool/3); accepted by every web search version.

Server-tool output is typed as server_tool_use / web_search_tool_result blocks (see Claudio.Messages.Response.get_server_tool_uses/1).

apply_compaction(request, response)

@spec apply_compaction(t(), Claudio.Messages.Response.t()) :: t()

Continues a conversation from a compaction summary, for either kind of compaction.

Replaces messages with a single assistant message holding the response content from its last compaction block onward (the block first, byte-exact, as the API requires), and clears compaction so the next call is a normal turn. Everything else — system, tools, thinking, context_management (a threshold replay needs its compact_20260112 edit), betas — is kept. The replay beta is declared by add_message/3. Add the next user turn after it — also after a pause_after_compaction: true reply, whose content is only the block (a [assistant: [block], user: …] history is accepted, probe P8). A paused threshold compaction summarized the user turn that triggered it too: re-add that turn after the block if the next reply should still answer it.

Raises ArgumentError for a failed compaction (content: nil) — the current history is still the only record of the conversation.

Editing the history yourself (rather than through this function) can invalidate the signatures of kept thinking blocks; set_thinking_block_binding(:drop_block) makes the API drop such blocks instead of rejecting the request.

Raises ArgumentError when the response has no compaction block.

disable_thinking(request, opts \\ [])

@spec disable_thinking(
  t(),
  keyword()
) :: t()

Turns up-front thinking off, replacing any previous thinking config.

Options

  • :mode — :disabled (default) sends %{"type" => "disabled"}. :between_tools sends %{"type" => "between_tools"}: no thinking before the first response, but thinking between tool calls. Claude Sonnet 5.5 uses :between_tools as its off switch (at high effort or below).

On Claude Opus 5.5, thinking can't be disabled: "disabled" returns a 400 error. Omit the thinking field and control thinking depth with set_effort/2.

enable_adaptive_thinking(request, opts \\ [])

@spec enable_adaptive_thinking(
  t(),
  keyword()
) :: t()

Enables adaptive thinking (thinking: %{"type" => "adaptive"}), replacing any previous thinking config. The model decides how much to think; steer it with set_effort/2.

Options

  • :display — :summarized, :omitted or :updates. Omit it (or pass nil) to use the model's default. :updates (progress notes as separate thinking blocks) also declares the thinking-display-updates-2026-08-18 beta. A beta declared here stays declared if thinking is later replaced.
  • :block_binding — :error or :drop_block: what the API does with a thinking block whose conversation prefix changed since it was produced (an edited earlier message, a block removed from the middle). :error rejects the request (400); :drop_block drops that block and every later thinking block and reports it in Response.input_transformations. Declares thinking-binding-controls-2026-08-01. Unset: accounts created on/after 2026-08-31 behave as :error; older accounts are not enforced. See set_thinking_block_binding/2.

Example

Request.new("claude-opus-5-5")
|> Request.enable_adaptive_thinking(display: :summarized)
|> Request.set_effort(:high)

enable_cache_diagnostics(request, previous_message_id \\ nil)

@spec enable_cache_diagnostics(t(), String.t() | nil) :: t()

Asks for cache diagnostics (GA, no beta): the response's diagnostics explains a prompt-cache miss against previous_message_id (the id of an earlier response in the same conversation). It is nil when there is nothing to compare or no divergence was found, and %{"cache_miss_reason" => nil} when the comparison was still pending. Not sent by Claudio.Messages.count_tokens/2 when given a Request (that endpoint rejects it).

enable_streaming(request)

@spec enable_streaming(t()) :: t()

Enables streaming responses.

Example

Request.new("claude-opus-5-5")
|> Request.enable_streaming()

enable_thinking(request, config)

@spec enable_thinking(t(), map()) :: t()

Enables extended thinking with optional budget.

Example

Request.new("claude-opus-5-5")
|> Request.enable_thinking(%{"type" => "adaptive"})

%{"type" => "enabled", "budget_tokens" => n} returns 400 on Claude Opus 4.7+, Opus 5.x, Sonnet 5 and Fable models; use "adaptive" there. This is the raw setter (replaces thinking); prefer enable_adaptive_thinking/2 / disable_thinking/2, and set_effort/2 to steer how much the model thinks.

new(model)

@spec new(String.t()) :: t()

Creates a new request builder with the specified model.

Example

Request.new("claude-opus-5-5")

request_compaction(request, opts \\ [])

@spec request_compaction(
  t(),
  keyword()
) :: t()

Asks for an on-demand summary of the conversation so far (top-level compaction: %{"type" => "summarize"}; declares compact-2026-09-04). The reply is only a signed compaction block with stop_reason: :compaction; continue with apply_compaction/2. The API rejects this combined with context_management, stop_sequences, output_config.format, a forced tool_choice, or a last assistant turn ending in an unanswered tool_use — those are left to its 400. To drop context-management edits set earlier, use %{request | context_management: nil} (set_context_management/2 takes a map, and %{} would still be sent).

Options

  • :instructions — replaces the default summarization prompt (≤ 16384 characters)

Example

{:ok, summary} = Messages.create(client, Request.request_compaction(request))

request =
  request
  |> Request.apply_compaction(summary)
  |> Request.add_message(:user, "Continue")

required_betas(request)

@spec required_betas(t()) :: [String.t()]

Returns the list of beta feature flags this request requires.

search_result_block(source, title, contents, opts \\ [])

@spec search_result_block(String.t(), String.t(), [String.t() | map()], keyword()) ::
  map()

Builds a search_result content block for RAG / grounded citations.

contents may be a list of strings (each wrapped as a text block) or a list of pre-built text-block maps. Compose into a turn with add_message/3:

result =
  Request.search_result_block("https://docs/api", "API Reference", ["…"],
    citations: true
  )

request
|> Request.add_message(:user, [
  result,
  %{"type" => "text", "text" => "How do I authenticate?"}
])

Options

  • :citations - When true, enables citations on this result (surfaces as search_result_location citations on response text blocks).
  • :cache_control - true for default ephemeral caching, or a ttl string ("5m" / "1h").

set_cache_control(request, opts \\ [])

@spec set_cache_control(
  t(),
  keyword()
) :: t()

Sets a top-level cache_control breakpoint, auto-placed on the last cacheable block of the request (server-side). The simplest way to cache the request prefix when you don't need per-block placement. GA — no beta header.

Options

  • :ttl — cache duration, "5m" (default) or "1h"

Example

Request.new("claude-opus-4-8")
|> Request.set_system("Large shared context...")
|> Request.set_cache_control(ttl: "1h")

set_container(request, container)

@spec set_container(t(), String.t() | map()) :: t()

Sets container identifier for tool reuse.

Allows tools to maintain state across requests.

Example

# String container ID
Request.new("claude-opus-5-5")
|> Request.set_container("my-container-123")

# Container config object
Request.new("claude-opus-5-5")
|> Request.set_container(%{
  "id" => "my-container",
  "ttl" => 3600
})

set_context_management(request, config)

@spec set_context_management(t(), map()) :: t()

Sets the raw context_management map, replacing any previous one (including edits added by add_clear_tool_uses/2, add_clear_thinking/2, add_compaction/2; betas they declared stay). Always declares context-management-2025-06-27; also declares compact-2026-01-12 when edits holds a compact_20260112 edit (the API rejects it otherwise). Prefer the builders.

Example

Request.new("claude-opus-5-5")
|> Request.set_context_management(%{
  "edits" => [
    %{"type" => "clear_thinking_20251015", "keep" => "all"},
    %{"type" => "clear_tool_uses_20250919", "keep" => %{"type" => "tool_uses", "value" => 3}},
    %{"type" => "compact_20260112", "trigger" => %{"type" => "input_tokens", "value" => 150_000}}
  ]
})

set_effort(request, level)

@spec set_effort(t(), :low | :medium | :high | :xhigh | :max) :: t()

Sets output_config.effort — how much the model thinks and spends overall. GA, no beta header. Merges into output_config.

level is :low, :medium, :high, :xhigh or :max. Which levels a model accepts (and its default) varies; the API rejects unsupported ones.

Example

Request.new("claude-opus-5-5")
|> Request.enable_adaptive_thinking()
|> Request.set_effort(:xhigh)

set_fallbacks(request, entries)

@spec set_fallbacks(t(), :default | [String.t() | map(), ...]) :: t()

Sets fallbacks — server-side retry of a refused request on another model (beta; declares server-side-fallback-2026-07-01).

  • :default — the API picks the recommended fallback for the refusal category.
  • a non-empty list — tried in order; a model string becomes %{"model" => model}, a map is sent unchanged (it may override max_tokens, thinking, output_config and speed for that attempt).

The API allows up to three entries, each distinct and listed in the requested model's allowed_fallback_models; those rules are left to it. Not supported by the Message Batches API (the item errors). Not sent by Claudio.Messages.count_tokens/2 when given a Request (that endpoint rejects it). See Claudio.Messages.Response for the fallback block, Response.served_by/1 and usage.iterations.

set_inference_geo(request, geo)

@spec set_inference_geo(t(), :global | :us) :: t()

Sets inference_geo — where the request is processed (:global or :us; GA, no beta). Without it the workspace default applies. :us is billed at 1.1× standard pricing. Not sent by Claudio.Messages.count_tokens/2 when given a Request (that endpoint rejects it). The response's usage.inference_geo reports where it ran.

set_max_tokens(request, max_tokens)

@spec set_max_tokens(t(), integer()) :: t()

Sets the maximum number of tokens to generate.

Example

Request.new("claude-opus-5-5")
|> Request.set_max_tokens(1024)

set_metadata(request, metadata)

@spec set_metadata(t(), map()) :: t()

Sets request metadata.

Example

Request.new("claude-opus-5-5")
|> Request.set_metadata(%{"user_id" => "123"})

set_output_config(request, config)

@spec set_output_config(t(), map()) :: t()

Sets the raw output_config map.

output_config is the API container for output controls (format, and on supported models effort / task_budget). This replaces the whole map — calling it after set_effort/2, set_task_budget/3 or set_output_format/2 discards what they set. Prefer those helpers; they merge.

Example

Request.new("claude-opus-4-8")
|> Request.set_output_config(%{"effort" => "high"})

set_output_format(request, schema)

@spec set_output_format(t(), map()) :: t()

Requests structured JSON output matching schema (a JSON Schema map).

Sets output_config.format to {type: "json_schema", schema: schema}, merging into any existing output_config (so a prior set_output_config/2 survives). GA — no beta header. The schema must use "additionalProperties" => false and list its "required" keys. Not compatible with document citations.

Example

Request.new("claude-opus-4-8")
|> Request.set_output_format(%{
  "type" => "object",
  "properties" => %{"name" => %{"type" => "string"}},
  "required" => ["name"],
  "additionalProperties" => false
})

set_service_tier(request, tier)

@spec set_service_tier(t(), String.t()) :: t()

Sets service tier for capacity selection.

Options:

  • "auto" - Automatically select based on availability
  • "standard_only" - Only use standard tier capacity

Example

Request.new("claude-opus-5-5")
|> Request.set_service_tier("auto")

set_speed(request, speed)

@spec set_speed(t(), :fast | :standard) :: t()

Sets speed (:fast or :standard). Fast mode is an access-gated research preview. Always declares the fast-mode-2026-02-01 beta — the API rejects the speed field without it, even for :standard. The response's usage.speed reports the speed used.

set_stop_sequences(request, sequences)

@spec set_stop_sequences(t(), [String.t()]) :: t()

Sets custom stop sequences.

Example

Request.new("claude-opus-5-5")
|> Request.set_stop_sequences(["END", "STOP"])

set_system(request, system)

@spec set_system(t(), String.t() | list()) :: t()

Sets the system prompt.

Can be a string or a list of content blocks with optional cache_control.

Examples

# Simple string
Request.new("claude-opus-5-5")
|> Request.set_system("You are a helpful assistant")

# With prompt caching
Request.new("claude-opus-5-5")
|> Request.set_system([
  %{
    "type" => "text",
    "text" => "Long system prompt here...",
    "cache_control" => %{"type" => "ephemeral"}
  }
])

set_system_with_cache(request, text, opts \\ [])

@spec set_system_with_cache(t(), String.t(), keyword()) :: t()

Sets the system prompt with prompt caching enabled.

Options

  • :ttl - Cache duration, either "5m" (default) or "1h"

Example

Request.new("claude-opus-5-5")
|> Request.set_system_with_cache("Long system prompt...", ttl: "1h")

set_task_budget(request, total, opts \\ [])

@spec set_task_budget(t(), pos_integer(), keyword()) :: t()

Sets an advisory token budget for the whole task (output_config.task_budget = %{"type" => "tokens", "total" => total}) and declares the task-budgets-2026-03-13 beta. Merges into output_config; calling it again replaces the budget. max_tokens stays the hard cap.

total must be a positive integer (the API enforces its own minimum, 20,000 as of 2026-09). Options:

  • :remaining — tokens left when carrying a budget across requests (non-negative integer; the API defaults it to total).

Example

Request.new("claude-opus-5-5")
|> Request.set_task_budget(64_000, remaining: 40_000)

set_temperature(request, temperature)

@spec set_temperature(t(), float()) :: t()

Sets the temperature (0.0-1.0).

Example

Request.new("claude-haiku-4-5")
|> Request.set_temperature(0.7)

Sampling parameters return 400 on Claude Opus 4.7+, Opus 5.x, Sonnet 5 and Fable models; use them only with models that accept them (e.g. Claude Haiku 4.5).

set_thinking_block_binding(request, behavior)

@spec set_thinking_block_binding(t(), :error | :drop_block) :: t()

Sets thinking.block_binding.prefix_mismatch_behavior (:error or :drop_block) on the thinking config already set — adaptive or a raw enable_thinking/2 "enabled" map — and declares thinking-binding-controls-2026-08-01. Raises if no thinking config is set. A later thinking setter replaces the whole map (the beta stays declared). The API rejects block_binding on "disabled" thinking.

:error rejects a request whose thinking block no longer matches the conversation prefix it was produced under (400); :drop_block drops that block and every later thinking block and reports it in Response.input_transformations. Unset, accounts created on/after 2026-08-31 behave as :error and older accounts are not enforced — set it explicitly to get the same behavior everywhere.

Example

Request.new("claude-sonnet-4-6")
|> Request.enable_thinking(%{"type" => "enabled", "budget_tokens" => 2048})
|> Request.set_thinking_block_binding(:drop_block)

set_tool_choice(request, other)

@spec set_tool_choice(t(), tool_choice()) :: t()

Sets tool choice strategy.

Example

Request.new("claude-opus-5-5")
|> Request.set_tool_choice(:auto)
|> Request.set_tool_choice(:any)
|> Request.set_tool_choice({:tool, "get_weather"})
|> Request.set_tool_choice(:none)

:any and {:tool, name} return 400 on Claude Fable 5.1, Mythos 5.1, Opus 5.5 and Sonnet 5.5. There, use :auto with a prompt instruction naming the tool, add_strict_tool/2 for schema-valid arguments, or set_output_format/2 when the forced call only existed to get JSON back.

set_top_k(request, top_k)

@spec set_top_k(t(), integer()) :: t()

Sets top_k for sampling from top K options.

Example

Request.new("claude-haiku-4-5")
|> Request.set_top_k(40)

Sampling parameters return 400 on Claude Opus 4.7+, Opus 5.x, Sonnet 5 and Fable models; use them only with models that accept them (e.g. Claude Haiku 4.5).

set_top_p(request, top_p)

@spec set_top_p(t(), float()) :: t()

Sets top_p for nucleus sampling (0.0-1.0).

Example

Request.new("claude-haiku-4-5")
|> Request.set_top_p(0.9)

Sampling parameters return 400 on Claude Opus 4.7+, Opus 5.x, Sonnet 5 and Fable models; use them only with models that accept them (e.g. Claude Haiku 4.5).

to_map(request)

@spec to_map(t()) :: map()

Converts the request to a map suitable for the API.