DataSources
Load a local spreadsheet or CSV, or an RSS, Atom, or JSON feed, once and use its columns everywhere. Workflows loop the rows, dashboards chart them, and the AI reads them through a built-in tool. Keep a source as a fixed snapshot or a live read, preview and edit every row in a paged and filterable grid, and move a source between this project and all projects without breaking what points at it.
What happens in this clip
- A spreadsheet is open as a data source, in a grid.
- Double-click a cell to fix it in place.
- Add a row through a typed dialog and it appears at the bottom.
- Rename a column from its header menu, with a warning about what references the old name.
- Check the rows you want and hand exactly those to the chat. It is the same grid the assistant reads from.
Related features
Load a Spreadsheet Once, Use It Everywhere
Import an Excel file or a CSV and it becomes a named table of typed columns. A workflow can loop its rows and a dashboard can chart them, from the same source. Load a leads list or a price sheet one time and every automation and board can read it.
- Excel (.xlsx) and CSV, with a per-column type pass: text, number, yes/no, date
- Drag a file onto the panel, or import inline wherever a source is picked
- Imported once, available to every workflow and dashboard
- Identifier columns stay text, so phone numbers and ids are never read as dates
An RSS Feed Is a Data Source Too
Paste a feed URL, or a site home page and pick the feed it links to, and it loads as a table, one row per item. Every feed gets the same typed columns: title, link, published, author, summary, content, categories, and id. Loop it in a workflow, chart it on a dashboard, or let the AI read it, the same as any spreadsheet.
- RSS 2.0, Atom, and JSON Feed, parsed into the standard column set
- Paste a site URL and pick its feed, no hunting for the link
- Private feeds via an API Connection: key, bearer, or basic auth
- Expose all fields adds a column for every other element in the feed
- Feeds default to live, so the table stays current
Snapshot or Live, Your Choice
A snapshot stores the rows as they were the moment you imported: offline-safe, and fixed until you refresh. Live re-reads the original file each time, so edits show up without re-importing. Set it per source and override it wherever the source is used.
- Snapshot for a one-off campaign over a fixed list
- Live for a file you keep editing in place
- Refresh from source pulls the latest rows into the snapshot on demand
- Freshness is a per-use override on the tool and in every picker
Preview Every Row, Not Just the First Few
Open a source and it expands into a full-panel grid: every row paged, a search box across all columns, per-column filters in a dropdown off the search bar, and click-to-sort. Rows are fetched a page at a time from the local daemon, so a few thousand stay responsive.
- Pages of 25 to 250 rows, each fetched on demand
- Global search plus a per-column filter
- Sortable columns, ascending or descending
- Opens as a wide in-panel view with a full-screen toggle, the way a board opens
Edit It Like a Spreadsheet
The grid is where you change the data, not just read it. Double-click a cell to fix it, open a whole row in a typed dialog, add and delete rows, and rename, retype or drop a column from its header menu. Or start a blank table and type it yourself, with no file to import.
- Double-click a cell: Enter saves, Esc discards, Tab moves on
- Add or delete rows one at a time, or check several and delete the lot
- Rename, retype, add and delete columns from the header menu
- Changing a type says how many values will not convert, and keeps them as text
- Start a blank table from the Add menu: name it, declare its columns, fill it in
Read Only When It Has To Be
A feed is never editable, because its rows are replaced on every refresh. A source that reads live from a file you own is refused rather than edited invisibly, and the banner offers to switch it to a snapshot for editing. A snapshot over your own file is editable, and the refresh button asks before it overwrites your edits.
- A feed hides its edit controls rather than greying them
- A live source offers Switch to Snapshot right where the refusal appears
- Refresh only warns once you have actually edited something
- A source your organization pushed can have its rows edited but not be deleted
Mention It in Chat, Whole or Row by Row
Type @ in the chat input and pick a data source. The message carries its columns, row count, and first rows, and the AI reads past that with the tool when it needs more. For exact rows, check them in the preview grid and click Add to chat; the conversation then points at precisely those rows.
- A Data sources section in the @ picker, searchable by name
- A whole-source mention inlines the schema and the first 20 rows
- Check rows across pages, searches, and filters; the # column numbers them
- Row mentions read @dataset:<id>#rows=2-15,40 and inline up to 200 rows
Ask for a List, or a Row
Tell the assistant what you want and it builds the data source or changes the rows: a new list from what you just pasted, a row added, a value fixed, a test row dropped. The panel updates the moment it finishes, and a list it makes for you is an ordinary source, with the same preview, scope, and refresh.
- Create a source from rows in the conversation, named and typed
- Add, edit, or remove rows in a source you already have
- Identifier columns can be pinned as text, so a leading zero survives
- The panel, the pickers, and an open preview all refresh on their own
- A feed is never edited, and a live source backed by your own file is left alone
- Or open a chat docked beside the grid, bound to that one source, and watch it work
Loop Over the Rows in a Workflow
Give a workflow a Data source input. At run time you pick the file (or import one on the spot) and the freshness. A tool step loads the rows, a loop walks them, and each column reads as a template variable.
- Data source is a typed workflow input that resolves to {id, mode}
- A plexon_dataset tool step returns the rows
- A loop step over the rows fans the work out, one item at a time
- Each column reads as {{loop.item.<Column>}} inside the loop
Bind a Dashboard Widget to a Source
In the widget editor, click Use a data source, pick the file from the list, and choose the column to show. A table widget renders the whole sheet; a metric or gauge widget shows one field. No hand-written JSON arguments required.
- Pick the data source and the field from dropdowns
- Table widgets render every column and row
- Value widgets map one column to the number they display
- Or reference a board parameter for a viewer-switchable source
One Tool Behind Both Paths
A read-only built-in tool, plexon_dataset, backs the dashboard binding and the workflow step alike. It returns typed columns and column-keyed rows, with paging, a column subset, and an optional group-by count. The AI can call it from any prompt too. Writes go through a separate tool, plexon_dataset_edit, which boards and workflow steps cannot reach.
- Returns columns, rows, row_count, and an optional per-value group count
- Rows keyed by column name, so a loop and a table both read them directly
- limit, offset, columns, and group_by arguments for shaping the result
- Bindable in workflows and dashboards through the built-in tool allowlist
- Creating and editing is a separate tool, kept off the unattended path
Project or Global, and Move Between Them
A source lives in one project or across all of them, your choice at import. Move it between the two from its card at any time, and its id stays the same, so workflows and dashboards that already reference it keep resolving. The panel footer counts both scopes.
- This project only, or all projects
- Move a source from project to global and back, references survive
- The footer shows the count in each scope
- A sidebar badge shows how many sources you have at a glance
Ship a Sample List With a Persona
A persona can carry its own Data Source. Install the persona, or switch to it, and a sample CSV lands in your global sources, there to read from a workflow or a board. The copy is written only when it is missing, so once you edit the rows they stay yours through every later switch.
- A persona declares a sample CSV in its profile; install or switch drops a copy into your sources
- Seed-if-missing: written once, then your edits survive every reinstall and every switch
- Fully editable, the same as a source you imported by hand
- Lands in your global scope, available to every project
Local, Bounded, and Safe
The file never leaves your machine. Imports cap at 64 MB and snapshots at 200,000 rows. Date detection is conservative on purpose, so an id or phone column is never reinterpreted. Delete a source and anything still pointing at it shows a clear message instead of failing silently.
- Files stay on disk under ~/.plexon/datasets or <project>/.plexon/datasets
- 64 MB import cap; 200,000-row snapshot cap with a note when truncated
- Conservative ISO-date detection keeps ids and phone numbers as text
- A deleted source surfaces a clear missing-source message, never a silent break
Under the Hood
Import Pipeline, excelize Off the Hot Path
An Excel import is parsed once with excelize and written as a snapshot CSV; every later read uses encoding/csv only. Each row is typed from the column metadata you set at import, so a number column stays numeric and an id column stays text. The original file path is remembered for a refresh from source.
One Read-Only Tool, plexon_dataset
A single built-in tool registers on the same embedded MCP server every built-in tool uses. It reads the snapshot (or re-parses the original in live mode) and returns typed columns with column-keyed rows. Dashboards and workflow tool steps reach it through the bindable allowlist; the AI can call it from any prompt.
Paged Rows for the Preview
The preview grid asks the daemon for one page at a time with an offset, limit, search term, per-column filters, and a sort. Filtering and sorting run server-side over the in-memory snapshot, so the renderer only ever holds the page on screen. A big leads list opens without shipping every row across the bus.
Typed, Conservative Columns
Type inference is deliberately careful: textual booleans only, ISO YYYY-MM-DD dates only, and leading-zero or very long integers stay text. That keeps Contact ID, Deal ID, and phone columns from being mangled into numbers or dates, which is the difference between a usable campaign list and a broken one.
Snapshot and Live
Snapshot is a stored copy that never changes until you refresh; live re-reads the source on every use, a file from disk or a feed re-fetched. Freshness is set per source and overridable on the tool call and in every picker, so the same source can drive an offline campaign and a live board without a second import.
Feeds Fetch Through the SSRF Guard
A feed is the one source that reaches the network, so it goes through the same guarded fetch the API Connections use: a scheme and host allowlist, a post-DNS check against private and link-local ranges, and a pinned dial that closes the rebind window. A live feed read is cached for about a minute so several widgets on one feed share a single fetch.
Mention Expansion on the Daemon
An @dataset token is plain text until the message leaves the machine: the local daemon expands it in place, appending the schema and the referenced rows as CSV beneath the prompt. Reads come from the stored snapshot so the same token always expands to the same rows, the inline expansion is size-capped, and everything past the cap stays one plexon_dataset call away.
Per-Scope Stores That Move
Each scope has its own index and snapshot directory: the Plexon home for global, the project folder for project. A move reads the snapshot, writes it under the target scope keeping the same id, then removes the source copy. References by id survive the move because the resolver searches both scopes.
A Dataset a Persona Can Carry
A persona profile lists its sample sources under a datasets: field. On install and on every persona switch, the seeder copies each one into the global dataset store, but only when a source with that id is not already there. The first switch writes the file; later switches leave your edited copy alone, so a persona ships a starting list without overwriting your work.
A Typed Workflow Input
Data source is a first-class workflow input type that coerces to an object of id and mode. A tool step reads the id with {{trigger.<name>.id}} and the freshness with {{trigger.<name>.mode}}, then a loop walks the rows. The run dialog opens the picker so a non-author can choose the file at run time.
Trusted, On-Disk, Bounded
The datasets directory is a trusted root the file tools can read, and it is exposed as the $PLEXON_DATASETS path token for scripts. Imports cap at 64 MB and snapshots at 200,000 rows. Nothing about a source leaves the machine; the only thing on the wire is one page of rows when you open the preview.
Connects to
Nothing here works alone. See the whole map for how the pieces fit together.
This one is taught in step 6 of 8: make the result visible.
What feeds it
ΓΕΜΗ Lead Radar feeds this.
Every company the radar scores becomes a row in its own Data Source, ΓΕΜΗ radar leads, and the next run skips the registry numbers already there.
Where it goes
This feeds AI Chat & Modes.
A built-in tool reads a source from any prompt, and you can @-mention a source or exact rows.
This feeds Dynamic Workflows.
Give a workflow a Data source input and the loop step walks its rows.
This feeds Dashboards.
Bind a widget to a source and a field, with no JSON.
This is packaged by Personas.
A persona can bundle a dataset that seeds into your Data Sources on install.