Skip to content
Discord

Retrieve Conversation Stream

client.conversations.messages.stream(stringconversationID, MessageStreamParams { agent_id, batch_size, include_pings, 4 more } body?, RequestOptionsoptions?): MessageStreamResponse | Stream<LettaStreamingResponse>
POST/v1/conversations/{conversation_id}/stream

Resume the stream for the most recent active run in a conversation.

This endpoint allows you to reconnect to an active background stream for a conversation, enabling recovery from network interruptions.

Agent-direct mode: Pass conversation_id=“default” with agent_id in request body to retrieve the stream for the agent’s most recent active run.

Direct run access: Pass run_id directly to skip run lookup entirely. Useful for recovery from duplicate request 409 errors.

OTID lookup: Pass otid to look up the run_id from Redis. Useful when you have the otid from a 409 error response.

Deprecated: Passing an agent ID as conversation_id still works but will be removed.

ParametersExpand Collapse
conversationID: string

The conversation identifier. Can be a conversation ID (‘conv-’), ‘default’ for agent-direct mode (with agent_id parameter), or an agent ID (‘agent-’) for backwards compatibility (deprecated).

minLength1
maxLength42
body: MessageStreamParams { agent_id, batch_size, include_pings, 4 more }
agent_id?: string | null

Agent ID for agent-direct mode with ‘default’ conversation. Use with conversation_id=‘default’ in the URL path.

batch_size?: number | null

Number of entries to read per batch.

include_pings?: boolean | null

Whether to include periodic keepalive ping messages in the stream to prevent connection timeouts.

otid?: string | null

Offline threading ID to look up the run_id. Bypasses active run lookup if run_id not provided.

poll_interval?: number | null

Seconds to wait between polls when no new data.

run_id?: string | null

Run ID to stream directly, bypassing run lookup. Use for recovery from duplicate requests.

starting_after?: number

Sequence id to use as a cursor for pagination. Response will start streaming after this chunk sequence id

ReturnsExpand Collapse
MessageStreamResponse = unknown
LettaStreamingResponse = SystemMessage { id, content, date, 8 more } | UserMessage { id, content, date, 8 more } | ReasoningMessage { id, date, reasoning, 10 more } | 10 more

Streaming response type for Server-Sent Events (SSE) endpoints. Each event in the stream will be one of these types.

One of the following:
SystemMessage { id, content, date, 8 more }

A message generated by the system. Never streamed back on a response, only used for cursor pagination.

Args: id (str): The ID of the message date (datetime): The date the message was created in ISO format name (Optional[str]): The name of the sender of the message content (str): The message content sent by the system

id: string
content: string

The message content sent by the system

date: string
is_err?: boolean | null
message_type?: "system_message"

The type of the message.

name?: string | null
otid?: string | null

The offline threading id (OTID). Set by the client to deduplicate requests. Used for idempotency in background streaming mode — each message in a request must have a unique OTID. Retries of the same request should reuse the same OTIDs.

run_id?: string | null
sender_id?: string | null
seq_id?: number | null
step_id?: string | null
UserMessage { id, content, date, 8 more }

A message sent by the user. Never streamed back on a response, only used for cursor pagination.

Args: id (str): The ID of the message date (datetime): The date the message was created in ISO format name (Optional[str]): The name of the sender of the message content (Union[str, List[LettaUserMessageContentUnion]]): The message content sent by the user (can be a string or an array of multi-modal content parts)

id: string
content: Array<LettaUserMessageContentUnion> | string

The message content sent by the user (can be a string or an array of multi-modal content parts)

One of the following:
TextContent { text, signature, type }
text: string

The text content of the message.

signature?: string | null

Stores a unique identifier for any reasoning associated with this text content.

type?: "text"

The type of the message.

ImageContent { source, type }
source: URLImage { url, type } | Base64Image { data, media_type, detail, type } | LettaImage { file_id, data, detail, 2 more }

The source of the image.

One of the following:
URLImage { url, type }
url: string

The URL of the image.

type?: "url"

The source type for the image.

Base64Image { data, media_type, detail, type }
data: string

The base64 encoded image data.

media_type: string

The media type for the image.

detail?: string | null

What level of detail to use when processing and understanding the image (low, high, or auto to let the model decide)

type?: "base64"

The source type for the image.

LettaImage { file_id, data, detail, 2 more }
file_id: string

The unique identifier of the image file persisted in storage.

data?: string | null

The base64 encoded image data.

detail?: string | null

What level of detail to use when processing and understanding the image (low, high, or auto to let the model decide)

media_type?: string | null

The media type for the image.

type?: "letta"

The source type for the image.

type?: "image"

The type of the message.

string
date: string
is_err?: boolean | null
message_type?: "user_message"

The type of the message.

name?: string | null
otid?: string | null

The offline threading id (OTID). Set by the client to deduplicate requests. Used for idempotency in background streaming mode — each message in a request must have a unique OTID. Retries of the same request should reuse the same OTIDs.

run_id?: string | null
sender_id?: string | null
seq_id?: number | null
step_id?: string | null
ReasoningMessage { id, date, reasoning, 10 more }

Representation of an agent’s internal reasoning.

Args: id (str): The ID of the message date (datetime): The date the message was created in ISO format name (Optional[str]): The name of the sender of the message source (Literal[“reasoner_model”, “non_reasoner_model”]): Whether the reasoning content was generated natively by a reasoner model or derived via prompting reasoning (str): The internal reasoning of the agent signature (Optional[str]): The model-generated signature of the reasoning step

id: string
date: string
reasoning: string
is_err?: boolean | null
message_type?: "reasoning_message"

The type of the message.

name?: string | null
otid?: string | null

The offline threading id (OTID). Set by the client to deduplicate requests. Used for idempotency in background streaming mode — each message in a request must have a unique OTID. Retries of the same request should reuse the same OTIDs.

run_id?: string | null
sender_id?: string | null
seq_id?: number | null
signature?: string | null
source?: "reasoner_model" | "non_reasoner_model"
One of the following:
"reasoner_model"
"non_reasoner_model"
step_id?: string | null
HiddenReasoningMessage { id, date, state, 9 more }

Representation of an agent’s internal reasoning where reasoning content has been hidden from the response.

Args: id (str): The ID of the message date (datetime): The date the message was created in ISO format name (Optional[str]): The name of the sender of the message state (Literal[“redacted”, “omitted”]): Whether the reasoning content was redacted by the provider or simply omitted by the API hidden_reasoning (Optional[str]): The internal reasoning of the agent

id: string
date: string
state: "redacted" | "omitted"
One of the following:
"redacted"
"omitted"
hidden_reasoning?: string | null
is_err?: boolean | null
message_type?: "hidden_reasoning_message"

The type of the message.

name?: string | null
otid?: string | null

The offline threading id (OTID). Set by the client to deduplicate requests. Used for idempotency in background streaming mode — each message in a request must have a unique OTID. Retries of the same request should reuse the same OTIDs.

run_id?: string | null
sender_id?: string | null
seq_id?: number | null
step_id?: string | null
ToolCallMessage { id, date, tool_call, 9 more }

A message representing a request to call a tool (generated by the LLM to trigger tool execution).

Args: id (str): The ID of the message date (datetime): The date the message was created in ISO format name (Optional[str]): The name of the sender of the message tool_call (Union[ToolCall, ToolCallDelta]): The tool call

id: string
date: string
Deprecatedtool_call: ToolCall { arguments, name, tool_call_id } | ToolCallDelta { arguments, name, tool_call_id }
One of the following:
ToolCall { arguments, name, tool_call_id }
arguments: string
name: string
tool_call_id: string
ToolCallDelta { arguments, name, tool_call_id }
arguments?: string | null
name?: string | null
tool_call_id?: string | null
is_err?: boolean | null
message_type?: "tool_call_message"

The type of the message.

name?: string | null
otid?: string | null

The offline threading id (OTID). Set by the client to deduplicate requests. Used for idempotency in background streaming mode — each message in a request must have a unique OTID. Retries of the same request should reuse the same OTIDs.

run_id?: string | null
sender_id?: string | null
seq_id?: number | null
step_id?: string | null
tool_calls?: Array<ToolCall { arguments, name, tool_call_id } > | ToolCallDelta { arguments, name, tool_call_id } | null
One of the following:
Array<ToolCall { arguments, name, tool_call_id } >
arguments: string
name: string
tool_call_id: string
ToolCallDelta { arguments, name, tool_call_id }
arguments?: string | null
name?: string | null
tool_call_id?: string | null
ToolReturnMessage { id, date, status, 13 more }

A message representing the return value of a tool call (generated by Letta executing the requested tool).

Args: id (str): The ID of the message date (datetime): The date the message was created in ISO format name (Optional[str]): The name of the sender of the message tool_return (str): The return value of the tool (deprecated, use tool_returns) status (Literal[“success”, “error”]): The status of the tool call (deprecated, use tool_returns) tool_call_id (str): A unique identifier for the tool call that generated this message (deprecated, use tool_returns) stdout (Optional[List(str)]): Captured stdout (e.g. prints, logs) from the tool invocation (deprecated, use tool_returns) stderr (Optional[List(str)]): Captured stderr from the tool invocation (deprecated, use tool_returns) tool_returns (Optional[List[ToolReturn]]): List of tool returns for multi-tool support

id: string
date: string
Deprecatedstatus: "success" | "error"
One of the following:
"success"
"error"
Deprecatedtool_call_id: string
Deprecatedtool_return: string
is_err?: boolean | null
message_type?: "tool_return_message"

The type of the message.

name?: string | null
otid?: string | null

The offline threading id (OTID). Set by the client to deduplicate requests. Used for idempotency in background streaming mode — each message in a request must have a unique OTID. Retries of the same request should reuse the same OTIDs.

run_id?: string | null
sender_id?: string | null
seq_id?: number | null
Deprecatedstderr?: Array<string> | null
Deprecatedstdout?: Array<string> | null
step_id?: string | null
tool_returns?: Array<ToolReturn { status, tool_call_id, tool_return, 3 more } > | null
status: "success" | "error"
One of the following:
"success"
"error"
tool_call_id: string
tool_return: Array<TextContent { text, signature, type } | ImageContent { source, type } > | string

The tool return value - either a string or list of content parts (text/image)

One of the following:
Array<TextContent { text, signature, type } | ImageContent { source, type } >
TextContent { text, signature, type }
text: string

The text content of the message.

signature?: string | null

Stores a unique identifier for any reasoning associated with this text content.

type?: "text"

The type of the message.

ImageContent { source, type }
source: URLImage { url, type } | Base64Image { data, media_type, detail, type } | LettaImage { file_id, data, detail, 2 more }

The source of the image.

One of the following:
URLImage { url, type }
url: string

The URL of the image.

type?: "url"

The source type for the image.

Base64Image { data, media_type, detail, type }
data: string

The base64 encoded image data.

media_type: string

The media type for the image.

detail?: string | null

What level of detail to use when processing and understanding the image (low, high, or auto to let the model decide)

type?: "base64"

The source type for the image.

LettaImage { file_id, data, detail, 2 more }
file_id: string

The unique identifier of the image file persisted in storage.

data?: string | null

The base64 encoded image data.

detail?: string | null

What level of detail to use when processing and understanding the image (low, high, or auto to let the model decide)

media_type?: string | null

The media type for the image.

type?: "letta"

The source type for the image.

type?: "image"

The type of the message.

string
stderr?: Array<string> | null
stdout?: Array<string> | null
type?: "tool"

The message type to be created.

AssistantMessage { id, content, date, 8 more }

A message sent by the LLM in response to user input. Used in the LLM context.

Args: id (str): The ID of the message date (datetime): The date the message was created in ISO format name (Optional[str]): The name of the sender of the message content (Union[str, List[LettaAssistantMessageContentUnion]]): The message content sent by the agent (can be a string or an array of content parts)

id: string
content: Array<LettaAssistantMessageContentUnion { text, signature, type } > | string

The message content sent by the agent (can be a string or an array of content parts)

One of the following:
Array<LettaAssistantMessageContentUnion { text, signature, type } >
text: string

The text content of the message.

signature?: string | null

Stores a unique identifier for any reasoning associated with this text content.

type?: "text"

The type of the message.

string
date: string
is_err?: boolean | null
message_type?: "assistant_message"

The type of the message.

name?: string | null
otid?: string | null

The offline threading id (OTID). Set by the client to deduplicate requests. Used for idempotency in background streaming mode — each message in a request must have a unique OTID. Retries of the same request should reuse the same OTIDs.

run_id?: string | null
sender_id?: string | null
seq_id?: number | null
step_id?: string | null
ApprovalRequestMessage { id, date, tool_call, 9 more }

A message representing a request for approval to call a tool (generated by the LLM to trigger tool execution).

Args: id (str): The ID of the message date (datetime): The date the message was created in ISO format name (Optional[str]): The name of the sender of the message tool_call (ToolCall): The tool call

id: string
date: string
Deprecatedtool_call: ToolCall { arguments, name, tool_call_id } | ToolCallDelta { arguments, name, tool_call_id }

The tool call that has been requested by the llm to run

One of the following:
ToolCall { arguments, name, tool_call_id }
arguments: string
name: string
tool_call_id: string
ToolCallDelta { arguments, name, tool_call_id }
arguments?: string | null
name?: string | null
tool_call_id?: string | null
is_err?: boolean | null
message_type?: "approval_request_message"

The type of the message.

name?: string | null
otid?: string | null

The offline threading id (OTID). Set by the client to deduplicate requests. Used for idempotency in background streaming mode — each message in a request must have a unique OTID. Retries of the same request should reuse the same OTIDs.

run_id?: string | null
sender_id?: string | null
seq_id?: number | null
step_id?: string | null
tool_calls?: Array<ToolCall { arguments, name, tool_call_id } > | ToolCallDelta { arguments, name, tool_call_id } | null

The tool calls that have been requested by the llm to run, which are pending approval

One of the following:
Array<ToolCall { arguments, name, tool_call_id } >
arguments: string
name: string
tool_call_id: string
ToolCallDelta { arguments, name, tool_call_id }
arguments?: string | null
name?: string | null
tool_call_id?: string | null
ApprovalResponseMessage { id, date, approval_request_id, 11 more }

A message representing a response form the user indicating whether a tool has been approved to run.

Args: id (str): The ID of the message date (datetime): The date the message was created in ISO format name (Optional[str]): The name of the sender of the message approve: (bool) Whether the tool has been approved approval_request_id: The ID of the approval request reason: (Optional[str]) An optional explanation for the provided approval status

id: string
date: string
Deprecatedapproval_request_id?: string | null

The message ID of the approval request

approvals?: Array<ApprovalReturn { approve, tool_call_id, reason, type } | ToolReturn { status, tool_call_id, tool_return, 3 more } > | null

The list of approval responses

One of the following:
ApprovalReturn { approve, tool_call_id, reason, type }
approve: boolean

Whether the tool has been approved

tool_call_id: string

The ID of the tool call that corresponds to this approval

reason?: string | null

An optional explanation for the provided approval status

type?: "approval"

The message type to be created.

ToolReturn { status, tool_call_id, tool_return, 3 more }
status: "success" | "error"
One of the following:
"success"
"error"
tool_call_id: string
tool_return: Array<TextContent { text, signature, type } | ImageContent { source, type } > | string

The tool return value - either a string or list of content parts (text/image)

One of the following:
Array<TextContent { text, signature, type } | ImageContent { source, type } >
TextContent { text, signature, type }
text: string

The text content of the message.

signature?: string | null

Stores a unique identifier for any reasoning associated with this text content.

type?: "text"

The type of the message.

ImageContent { source, type }
source: URLImage { url, type } | Base64Image { data, media_type, detail, type } | LettaImage { file_id, data, detail, 2 more }

The source of the image.

One of the following:
URLImage { url, type }
url: string

The URL of the image.

type?: "url"

The source type for the image.

Base64Image { data, media_type, detail, type }
data: string

The base64 encoded image data.

media_type: string

The media type for the image.

detail?: string | null

What level of detail to use when processing and understanding the image (low, high, or auto to let the model decide)

type?: "base64"

The source type for the image.

LettaImage { file_id, data, detail, 2 more }
file_id: string

The unique identifier of the image file persisted in storage.

data?: string | null

The base64 encoded image data.

detail?: string | null

What level of detail to use when processing and understanding the image (low, high, or auto to let the model decide)

media_type?: string | null

The media type for the image.

type?: "letta"

The source type for the image.

type?: "image"

The type of the message.

string
stderr?: Array<string> | null
stdout?: Array<string> | null
type?: "tool"

The message type to be created.

Deprecatedapprove?: boolean | null

Whether the tool has been approved

is_err?: boolean | null
message_type?: "approval_response_message"

The type of the message.

name?: string | null
otid?: string | null

The offline threading id (OTID). Set by the client to deduplicate requests. Used for idempotency in background streaming mode — each message in a request must have a unique OTID. Retries of the same request should reuse the same OTIDs.

Deprecatedreason?: string | null

An optional explanation for the provided approval status

run_id?: string | null
sender_id?: string | null
seq_id?: number | null
step_id?: string | null
LettaPing { id, date, is_err, 7 more }

A ping message used as a keepalive to prevent SSE streams from timing out during long running requests.

Args: id (str): The ID of the message date (datetime): The date the message was created in ISO format

id: string
date: string
is_err?: boolean | null
message_type?: "ping"

The type of the message. Ping messages are a keep-alive to prevent SSE streams from timing out during long running requests.

name?: string | null
otid?: string | null

The offline threading id (OTID). Set by the client to deduplicate requests. Used for idempotency in background streaming mode — each message in a request must have a unique OTID. Retries of the same request should reuse the same OTIDs.

run_id?: string | null
sender_id?: string | null
seq_id?: number | null
step_id?: string | null
LettaErrorMessage { error_type, message, message_type, 3 more }

Error messages are used to notify the client of an error that occurred during the agent’s execution.

error_type: string

The type of error.

message: string

The error message.

message_type: "error_message"

The type of the message.

run_id: string

The ID of the run.

detail?: string

An optional error detail.

seq_id?: number

The sequence ID for cursor-based pagination.

LettaStopReason { stop_reason, message_type }

The stop reason from Letta indicating why agent loop stopped execution.

stop_reason: StopReasonType

The reason why execution stopped.

One of the following:
"end_turn"
"error"
"llm_api_error"
"invalid_llm_response"
"invalid_tool_call"
"max_steps"
"max_tokens_exceeded"
"no_tool_call"
"tool_rule"
"cancelled"
"insufficient_credits"
"requires_approval"
"context_window_overflow_in_system_prompt"
message_type?: "stop_reason"

The type of the message.

LettaUsageStatistics { cache_write_tokens, cached_input_tokens, completion_tokens, 7 more }

Usage statistics for the agent interaction.

Attributes: completion_tokens (int): The number of tokens generated by the agent. prompt_tokens (int): The number of tokens in the prompt. total_tokens (int): The total number of tokens processed by the agent. step_count (int): The number of steps taken by the agent. cached_input_tokens (Optional[int]): The number of input tokens served from cache. None if not reported. cache_write_tokens (Optional[int]): The number of input tokens written to cache. None if not reported. reasoning_tokens (Optional[int]): The number of reasoning/thinking tokens generated. None if not reported.

cache_write_tokens?: number | null

The number of input tokens written to cache (Anthropic only). None if not reported by provider.

cached_input_tokens?: number | null

The number of input tokens served from cache. None if not reported by provider.

completion_tokens?: number

The number of tokens generated by the agent.

context_tokens?: number | null

Estimate of tokens currently in the context window.

message_type?: "usage_statistics"
prompt_tokens?: number

The number of tokens in the prompt.

reasoning_tokens?: number | null

The number of reasoning/thinking tokens generated. None if not reported by provider.

run_ids?: Array<string> | null

The background task run IDs associated with the agent interaction

step_count?: number

The number of steps taken by the agent.

total_tokens?: number

The total number of tokens processed by the agent.

Retrieve Conversation Stream

import Letta from '@letta-ai/letta-client';

const client = new Letta({
  apiKey: process.env['LETTA_API_KEY'], // This is the default and can be omitted
});

const response = await client.conversations.messages.stream('default');

console.log(response);
{}
Returns Examples
{}