Eric Hare dfb34c7be4 fix(agent): scope chat history retrieval by flow_id to prevent cross-flow leak (#13087)
* fix(agent): scope chat history retrieval by flow_id to prevent cross-flow leak (#13059)

AgentComponent.get_memory_data filtered chat history by session_id only, so
the playground's default session names (e.g. "New Session 0") leaked
conversation history across unrelated flows whenever two flows happened to
use the same default name.

The fix replaces the ad-hoc MemoryComponent spawn (whose internal _vertex is
None and therefore cannot see the running flow's flow_id) with a direct
aget_messages call that passes flow_id from the agent's own graph context.
MemoryComponent.retrieve_messages is also updated to scope by self.graph.flow_id
when available, so the standalone Message History component does not have
the same leak.

Adds regression tests covering: UUID coercion of string flow_ids, isolation
of two flows that share a session name, graceful fallback when flow_id is
missing or non-UUID, untouched external-memory path, and filtering out the
current input message.

* fix(agent): preserve n_messages=0 disable-memory contract and apply scoping to Cuga

Review follow-up on #13087:

- AgentComponent.get_memory_data regressed n_messages=0: before this PR the
  call went through MemoryComponent.retrieve_messages which short-circuits to
  [] when n_messages==0. The direct aget_messages call lost that contract,
  because `if self.n_messages:` is falsy for 0 and `messages[-0:]` returns
  every message fetched under limit=10000.

- CugaComponent.get_memory_data had the same leak pattern (issue #13059)
  because it also spawned an ad-hoc MemoryComponent whose _vertex is None.

Extract aget_agent_chat_history(session_id, flow_id, context_id, n_messages)
into memory.py:
  * returns [] when n_messages == 0
  * coerces flow_id to UUID (gracefully falls back on invalid values)
  * applies n_messages slicing

Both AgentComponent and CugaComponent now route through it.

Tests:
  * aget_agent_chat_history: passes flow_id as UUID, short-circuits on
    n_messages=0, slices to most-recent N, returns all on n_messages=None,
    falls back to unscoped query on invalid flow_id.
  * AgentComponent integration: routes through helper with flow_id, filters
    out current input, n_messages=0 disables memory (asserts aget_messages
    is never awaited so a future regression resurfaces as a real DB call).
  * CugaComponent integration: scopes by flow_id, n_messages=0 disables
    memory. Module-import gated for envs without optional Cuga deps.

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* [autofix.ci] apply automated fixes

* Template update

* [autofix.ci] apply automated fixes

* Update .secrets.baseline

* [autofix.ci] apply automated fixes

* Update starter projects

* [autofix.ci] apply automated fixes

* Update .secrets.baseline

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

* fix(memory): address PR #13087 review — symmetric flow_id, DESC fetch, loud fallback

Addresses the review comments on PR #13087:

I1 (symmetric flow_id handling): `store_message` now routes the
internal-memory write through `_coerce_flow_id_to_uuid(_safe_graph_flow_id(self))`
instead of accessing `self.graph.flow_id` directly, so an ad-hoc /
custom-subclass MemoryComponent without `_vertex` no longer crashes
on the write half before reaching the safe read half. Both calls share
a single `flow_id_scope` variable.

I2 (>10k row ordering bug): both `aget_agent_chat_history` and
`MemoryComponent.retrieve_messages` (internal-memory branch) now query
in `DESC` order with `limit=n_messages` (falling back to
`MAX_CHAT_HISTORY_FETCH_LIMIT` when no explicit limit is set), then
reverse to the caller's preferred order. The previous ASC + slice shape
returned the chronological FIRST window once sessions exceeded 10k
rows, silently serving stale history.

I3 (loud fallback observability): when `_coerce_flow_id_to_uuid` is
forced to return `None` for a malformed `flow_id`, the log call is now
`logger.error` (was `warning`) and carries a structured `event` tag
(`memory_flow_id_unscoped`). The unbounded-fetch ceiling-hit path
emits a parallel `memory_chat_history_limit_reached` warning. Both
events are explicit alert hooks for observability pipelines so a
regression cannot silently re-enable the cross-flow leak that motivated
the PR.

R1 (magic number): extracted `MAX_CHAT_HISTORY_FETCH_LIMIT = 10_000` as
a module-level constant; reused in both call sites and the test suite.

R2 (signature): tightened `_coerce_flow_id_to_uuid` and
`_safe_graph_flow_id` from `Any` to `str | UUID | None`; tightened
`aget_agent_chat_history`'s `flow_id` argument accordingly.

Tests: extended `test_memory_flow_id_scoping.py` with coverage for
each of the above — symmetric store/read flow_id (I1), DESC+reverse
ordering on retrieve_messages (I2), ceiling-warning emission (I2),
structured error log on flow_id fallback (I3), and explicit-limit
suppression of the warning. All 26 tests pass.

* [autofix.ci] apply automated fixes

* Template update

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-05-20 19:46:51 +00:00

Langflow logo

Release Notes PyPI - License PyPI - Downloads Twitter YouTube Channel Discord Server Ask DeepWiki

Langflow is a powerful platform for building and deploying AI-powered agents and workflows. It provides developers with both a visual authoring experience and built-in API and MCP servers that turn every workflow into a tool that can be integrated into applications built on any framework or stack. Langflow comes with batteries included and supports all major LLMs, vector databases and a growing library of AI tools.

Highlight features

  • Visual builder interface to quickly get started and iterate.
  • Source code access lets you customize any component using Python.
  • Interactive playground to immediately test and refine your flows with step-by-step control.
  • Multi-agent orchestration with conversation management and retrieval.
  • Deploy as an API or export as JSON for Python apps.
  • Deploy as an MCP server and turn your flows into tools for MCP clients.
  • Observability with LangSmith, LangFuse and other integrations.
  • Enterprise-ready security and scalability.

🖥️ Langflow Desktop

Langflow Desktop is the easiest way to get started with Langflow. All dependencies are included, so you don't need to manage Python environments or install packages manually. Available for Windows and macOS.

📥 Download Langflow Desktop

Quickstart

Requires Python 3.103.13 and uv (recommended package manager).

Install

From a fresh directory, run:

uv pip install langflow -U

The latest Langflow package is installed. For more information, see Install and run the Langflow OSS Python package.

Run

To start Langflow, run:

uv run langflow run

Langflow starts at http://127.0.0.1:7860.

That's it! You're ready to build with Langflow! 🎉

📦 Other install options

Run from source

If you've cloned this repository and want to contribute, run this command from the repository root:

make run_cli

For more information, see DEVELOPMENT.md.

Docker

Start a Langflow container with default settings:

docker run -p 7860:7860 langflowai/langflow:latest

Langflow is available at http://localhost:7860/. For configuration options, see the Docker deployment guide.

🛡️ Security

For security information, see our Security Policy.

🚀 Deployment

Langflow is completely open source and you can deploy it to all major deployment clouds. To learn how to deploy Langflow, see our Langflow deployment guides.

Stay up-to-date

Star Langflow on GitHub to be instantly notified of new releases.

Star Langflow

👋 Contribute

We welcome contributions from developers of all levels. If you'd like to contribute, please check our contributing guidelines and help make Langflow more accessible.


Star History Chart

❤️ Contributors

langflow contributors

Description
Langflow is a powerful tool for building and deploying AI-powered agents and workflows.
Readme MIT 2.3 GiB
Languages
Python 64.5%
TypeScript 23.4%
JavaScript 11.4%
CSS 0.3%
Makefile 0.2%
Other 0.1%