---
sidebar:
  hidden: true
title: roboto.ai.core.content
---
Message-content primitive value types shared across the `roboto.ai` layer.

These are the leaf building blocks of [`AgentMessage.content`](/docs/reference/python-sdk/roboto/ai/core#roboto.ai.core.AgentMessage.content). They live here — below both [`roboto.ai.core.record`](/docs/reference/python-sdk/roboto/ai/core/record) and [`roboto.ai.goals`](/docs/reference/python-sdk/roboto/ai/goals) — so the goals layer can reference the raw tool-call blocks (to carry them on a [`GoalResult`](/docs/reference/python-sdk/roboto/ai/goals#roboto.ai.goals.GoalResult)) without importing from `core.record`. That keeps the `roboto.ai` &#105;mport graph a DAG: `core.content` depends only on [`roboto.ai.core.context`](/docs/reference/python-sdk/roboto/ai/core/context) (itself a leaf with no `roboto.ai` imports of its own); `goals` and `core.record` both depend down onto `core.content`.

## Module Contents

### AGENT_CONTENT_MODEL_BY_TYPE

```python
roboto.ai.core.content.AGENT_CONTENT_MODEL_BY_TYPE: dict[AgentContentType, type[AgentContent]]
```

`from roboto.ai.agent_thread import AGENT_CONTENT_MODEL_BY_TYPE`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/ai/core/content.py#L275-L282)

The model class for each JSON-serialized content type, keyed by discriminator.

Excludes [`AgentContentType.TEXT`](/reference/python-sdk/roboto/ai/core/content#roboto.ai.core.content.AgentContentType.TEXT), whose payload is persisted as raw text rather than a serialized model. Every other member of [`AgentContent`](/reference/python-sdk/roboto/ai/core/content#roboto.ai.core.content.AgentContent) carries a `content_type` discriminator and round-trips through `model_dump_json` / `model_validate_json`; driving both serialization directions off this one map keeps them symmetric, so a member added to the union without a home here fails loudly instead of being silently dropped on write or reconstructed without its payload on read.

### AgentClientContextEntry

```python
class roboto.ai.core.content.AgentClientContextEntry(/, **data: Any)
```

`from roboto.ai.agent_thread import AgentClientContextEntry`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/ai/core/content.py#L243-L260)

Bases: `pydantic.BaseModel`

The caller's attached viewing context, carried on their own message.

Replaces a `<ctx>{json}</ctx>` marker persisted as a separate ROBOTO-role message. That shape made every consumer regex a JSON blob back out of prose it had serialized itself -- four parsers across two languages -- and relied on the ROBOTO role to keep the marker out of the chat view. It also put the context on a non-USER message, which the compression deletion pass collapses wholesale inside a resolved task's interior, so the context silently disappeared from compressed history.

As a block on the user's own message it is a typed field, invisible to text renderers (no `text` field), and safe from that collapse -- USER turns are never dropped.

**Parameters**

- **data** (`Any`)

**Attributes**

- **AgentClientContextEntry.content_type** (`Literal[AgentContentType]`)
- **AgentClientContextEntry.context** (`roboto.ai.core.context.ClientViewingContext`): What the caller had open: attached datasets, files, and visualizer state.

### AgentCompressionFillerContent

```python
class roboto.ai.core.content.AgentCompressionFillerContent(/, **data: Any)
```

`from roboto.ai.agent_thread import AgentCompressionFillerContent`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/ai/core/content.py#L228-L240)

Bases: `pydantic.BaseModel`

Filler standing in for a message the compression deletion pass emptied.

Carries no payload. A message reduced to nothing but tombstones keeps this single block instead of an empty content list, so it stays in the Bedrock payload at its original role and turn alternation survives without relocating content. The Bedrock boundary renders it as `<Deleted in compression>`. Produced only by the compression deletion pass and stored only at the `DELETED` tier; the verbatim `original` thread (what the SDK and UI render) never contains one.

**Parameters**

- **data** (`Any`)

**Attributes**

- **AgentCompressionFillerContent.content_type** (`Literal[AgentContentType]`)

### AgentContent

```python
type roboto.ai.core.content.AgentContent = AgentTextContent | AgentToolUseContent | AgentToolResultContent | AgentErrorContent | AgentDeletedContent | AgentCompressionFillerContent | AgentClientContextEntry
```

`from roboto.ai.agent_thread import AgentContent`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/ai/core/content.py#L263-L271)

Type alias for all possible content types within agent messages.

### AgentContentType

```python
class roboto.ai.core.content.AgentContentType
```

`from roboto.ai.agent_thread import AgentContentType`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/ai/core/content.py#L27-L69)

Bases: `roboto.compat.StrEnum`

Enumeration of different types of content within agent messages.

Defines the various content types that can be included in agent messages.

**Attributes**

- **AgentContentType.CLIENT_CONTEXT** = `'client_context'`: What the caller was looking at when they composed the message this block sits on.

  Superseded shape: the same payload used to be persisted as a whole ROBOTO-role message whose text was a `<ctx>...</ctx>` marker (ENG-2185). Readers still accept that form for threads written before this type existed; nothing emits it any more.

- **AgentContentType.COMPRESSION_FILLER** = `'compression_filler'`: Stand-in block kept in a message the deletion pass emptied entirely.

  A message reduced to nothing but tombstones would break user/assistant alternation if it dropped from the payload. Replacing its content with this single filler keeps the message — and its role — in place. The model sees it as `<Deleted in compression>`. Only the cross-message deletion pass produces it, so it appears only inside a `DELETED`-tier compressed variant, never in the verbatim `original` thread the SDK and UI read.

- **AgentContentType.DELETED** = `'deleted'`: Tombstone marking a content block elided by compression.

  Appears only inside a `DELETED`-tier compressed variant. Both producers — message-tier compression dropping a pure-filler text run, and the cross-message deletion pass dropping a whole tool exchange — store their output at the DELETED tier, so a message carrying one is always a DELETED-tier variant. Never in the verbatim `original` thread the SDK and UI read.

- **AgentContentType.ERROR** = `'error'`: Error information when message generation fails.

- **AgentContentType.TEXT** = `'text'`: Plain text content from users or AI responses.

- **AgentContentType.TOOL_RESULT** = `'tool_result'`: Results returned from tool executions.

- **AgentContentType.TOOL_USE** = `'tool_use'`: Tool invocation requests from the AI assistant.

### AgentDeletedContent

```python
class roboto.ai.core.content.AgentDeletedContent(/, **data: Any)
```

`from roboto.ai.agent_thread import AgentDeletedContent`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/ai/core/content.py#L211-L225)

Bases: `pydantic.BaseModel`

Tombstone for a content block removed by compression.

Carries no payload — its presence records that a block once occupied this slot, and it converts to `None` at the Bedrock boundary so the block drops from the LLM payload. Produced when compression drops a block — a pure-filler text run at message compression, or a whole redundant tool exchange in the cross-message deletion pass — and stored only at the `DELETED` tier, so a message carrying one is always a DELETED-tier variant. A message reduced to nothing but tombstones does not drop: it is replaced with a single [`AgentCompressionFillerContent`](/reference/python-sdk/roboto/ai/core/content#roboto.ai.core.content.AgentCompressionFillerContent) so it keeps its role and turn. The verbatim `original` thread (what the SDK and UI render) never contains one.

**Parameters**

- **data** (`Any`)

**Attributes**

- **AgentDeletedContent.content_type** (`Literal[AgentContentType]`)

### AgentErrorContent

```python
class roboto.ai.core.content.AgentErrorContent(/, **data: Any)
```

`from roboto.ai.agent_thread import AgentErrorContent`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/ai/core/content.py#L197-L208)

Bases: `pydantic.BaseModel`

Error content within an agent message.

Used when message generation fails due to an error or is cancelled by the user.

**Parameters**

- **data** (`Any`)

**Attributes**

- **AgentErrorContent.content_type** (`Literal[AgentContentType]`)
- **AgentErrorContent.error_code** (`str | None`) = `None`: Optional error code for programmatic handling.
- **AgentErrorContent.error_message** (`str`): User-friendly error message describing what went wrong.

### AgentTextContent

```python
class roboto.ai.core.content.AgentTextContent(/, **data: Any)
```

`from roboto.ai.agent_thread import AgentTextContent`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/ai/core/content.py#L72-L79)

Bases: `pydantic.BaseModel`

Text content within an agent message.

**Parameters**

- **data** (`Any`)

**Attributes**

- **AgentTextContent.text** (`str`): The actual text content of the message.

### AgentToolResultContent

```python
class roboto.ai.core.content.AgentToolResultContent(/, **data: Any)
```

`from roboto.ai.agent_thread import AgentToolResultContent`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/ai/core/content.py#L96-L139)

Bases: `pydantic.BaseModel`

Tool execution result content within an agent message.

**Parameters**

- **data** (`Any`)

**Attributes**

- **AgentToolResultContent.content_type** (`Literal[AgentContentType]`)

- **AgentToolResultContent.payload** (`str | dict[str, Any] | list[Any] | None`) = `None`: What the tool returned: free-form text, or a JSON object or array of structured data.

  Independent of any model provider's wire format (provider-agnostic, like [`AgentToolUseContent.input`](/reference/python-sdk/roboto/ai/core/content#roboto.ai.core.content.AgentToolUseContent.input)). `None` on results written before this field existed; use [`resolve_payload()`](/reference/python-sdk/roboto/ai/core/content#roboto.ai.core.content.AgentToolResultContent.resolve_payload) to read old and new results uniformly.

- **AgentToolResultContent.raw_response** (`dict[str, Any] | None`) = `None`: Legacy provider-formatted response envelope (Bedrock `toolResult` shape).

  Kept so results written before [`payload`](/reference/python-sdk/roboto/ai/core/content#roboto.ai.core.content.AgentToolResultContent.payload) existed remain readable; deprecated for new readers, who should call [`resolve_payload()`](/reference/python-sdk/roboto/ai/core/content#roboto.ai.core.content.AgentToolResultContent.resolve_payload) instead of parsing this field.

  Populated only where the server-side envelope is in scope: threads read over the API arrive with this field stripped (and, for legacy rows, with [`payload`](/reference/python-sdk/roboto/ai/core/content#roboto.ai.core.content.AgentToolResultContent.payload) synthesized from it server-side before the strip), so API/SDK readers should not expect it.

- **AgentToolResultContent.runtime_ms** (`int`): Wall-clock execution time of the tool in milliseconds.

- **AgentToolResultContent.status** (`str`): Outcome of the tool execution (e.g. 'success', 'error').

- **AgentToolResultContent.tool_name** (`str`): Name of the tool that was executed.

- **AgentToolResultContent.tool_use_id** (`str`): Identifier of the tool invocation this result corresponds to.

#### AgentToolResultContent.resolve_payload()

```python
def resolve_payload() -> Optional[Union[str, dict[str, Any], list[Any]]]
```

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/ai/core/content.py#L126-L139)

Return what the tool returned, whichever field carries it.

Prefers [`payload`](/reference/python-sdk/roboto/ai/core/content#roboto.ai.core.content.AgentToolResultContent.payload). Results written before that field existed carry only the legacy envelope, from which the equivalent value is reconstructed via [`synthesize_tool_result_payload()`](/reference/python-sdk/roboto/ai/core/content#roboto.ai.core.content.synthesize_tool_result_payload).

**Returns**

- `Optional[Union[str, dict[str, Any], list[Any]]]`: The tool's text or JSON output, or `None` when neither field carries a recognizable value.

### AgentToolUseContent

```python
class roboto.ai.core.content.AgentToolUseContent(/, **data: Any)
```

`from roboto.ai.agent_thread import AgentToolUseContent`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/ai/core/content.py#L82-L93)

Bases: `pydantic.BaseModel`

Tool usage request content within an agent message.

**Parameters**

- **data** (`Any`)

**Attributes**

- **AgentToolUseContent.content_type** (`Literal[AgentContentType]`)
- **AgentToolUseContent.input** (`dict[str, Any] | None`) = `None`: Parsed tool input parameters chosen by the LLM (provider-agnostic).
- **AgentToolUseContent.raw_request** (`dict[str, Any] | None`) = `None`: Raw, unparsed request payload for this tool invocation.
- **AgentToolUseContent.tool_name** (`str`): Name of the tool the LLM is requesting to invoke.
- **AgentToolUseContent.tool_use_id** (`str`): Unique identifier for this tool invocation, used to correlate with its result.

### synthesize_tool_result_payload()

```python
def roboto.ai.core.content.synthesize_tool_result_payload(
    raw_response: Optional[dict[str, Any]],
) -> Optional[Union[str, dict[str, Any], list[Any]]]
```

`from roboto.ai.core import synthesize_tool_result_payload`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/ai/core/content.py#L142-L194)

Reconstruct a tool result's text or JSON output from its legacy response envelope.

Reads both shapes tool results were persisted with before [`AgentToolResultContent.payload`](/reference/python-sdk/roboto/ai/core/content#roboto.ai.core.content.AgentToolResultContent.payload) existed:

- The provider envelope: a `toolResult` object whose `content` list carries the output as a `text` or `json` block, followed at most by image attachments.
- A bare output dict with no `toolResult` key at all — the shape client-submitted results and fabricated skill-invocation results persisted, where the dict *is* the tool's output and is returned as the payload verbatim.

A `json` value of the exact single-key form `{"items": [...]}` — the wrapper applied because the model provider rejected a top-level array — is unwrapped back to the bare array. This unwrap is heuristic: a tool that genuinely returned a single-key `{"items": [...]}` dict is indistinguishable from the wrapper here and synthesizes as the bare array. Writers that still hold the tool's true return value should persist [`AgentToolResultContent.payload`](/reference/python-sdk/roboto/ai/core/content#roboto.ai.core.content.AgentToolResultContent.payload) directly rather than round- tripping through this function.

**Parameters**

- **raw_response** (`Optional[dict[str, Any]]`): The legacy value, as carried by [`AgentToolResultContent.raw_response`](/reference/python-sdk/roboto/ai/core/content#roboto.ai.core.content.AgentToolResultContent.raw_response). `None` is accepted.

**Returns**

- `Optional[Union[str, dict[str, Any], list[Any]]]`: The tool's text or JSON output, or `None` when the value is absent, is a malformed envelope, or is an envelope carrying no text or JSON block.
