Skip to main content

Content Parts

Agent responses (and user messages) use content_parts to carry structured data alongside the plain content string. There are four types:

TypePurposeDetails
"text"A text segment of the responseMirrors content; used when the response interleaves text with other part types
"context"Documents/filters/tags the agent found or that the client attachedSee Passing Context
"tool"Tool execution lifecycle eventsDescribed below
"table"Structured tabular dataDescribed below

During streaming, content_parts grows with each SSE event as the agent progresses through tool calls and text generation.

Tool Content Parts

When an agent executes tools (search, sub-agents, custom functions), it streams tool execution state to the client via content_parts with type: "tool". This lets you build UIs that show what the agent is doing in real time — "Searching for documents...", "Analyzing results...", etc.

tip

Which tool calls are streamed to the client, and which fields (params, response, display_text) are included, is controlled by the agent's streaming tool events configuration.

Tool Lifecycle

Each tool call progresses through a lifecycle reflected in the status field:

running → completed
running → error

The agent streams a ContentPartTool for each state transition:

1. Running

When the agent decides to call a tool, it emits a tool content part with status: "running":

{
"type": "tool",
"tool": {
"tool_call_id": "call_abc123",
"name": "document_search",
"params": {"query": "What is BERT?"},
"display_text": "Searching for documents about BERT...",
"status": "running"
}
}

2. Completed

When the tool finishes successfully:

{
"type": "tool",
"tool": {
"tool_call_id": "call_abc123",
"name": "document_search",
"params": {"query": "What is BERT?"},
"response": {"document_ids": ["abc_0", "def_0"], "count": 2},
"display_text": "Found 2 documents about BERT",
"status": "completed"
}
}

3. Error

If the tool execution fails:

{
"type": "tool",
"tool": {
"tool_call_id": "call_abc123",
"name": "document_search",
"params": {"query": "What is BERT?"},
"display_text": null,
"status": "error"
}
}

ContentPartTool Fields

FieldTypeDescription
tool_call_idstringUnique identifier for this specific tool invocation
namestringThe tool that was called
paramsobject or nullVisible parameters (may be a subset of actual params, filtered by the tool's configuration)
responseobject or nullTool result (present only when status is "completed", may be filtered)
display_textstring or nullHuman-readable text describing what the tool is doing or did
status"running" / "completed" / "error"Current lifecycle state

Rendering in a UI

A typical pattern for rendering tool content parts during streaming:

import json
import sseclient

# ... set up streaming request ...

client = sseclient.SSEClient(response)
tool_states = {} # track by tool_call_id

for event in client.events():
message = json.loads(event.data)

for part in message.get("content_parts") or []:
if part["type"] != "tool":
continue

tool = part["tool"]
tool_id = tool["tool_call_id"]
status = tool.get("status")

if status == "running":
# Show a spinner or "in progress" indicator
print(f"⏳ {tool.get('display_text', tool['name'])}")
tool_states[tool_id] = "running"

elif status == "completed":
# Replace spinner with completion state
print(f"✓ {tool.get('display_text', tool['name'])}")
tool_states[tool_id] = "completed"

elif status == "error":
print(f"✗ {tool['name']} failed")
tool_states[tool_id] = "error"

UI Recommendations

  • Show display_text rather than raw name + params — it is formatted for human consumption.
  • Use tool_call_id to correlate running → completed/error transitions for the same call.
  • Multiple tool calls can run concurrently — track each by tool_call_id.
  • The params and response fields are optional and may contain filtered subsets. Use them for advanced UIs (e.g., showing search parameters or result previews) but don't depend on their presence.

Multiple Tool Calls

Agents may call multiple tools in parallel. Each tool has its own tool_call_id. In a single SSE event, you may see multiple tool content parts at different lifecycle stages:

{
"content_parts": [
{"type": "tool", "tool": {"tool_call_id": "call_1", "name": "search", "status": "completed", ...}},
{"type": "tool", "tool": {"tool_call_id": "call_2", "name": "summarize", "status": "running", ...}},
{"type": "text", "text": "Based on the search results..."}
]
}

Table Content Parts

Agents can also return structured tabular data via content_parts with type: "table". This is used when the response contains data best presented as a table rather than prose.

{
"type": "table",
"table": {
"format": "row",
"headers": ["Document", "Score", "Source"],
"rows": [
{"Document": "BERT: Pre-training of Deep Bidirectional Transformers", "Score": "0.95", "Source": "arXiv"},
{"Document": "Attention Is All You Need", "Score": "0.87", "Source": "arXiv"}
]
}
}

Table Formats

FormatShapeUse when
"row"rows: array of {header: value} objectsMost common — each row is a record
"columnar"columns: object mapping header → [values]Efficient for large uniform datasets

Exactly one of rows or columns is present. headers provides column ordering for rendering.