This page covers how Langflow persists, retrieves, and exposes chat messages and related monitoring data. It describes the Message schema, the MessageTable ORM model, the async memory functions in langflow.memory, the LCBuiltinChatMemory LangChain adapter, and the REST API surface under /monitor.
For how messages are rendered in the chat UI, see 5.10. For the database layer that backs all persistence, see 4.8. For the event streaming that delivers tokens to the frontend during a build, see 4.7.
The core schema types are defined in the lfx package and re-exported by langflow for backward compatibility.
src/backend/base/langflow/schema/message.py1-9
| Type | Origin | Role |
|---|---|---|
Message | lfx.schema.message | Full message object used internally during flow execution |
MessageResponse | lfx.schema.message | Serialized API response shape for a stored message |
ContentBlock | lfx.schema.message | A structured block of content within a message (text, tool use, etc.) |
ErrorMessage | lfx.schema.message | Subtype of Message that carries an error flag |
DefaultModel | lfx.schema.message | Base Pydantic model reused across the message schema |
A Message object requires the following fields before it can be stored:
session_id — identifies the conversation threadsender — role string (e.g., "User" or "AI")sender_name — display nametext — message body (may be a string or an async iterator during streaming)Optional fields include files, flow_id, context_id, properties, content_blocks, category, timestamp, and error.
Sources: src/backend/base/langflow/schema/message.py1-9 src/backend/base/langflow/services/database/models/message/model.py18-33
Diagram: MessageTable ORM Structure
Sources: src/backend/base/langflow/services/database/models/message/model.py18-197
MessageTable is the SQLAlchemy/SQLModel table (__tablename__ = "message"). It stores files, properties, and content_blocks as JSON columns.from_message() is a classmethod on MessageBase that converts a Message domain object into a MessageTable row. It handles:
session_id are trimmed to {session_id}/{relative_path}."".properties and content_blocks serialized via model_dump_json().MessageRead adds id and flow_id and is used as the return type from memory functions.MessageUpdate is used for partial PATCH operations via the API; setting a new text automatically triggers edit = True in the update endpoint logic.The message table has no foreign key to the flow table. This was intentionally removed via an Alembic migration to allow messages to survive flow deletion.
src/backend/base/langflow/alembic/versions/1b8b740a6fa3_remove_fk_constraint_in_message_.py147-187
All application code that needs to read or write messages should use the async functions exported from langflow.memory.
src/backend/base/langflow/memory.py1-387
Diagram: Memory Module — Function Call Flow
Sources: src/backend/base/langflow/memory.py48-265
| Function | Signature summary | Description |
|---|---|---|
aget_messages | (sender, sender_name, session_id, context_id, order_by, order, flow_id, limit) → list[Message] | Queries MessageTable with optional filters. Returns only non-error messages by default. |
aadd_messages | `(messages: Message | list[Message], flow_id) → list[Message]` |
astore_message | (message: Message, flow_id) → list[Message] | If message has an id that exists in the DB, updates it; otherwise inserts it. Validates that session_id, sender, and sender_name are all set. |
aupdate_messages | `(messages: Message | list[Message]) → list[Message]` |
adelete_messages | (session_id, context_id) → None | Deletes all messages matching a session_id or context_id. One of the two must be provided. |
delete_message | (id_: str) → None | Deletes a single message by UUID. |
aadd_messagetables | (messages: list[MessageTable], session, retry_count) → list[MessageRead] | Low-level insert. Contains retry logic (up to 3 times) for asyncio.CancelledError that can arise in certain execution paths (e.g., build_public_tmp). |
The sync variants (get_messages, add_messages, store_message, delete_messages) are marked deprecated and wrap the async versions via run_until_complete.
src/backend/base/langflow/memory.py48-87 src/backend/base/langflow/memory.py120-151 src/backend/base/langflow/memory.py301-337
_get_variable_query() builds a SQLModel select statement against MessageTable. It always filters error == False. Optional parameters narrow the result by sender, sender_name, session_id, context_id, flow_id, and limit. The default ordering is timestamp DESC.
src/backend/base/langflow/memory.py19-45
LCBuiltinChatMemory implements LangChain's BaseChatMessageHistory interface, bridging Langflow's storage layer to LangChain chains and agents that expect a standard chat history object.
src/backend/base/langflow/memory.py340-386
class LCBuiltinChatMemory(BaseChatMessageHistory):
flow_id: str
session_id: str
context_id: str | None
| Method | Behavior |
|---|---|
messages (property) | Calls get_messages(session_id, context_id), converts each Message to a LangChain BaseMessage via to_lc_message(), excludes errors. |
aget_messages() | Async version of the above. |
add_messages(messages) | Converts each LangChain BaseMessage via Message.from_lc_message(), calls store_message(). |
aadd_messages(messages) | Async version of the above. |
clear() / aclear() | Calls delete_messages() / adelete_messages() for the session and context. |
Note:
LCBuiltinChatMemoryis marked deprecated. It is retained for backward compatibility with LangChain-based components that construct memory objects directly.
Sources: src/backend/base/langflow/memory.py340-386
All message and monitoring endpoints are mounted under the /api/v1/monitor prefix. All routes require an authenticated user (get_current_active_user). Messages are scoped to the current user via a JOIN against the flow table, ensuring users only see their own data.
src/backend/base/langflow/api/v1/monitor.py1-211
Diagram: Monitor Router — Endpoints and Dependencies
Sources: src/backend/base/langflow/api/v1/monitor.py1-211
Messages
| Method | Path | Parameters | Returns |
|---|---|---|---|
GET | /monitor/messages | flow_id?, session_id?, sender?, sender_name?, order_by? | list[MessageResponse] |
GET | /monitor/messages/sessions | flow_id? | list[str] (distinct session IDs) |
DELETE | /monitor/messages | body: list[UUID] | 204 |
PUT | /monitor/messages/{message_id} | body: MessageUpdate | MessageRead |
PATCH | /monitor/messages/session/{old_session_id} | query: new_session_id | list[MessageResponse] |
DELETE | /monitor/messages/session/{session_id} | — | 204 |
The GET /monitor/messages endpoint filters messages through a JOIN on Flow.user_id == current_user.id, ensuring user isolation. The session_id query parameter is URL-decoded before use.
src/backend/base/langflow/api/v1/monitor.py66-99
The PUT /monitor/messages/{message_id} endpoint auto-sets edit = True when the text field is updated.
src/backend/base/langflow/api/v1/monitor.py110-134
Builds (VertexBuild)
| Method | Path | Parameters | Returns |
|---|---|---|---|
GET | /monitor/builds | flow_id (required) | VertexBuildMapModel |
DELETE | /monitor/builds | flow_id (required) | 204 |
VertexBuildMapModel groups VertexBuildTable records by vertex ID (a dict[str, list[VertexBuildTable]]).
src/backend/base/langflow/services/database/models/vertex_builds/model.py74-84
Transactions
| Method | Path | Parameters | Returns |
|---|---|---|---|
GET | /monitor/transactions | flow_id (required), pagination params | Page[TransactionLogsResponse] |
Transactions record per-vertex inputs and outputs during a build run. Sensitive values (API keys, passwords, tokens) are automatically masked by sanitize_data() in TransactionBase.__init__() before storage, and again during serialization.
src/backend/base/langflow/services/database/models/transactions/model.py113-133
Stores a record of each vertex execution within a flow run.
src/backend/base/langflow/services/database/models/transactions/model.py113-159
| Field | Type | Description |
|---|---|---|
id | UUID | Primary key |
flow_id | UUID | The flow this transaction belongs to |
vertex_id | str | The vertex that was executed |
target_id | `str | None` |
inputs | `dict | None` |
outputs | `dict | None` |
status | str | Execution status |
error | `str | None` |
timestamp | datetime | UTC timestamp |
TransactionLogsResponse is the read model returned by GET /monitor/transactions. It excludes error and flow_id to reduce noise in logs views.
Records each build attempt for a vertex within a flow.
src/backend/base/langflow/services/database/models/vertex_builds/model.py11-72
| Field | Type | Description |
|---|---|---|
build_id | UUID | Primary key |
id | str | Vertex ID |
flow_id | UUID | Owning flow |
job_id | `UUID | None` |
data | `dict | None` |
artifacts | `dict | None` |
params | `str | None` |
valid | bool | Whether the build succeeded |
timestamp | datetime | UTC timestamp |
Serializers on data, artifacts, and params enforce configurable maximum text length and item count to prevent unbounded storage growth.
Diagram: End-to-End Message Persistence Flow
Sources: src/backend/base/langflow/memory.py128-337 src/backend/base/langflow/api/v1/monitor.py66-99
Refresh this wiki
This wiki was recently refreshed. Please wait 3 days to refresh again.