# `Alloy.Message`
[🔗](https://github.com/alloy-ex/alloy/blob/v0.10.1/lib/alloy/message.ex#L1)

Normalized message struct used throughout Alloy.

All providers translate their wire format to/from this struct.
Internal format uses content blocks (similar to Anthropic's API)
since it's the most expressive.

## Content Block Types

### Text and tool blocks
- `%{type: "text", text: "..."}` - Plain text
- `%{type: "tool_use", id: "...", name: "...", input: %{}}` - Tool call from assistant
- `%{type: "tool_result", tool_use_id: "...", content: "..."}` - Tool execution result

### Media blocks (pass-through — providers map these to their wire format)
- `%{type: "image", mime_type: "image/jpeg", data: "base64..."}` - Inline image
- `%{type: "audio", mime_type: "audio/mp3", data: "base64..."}` - Inline audio
- `%{type: "video", mime_type: "video/mp4", data: "base64..."}` - Inline video
- `%{type: "document", mime_type: "application/pdf", uri: "..."}` - URI-referenced document

Alloy Core does not read, transcode, or base64-encode media. It expects callers
(e.g. Anvil connectors) to supply pre-encoded data or provider-specific URIs.

# `content_block`

```elixir
@type content_block() :: map()
```

# `role`

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

# `t`

```elixir
@type t() :: %Alloy.Message{content: String.t() | [content_block()], role: role()}
```

# `assistant`

```elixir
@spec assistant(String.t()) :: t()
```

Creates an assistant message with text content.

# `assistant_blocks`

```elixir
@spec assistant_blocks([content_block()]) :: t()
```

Creates an assistant message with content blocks (used for tool calls).

# `audio`

```elixir
@spec audio(String.t(), String.t()) :: content_block()
```

Creates an inline audio content block.

`mime_type` is typically `"audio/mp3"`, `"audio/wav"`, `"audio/ogg"`, etc.
`data` must be a base64-encoded string of the raw audio bytes.

# `document`

```elixir
@spec document(String.t(), String.t()) :: content_block()
```

Creates a URI-referenced document content block.

Used with provider APIs that require pre-uploaded files (e.g. Google File API).
`uri` is the provider-specific URI returned after uploading the file.

# `image`

```elixir
@spec image(String.t(), String.t()) :: content_block()
```

Creates an inline image content block.

`mime_type` should be one of `"image/jpeg"`, `"image/png"`, `"image/gif"`,
`"image/webp"`. `data` must be a base64-encoded string of the raw image bytes.

# `server_tool_result_block`

```elixir
@spec server_tool_result_block(String.t(), String.t(), boolean()) :: content_block()
```

Builds a server_tool_result content block (for code_execution server tool calls).

# `text`

```elixir
@spec text(t()) :: String.t()
```

Extracts plain text from a message, ignoring tool blocks.
Returns nil if no text content exists.

# `tool_calls`

```elixir
@spec tool_calls(t()) :: [content_block()]
```

Extracts tool_use blocks from an assistant message.

# `tool_result_block`

```elixir
@spec tool_result_block(String.t(), String.t(), boolean()) :: content_block()
```

Builds a tool_result content block.

# `tool_results`

```elixir
@spec tool_results([content_block()]) :: t()
```

Creates a user message containing tool results.

# `user`

```elixir
@spec user(String.t()) :: t()
```

Creates a user message with text content.

# `video`

```elixir
@spec video(String.t(), String.t()) :: content_block()
```

Creates an inline video content block.

`mime_type` is typically `"video/mp4"`, `"video/webm"`, etc.
`data` must be a base64-encoded string of the raw video bytes.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
