Splits monolithic agent instructions into a slim AGENTS.md hub plus docs/agents/ topic files (philosophy, architecture, components, contracts, testing, anti-patterns) so AI coding agents have a single source of truth for how the project thinks. Removes the .cursor/rules/ directory; AGENTS.md is now the only agent-facing doc. Fixes the long-standing pointer to the empty src/backend/base/langflow/components/ stubs (real components live in src/lfx/src/lfx/components/) and corrects the v2 API description from 'future' to its actual mounted state.
4.2 KiB
Project Philosophy
Read this file before scoping any non-trivial work. Most off-narrative work comes from skipping it.
Langflow is a visual flow builder first. Every change should make sense to someone whose only interface is dragging nodes onto a canvas. Use these principles to scope work; if a proposed change fails one of them, stop and reconsider.
Tenets
-
Flows are user artifacts, not implementation details. Flow JSON lives in users' databases and runs in production. Backwards compatibility for components is non-negotiable: never rename a class name,
nameattribute, input name, or output name; never remove an input or output; never tighten an output type; never remove methods from base classes likeLCModelComponent. To change a component, add the new one alongside, setlegacy=True+replacement=[...]on the old, and updatefile_names_mappingin tests so saved flows still load. See CONTRACTS.md for the full surface. -
Every backend feature must land on the canvas. If a capability cannot be expressed as a component (or a property of one) that a non-Python user can wire up, it is an SDK feature and belongs in
lfx, notlangflow-base. Backend changes that have no visual surface are almost always off-narrative. -
Components are the unit of work, not endpoints or services. Before adding a route, store, or service, ask: which component does this serve? If the answer is "none yet," the route is premature. New REST endpoints without a component or UI consumer are off-narrative.
-
lfxis the runtime,langflow-baseis the platform,langflowis the distribution. Components and the graph engine live inlfx(src/lfx/src/lfx/components/). API, auth, persistence, and multi-user concerns live inlangflow-base. Thelangflowpackage is the integration that ships everything together. New code goes in the lowest layer that can host it. Boundaries are enforced one-way:langflow→langflow-base→lfx. See ARCHITECTURE.md. -
Don't add a config flag for something a builder-user would set on a node. If a setting affects flow behavior, it's a component input. If it affects deployment, it's an env var. Hidden global flags that change component semantics break the visible-data-flow contract.
-
Visible data flow beats clever magic. Implicit context, hidden globals, and side-channel state make flows unreadable on the canvas. Pass data through inputs and outputs. If you find yourself reaching for a global, you're probably building something that doesn't belong in a node.
-
Composition over capability. Prefer adding small, single-purpose components users can wire together over one large component with many modes. The
If-Else/Current Datestyle (one job, clear name, obvious icon) is the target shape. -
Every component needs
display_name,description,icon, and a sensible category. A component that doesn't render legibly in the sidebar shouldn't ship. The icon is part of the API, not decoration — pick a Lucide icon that matches the verb. -
The Playground is the test harness builder-users see. A component is "done" when it works end-to-end in a flow on the canvas, not when its unit test passes. Use the Graph test pattern (build,
.set(),async_start, validate) before claiming a feature works. -
Two audiences, one product: visual builders and Python devs. When their needs conflict, the visual builder wins for
langflow-basefeatures and the Python dev wins forlfxSDK features. Don't compromise the canvas to make the SDK prettier, and don't compromise the SDK to make the canvas easier. -
It is not a fix if you didn't have evidence of the change fixing something. Adding error handling, retries, type widening, or skipping a flaky test does not constitute a fix. Reproduce the failure, demonstrate the fix removes it, then ship. See ANTI-PATTERNS.md.
How to apply
When scoping a task, walk through the tenets and name the ones the work serves. If a change fails tenet 1, 2, or 3, stop and surface the conflict before writing code. If you can't tell which tenet a change serves, it's probably off-narrative — ask.