# Anthropic content blocks — request and response shapes **Status:** `DOCUMENTED`; `text`, `image`, `document`, `tool_use`, `tool_result`, `thinking` `LIVE_VERIFIED` 2026-09-18 (Haiku 4.5). Beta blocks `BETA`. **Sources:** https://platform.claude.com/docs/en/api/messages (Domain types) · https://platform.claude.com/docs/en/api/beta/messages · https://platform.claude.com/docs/en/build-with-claude/vision · https://platform.claude.com/docs/en/build-with-claude/pdf-support **Machine-readable:** `generated/fragments/objects/anthropic-messages-objects.json` (`ContentBlock:*`), `generated/fragments/parameters/anthropic-messages.json` (`messages[].content[].*`) **Last verified:** 2026-09-18 `messages[].content` is a string (shorthand for one `text` block) or an array of blocks. Every request block may carry `cache_control: {type: "ephemeral", ttl?: "5m"|"1h"}`. Response blocks come back in `Message.content[]` and must be replayed **verbatim** (thinking/redacted_thinking especially) in later turns. ## Request-side blocks (`ContentBlockParam`) | `type` | Fields | Notes | |---|---|---| | `text` | `text` (min 1 char), `citations?: TextCitationParam[]`, `cache_control?` | also the shape of `system[]` and of `search_result.content[]` | | `image` | `source`: `{type: base64, media_type: image/jpeg\|png\|gif\|webp, data}` \| `{type: url, url}` \| `{type: file, file_id}`; `transformations?: {oversized_image: downsize\|error}`; `cache_control?` | `downsize` (default) silently rescales; `error` → 400. count_tokens rejects `url`/`file` sources. *1×1 PNG = +5 tokens live* | | `document` | `source`: `{type: base64, media_type: application/pdf, data}` \| `{type: text, media_type: text/plain, data}` \| `{type: content, content: string \| (text\|image)[]}` \| `{type: url, url}` \| `{type: file, file_id}`; `title?`, `context?`, `citations?: {enabled: bool}`, `cache_control?` | citations type depends on source: PDF → `page_location`, text → `char_location`, content → `content_block_location`. *text doc + citations.enabled = 562 tokens vs 11 (fixed citation overhead)* | | `search_result` | `source` (string), `title`, `content: TextBlockParam[]`, `citations?: {enabled}`, `cache_control?` | your own RAG results; cited as `search_result_location` | | `thinking` | `thinking`, `signature` | replay unmodified, in order — modified → 400 "`thinking` or `redacted_thinking` blocks in the latest assistant message cannot be modified" | | `redacted_thinking` | `data` (opaque) | replay unchanged | | `tool_use` | `id` (toolu_…), `name`, `input` (object), `caller?`, `toolset_name?`, `cache_control?` | replayed assistant tool call | | `tool_result` | `tool_use_id`, `content?: string \| (text\|image\|search_result\|document\|tool_reference\|browser_state)[]`, `is_error?`, `toolset_name?`, `cache_control?` | must immediately follow, one per `tool_use`, alone in the user message. *Missing → 400 "messages.2: `tool_use` ids were found without `tool_result` blocks immediately after: …"* | | `server_tool_use` | `id` (srvtoolu_…), `name ∈ web_search\|web_fetch\|code_execution\|bash_code_execution\|text_editor_code_execution\|tool_search_tool_regex\|tool_search_tool_bm25` (+beta `advisor`), `input`, `caller?` | replayed server-tool call | | `web_search_tool_result` | `tool_use_id`, `content: web_search_result[] {url, title, encrypted_content, page_age}` \| `{type: web_search_tool_result_error, error_code}` | error codes: `invalid_tool_input`, `unavailable`, `max_uses_exceeded`, `too_many_requests`, `query_too_long`, `request_too_large` | | `web_fetch_tool_result` | `tool_use_id`, `content: {type: web_fetch_result, url, content: document, retrieved_at}` \| `{type: web_fetch_tool_result_error, error_code}` | error codes: `invalid_tool_input`, `url_too_long`, `url_not_allowed`, `url_not_in_prior_context`, `url_not_accessible`, `unsupported_content_type`, `too_many_requests`, `max_uses_exceeded`, `unavailable`, `content_too_large` | | `code_execution_tool_result` | `tool_use_id`, `content: {type: code_execution_result, stdout, stderr, return_code, content: [{type: code_execution_output, file_id}]}` \| error `{error_code}` | codes: `invalid_tool_input`, `unavailable`, `too_many_requests`, `execution_time_exceeded` (encrypted variant exists for ZDR) | | `bash_code_execution_tool_result` | `{type: bash_code_execution_result, stdout, stderr, return_code, content[]}` \| error | + `output_file_too_large` | | `text_editor_code_execution_tool_result` | view `{content, file_type, num_lines, start_line, total_lines}` · create `{is_file_update}` · str_replace `{lines, new_lines, new_start, old_lines, old_start}` \| error | + `file_not_found` | | `tool_search_tool_result` | `{type: tool_search_tool_search_result, tool_references: [{type: tool_reference, tool_name}]}` \| error | codes as code_execution | | `container_upload` | `file_id`, `cache_control?` | puts a Files-API file in the container input dir | | `tool_reference` | `tool_name` | only inside `tool_result.content` (tool search) | | `browser_state` | tabs/changes/screenshot | only inside `tool_result.content` (browser toolset 20260801) | | **beta** `mcp_tool_use` / `mcp_tool_result` | `{id, name, server_name, input}` / `{tool_use_id, is_error, content: string \| text[]}` | `mcp-client-2025-11-20` | | **beta** `advisor_tool_result` | `{tool_use_id, content: advisor_result \| advisor_redacted_result \| error}` | `advisor-tool-2026-03-01` | | **beta** `compaction` | `{content: string\|null, encrypted_content, signature}` | round-trip verbatim; null content = failed compaction (no-op); empty string not allowed | | **beta** `fallback` | `{from: {model}, to: {model}, trigger: {type: refusal}}` | boundary between declining model and fallback model | ## Response-side blocks (`ContentBlock`) Same names; differences: `text` gains `citations: TextCitation[]|null`; `tool_use` always has `caller` (*live `{type: "direct"}`*) and `toolset_name?`; `server_tool_use`/`web_*_tool_result` carry `caller`; `thinking` has `signature` filled; response never contains `image`/`document`/`search_result`/`tool_result` (those are inputs). GA response union (12): `text`, `thinking`, `redacted_thinking`, `tool_use`, `server_tool_use`, `web_search_tool_result`, `web_fetch_tool_result`, `code_execution_tool_result`, `bash_code_execution_tool_result`, `text_editor_code_execution_tool_result`, `tool_search_tool_result`, `container_upload`. Beta adds `mcp_tool_use`, `mcp_tool_result`, `advisor_tool_result`, `compaction`, `fallback`. ## Citations (`TextCitation` / `citations_delta`) | `type` | Fields | |---|---| | `char_location` | `cited_text`, `document_index`, `document_title`, `start_char_index`, `end_char_index`, `file_id?` | | `page_location` | …, `start_page_number` (≥1), `end_page_number` | | `content_block_location` | …, `start_block_index`, `end_block_index` (exclusive) — `cited_text` = concatenated whole blocks, not billed | | `web_search_result_location` | `cited_text`, `url`, `title`, `encrypted_index` | | `search_result_location` | `cited_text`, `source`, `title`, `search_result_index`, `start_block_index`, `end_block_index` | ## Caller `caller: {type: "direct"}` (model called the tool) or `{type: "code_execution_20250825" | "code_execution_20260120", tool_id: "srvtoolu_…"}` (programmatic tool calling from inside the container).