ContentItem is the common typed unit for conversational and tool-interaction data. It represents Messages, ToolCalls, and ToolResults in both outbound requests and inbound responses, keeping the agent’s data model consistent. section 4.5.2 section 4.5.3
The communication layer uses ContentItem variants for:
- Messages containing user or assistant text. section 4.5.2
- ToolCalls recording requested tool names, identifiers, and arguments. section 4.5.4
- ToolResults recording executed tool output and its originating call linkage. section 4.5.4
ContentItems form the boundary between agent state and provider-specific API messages. LlmRequest selects and orders them, LlmClient translates them into API dictionaries, and LlmResponse returns provider output in the same standard form. section 4.5.1 section 4.5.4
A minimal request and response
An LlmRequest can contain a user Message asking “What is 2 + 2?”. After generation, LlmResponse.content contains an assistant Message with “4”. A tool-using response can instead contain an assistant Message and one or more ToolCalls, which are later paired with ToolResults. section 4.5.5 section 4.5.4
Listing 4.12 Building messages for the LLM API
def _build_messages(self, request: LlmRequest) -> List[dict]:
"""Convert LlmRequest to API message format."""
messages = []
for instruction in request.instructions:
messages.append({"role": "system", "content": instruction})
for item in request.contents:
if isinstance(item, Message):
messages.append({"role": item.role, "content": item.content})
elif isinstance(item, ToolCall):
tool_call_dict = {
"id": item.tool_call_id,
"type": "function",
"function": {
"name": item.name,
"arguments": json.dumps(item.arguments)
}
}
# Append to previous assistant message if exists
if messages and messages[-1]["role"] == "assistant":
messages[-1].setdefault("tool_calls", []).append(tool_call_dict)
else:
messages.append({
"role": "assistant",
"content": None,
"tool_calls": [tool_call_dict]
})
elif isinstance(item, ToolResult):
messages.append({
"role": "tool",
"tool_call_id": item.tool_call_id,
"content": str(item.content[0]) if item.content else ""
})
return messages
Inspect the conversion logic that preserves ContentItem semantics while combining assistant tool calls into provider-required message objects. section 4.5.4
