Tables

A table in Flow is a rectangle of rows and columns that came out of a CSV file or an Excel sheet. Fourteen nodes can read it, filter it, join it, group it and write it back to a file. There is no database involved: the table is computed inside a single run, in memory, and disappears together with it.

The nodes themselves are available on the free plan, but routine processing of exports is not: schedule and webhook triggers only work on a paid plan, and on the free plan the whole run has to fit into 120 seconds while a single uploaded file cannot exceed 10 MB. Exact values for both plans are in the limits.

The “table” port

Ports on df nodes declare the dataframe data type. An edge carries the whole table at once, not row after row: grouping, sorting and joining are defined over the entire set of rows, so a “stream of rows” simply would not fit — the node would still have to wait for the last row to arrive.

Two consequences follow immediately.

A table does not let you walk over rows. To process every row separately — say, to send one email per row — first turn the table into a list of objects with the convert node, and feed that list to a loop.

The log holds a preview, not the table. The live table exists only in the run’s memory; what goes into the run history, the SSE stream and the Output panel is a snapshot: column names, types, a size like 12480×7 and the first 50 rows. This keeps a hundred-megabyte table from being copied into the database at every step — see timeouts and budgets.

Where the files come from

From the workspace file storage — the same one that holds chat attachments and everything you uploaded by hand on the Files tab. By default df nodes read and write the storage of their own workspace, and the storage port is not even drawn: the configuration only needs a path and, if required, a subfolder. The port appears only when you switch the connection source to external — then a storage node is placed next to it, and the same graph starts working against someone else’s disk over WebDAV.

The path is a template, so reports/{{ variables.session_id }}.csv gives you one file per session.

The pipeline

Entry
Read CSV
DF Query
DF Group By
Write XLSX
Exit
  • Execute
  • Execute + Data
Read the export, filter rows, roll them up by group, write the result back to storage.

Reader nodes are started by a regular execute edge, while for all the others the incoming table doubles as the trigger: the table arrived, the node ran. That is why the pipeline looks like a chain without a single branch, and the order of steps in it is literally the order of operations.

The last node in the chain returns not a table but a write report: the path, how many bytes and how many rows were written. It is convenient to hand it to exit or to substitute it into the answer text.

All fourteen nodes

NodeWhat it doesWhat it returns
df_read_csvReads CSV from storage: delimiter, encoding, header row number, row limitA table
df_read_xlsxReads a sheet of an xlsx workbook — by name or by index (0 = first)A table
df_queryKeeps the rows matching an expression: revenue > 1000 and country == 'DE'A table
df_selectPicks, renames and drops columnsA table
df_sortSorts by one or several columns, each ascending or descendingA table
df_groupby_aggGroups by columns and computes aggregates: sum, mean, min, max, count, nunique, first, last, std, medianA table: one row per group
df_mergeJoins two tables on shared keys: inner, left, right, outer, crossA table
df_concatGlues two tables together by rows (one under the other) or by columns (side by side)A table
df_drop_duplicatesRemoves duplicates over a set of columns; you can keep the first or the last occurrenceA table
df_updateAssigns values to columns in the rows matching a condition; an empty condition means all rowsA table
convertConverts json, csv and dataframe into one anotherA value of the chosen type
df_write_csvWrites the table to CSV, overwriting the whole filePath, bytes, row count
df_write_xlsxWrites the table to an xlsx sheet, overwriting the whole filePath, bytes, row count
dataframe_toolGives an agent ten tools over tablesNot a graph step: it plugs into an agent

The fields of each node, its ports and an example graph are on its reference page.

Conversion: the one explicit way

convert is a graph step with its own timing and its own error, and that is the point: the conversion is visible on the canvas. Four directions are registered: json → dataframe, dataframe → json, dataframe → csv, csv → dataframe. The csv ↔ json pair is not among them — it is assembled from two nodes via dataframe, and the editor will tell you so before the run rather than halfway through it.

A table and a collection are different things

They are easy to confuse: both look like a table with columns. The difference is lifetime.

  • A table lives inside a run. It arrives from a file, goes through a chain of nodes and disappears when the run ends. The only way to keep it is to write it to a file with the df_write_csv or df_write_xlsx node.
  • A document collection outlives the run. It is workspace storage: the next run sees what the previous one wrote, documents can be selected by fields and edited by hand in the interface.

The rule is simple: a one-off file processing is a table; data that has to still be there tomorrow is a collection. Semantic search over text is a knowledge base altogether.

Boundaries

  • File size. Reading and writing have a ceiling in bytes: 25 MiB for reads and 50 MiB for writes by default. The field sits in the Advanced section and can be lowered but not raised — the ceiling is the maximum.
  • Time. A node cannot run longer than 600 seconds, and the whole run is capped by the plan (120 seconds on the free one). Parsing a large export hits that before it hits memory; see timeouts and budgets.
  • Space. A written file counts towards the owner’s file storage quota — a single quota across all of their workspaces.
  • Failures. Unreachable storage, a broken CSV, a missing column — these are node errors, not an empty table: the run fails unless you drew an on_error branch. How to draw one is in error handling.

Tables in an agent’s hands

dataframe_tool plugs into an agent and gives the model ten tools: load a CSV or an xlsx sheet, inspect the schema and a sample, filter, pick columns, join, group, export to JSON, save to CSV or xlsx. The tables stay on the server — the model gets a short handle and passes it to the next tool instead of hauling the data through its context.