The most common silo in business
The vendor sends a rebate schedule by email every quarter. The real-estate team keeps the lease costs for every location in a spreadsheet. An agency delivers a target list as an attachment, and a SaaS tool nobody ever integrated offers its records only as an export. Every business runs on files like these, and each becomes useful when it is joined against the data the company already has.
Getting the file somewhere joinable has always been the obstacle. The standard path ran through a request to data engineering, a staging table, and a loader that somebody now owns for a file that changes quarterly, or once. For a file needed one time, nobody files that ticket. So the analysis happens by hand in a spreadsheet, against an export that was stale before the lookup finished, or it does not happen.
Plenty of software accepts a CSV upload, which is how the problem usually hides. A BI tool takes the file and makes it a dataset its own dashboards can see. A campaign tool takes it and makes it an audience. The upload succeeds, and the silo has moved into a different product. What none of that produces is the file sitting beside the warehouse as a peer: one more table, in the same SQL, under the same governance.
What an agent does with a CSV, without help
Hand the same file to an AI agent and its first instinct is to read it. Reading means the whole file passes through the context window, so a three-hundred-row spreadsheet costs thousands of tokens before the first question is asked, and a fifty-thousand-row vendor file does not fit at all. Whatever the agent concludes, the spend repeats next session, because nothing durable came of it.
The workarounds are worse. An agent can fetch both sides and match rows in prose, which performs the join inside the model itself, token by token, with an error rate that grows with the row count. Or it can dribble the file into a database as batches of INSERT statements, which is slow, needs write access to somewhere, and leaves a half-loaded table when the session ends early.
A short list of keys needs no table at all: a handful of pasted ids joins inline as a VALUES clause through an ordinary read-only query, and Plexara tells the agent so. Registration is for files with hundreds or hundreds of thousands of rows, where the join belongs in a query engine.
CSV handling, with and without a registered table
Whole file in context
The file goes through the context window
- The agent reads the whole file into context, spending tokens on every row
- Joins happen agent-side: fetch both sides, match them in prose
- A fifty-thousand-row file does not fit at all
- The work is not repeatable: next session, same parsing, same spend
Register once, query by name
The file becomes a table
- One registration makes the file queryable where it sits
- The join runs in the query engine, and only the answer reaches the agent
- Row count stops mattering: 300 rows or 300,000 query the same way
- Search returns the table name and a sample join on the file from then on
Registration, not ingestion
Files reach Plexara two ways. A person uploads reference material into the portal, where it becomes a managed resource with versions, scoping, and usage tracking. Or an agent saves something it built as a portal asset: an export from a warehouse query, a dataset assembled from gateway API calls, a working file another tool produced. Either kind of CSV can be registered as a table.
Registration is deliberately not ingestion. The platform reads the file, takes column names from its header row, and creates an external table over the object where it already sits, in a scratch schema set aside for working tables. Nothing is copied, no pipeline is scheduled, and no storage is doubled. Under the surface this is Trino reading CSV through its Hive support, directly against the same object store that holds the platform’s files; to the person or agent doing the registering, it is one action with a table name as the answer.
From that moment the file and the table are linked. A search that finds the file returns the registered table’s name and a sample join on the same hit, so an agent that finds the file later starts from SQL rather than from the loading problem. And because the table reads the object in place, a vendor drop that overwrites its file changes the next query’s answer with no further action from anyone.
Registration flow
1 · A file lands
A person uploads it to the resource library
Or an agent saves one it built as an asset
store_id,annual_base_rent_usd,annual_cam_usd,lease_end
1,78900,11800,2026-04-01
2,50700,8500,2027-05-01
3,65100,14100,2030-01-01
2 · One registration
The platform reads the file, takes column names from its header, and creates an external table over the object where it already sits. Nothing is copied and no pipeline runs.
- Columns come from the header row
- The table name carries your persona
- An audit event records who and what
3 · Queryable beside everything
JOIN · ON store_id
The file reads as rows in the same SQL surface as the warehouse, so the join is one statement and only its answer spends tokens.
A worked example: lease costs against revenue
Everything in this section ran on a live Plexara deployment, the demo environment seeded with a 303-store retail chain, while the article was being written. The file is the classic case: a FY2026 lease schedule, one row per store, carrying annual base rent, common-area maintenance charges, and the lease end date. It is exactly the spreadsheet a real-estate team keeps and a warehouse never sees.
The agent saved the schedule as a portal asset and registered it with a single call. The response below is complete: the table name, the columns read from the header, and the one fact worth knowing before writing SQL, which is that a CSV’s columns arrive as VARCHAR and join to typed warehouse columns through a cast.
Registration call and response
manage_table action=register reference=mcp:asset:eda2a7a0… connection=scratch
- query_table
- scratch.uploads.admin_store_lease_costs
- columns
- store_id · annual_base_rent_usd · annual_cam_usd · lease_end
- connection
- scratch
- stale
- false
- note
- Every column is VARCHAR, so a join to a typed column needs a CAST.

The join
The file exists to answer one question: which stores pay rent out of proportion to what they sell. That is a three-way join, lease costs against the store dimension against a year of transactions, and with the registration in place it is one statement.
The chain’s median store spends 12.8 percent of revenue on occupancy. Twenty stores sit above 25 percent, five above 30, and the worst, a Springfield, California store, pays $143,800 in occupancy against $340,536 in revenue, 42.2 percent, with the lease up for renewal in June 2026.
Two things did not happen: the file never entered the context window, and the agent never read the source rows. It read eight result rows, because the query engine did the work and only the answer traveled. The statement is recorded, the result was saved as an asset with its provenance attached, and when next quarter’s schedule arrives, the same join runs against it.
The join
WITH revenue AS (
SELECT store_id, SUM(total) AS revenue_2025
FROM warehouse.public.transactions
WHERE transaction_date >= DATE '2025-01-01'
AND transaction_date < DATE '2026-01-01'
GROUP BY store_id
)
SELECT s.store_name, s.city, s.state,
CAST(l.annual_base_rent_usd AS integer)
+ CAST(l.annual_cam_usd AS integer) AS occupancy_cost,
ROUND(100.0 * (CAST(l.annual_base_rent_usd AS integer)
+ CAST(l.annual_cam_usd AS integer)) / r.revenue_2025, 1) AS occupancy_pct
FROM scratch.uploads.admin_store_lease_costs l
JOIN warehouse.public.stores s ON s.store_id = CAST(l.store_id AS integer)
JOIN revenue r ON r.store_id = s.store_id
ORDER BY occupancy_pct DESC| Store | 2025 revenue | Occupancy cost | Share | Lease ends |
|---|---|---|---|---|
Store #36 Springfield, CA | $340,536 | $143,800 | 42.2% | Jun 2026 |
Store #292 Ashland, WA | $362,966 | $149,600 | 41.2% | May 2028 |
Store #211 Manchester, OH | $415,759 | $152,600 | 36.7% | Nov 2026 |
Store #138 Kingston, MA | $462,066 | $145,600 | 31.5% | Oct 2029 |
Store #128 Bristol, MD | $304,314 | $95,700 | 31.5% | Nov 2029 |
Rows in the lease spreadsheet, registered as a table in a single call
One file, one registration
Median share of revenue the chain pays in rent and common-area charges
Registered CSV joined to 2025 revenue
Stores whose annual rent and CAM exceed 30 percent of 2025 revenue
Registered CSV joined to 2025 revenue
Versions, staleness, and refused files
A registered table serves the content that was current when it was registered. Every edit to a portal asset and every revision of a managed resource writes a new version, and a table that silently followed the newest version would change the results of any report built on it. So the table stays put, and everywhere the registration appears, the portal panel, the file’s search hit, the agent’s own listing, it is flagged as stale until someone registers again, which takes the table forward in one step. A file overwritten in place, the shape of a recurring vendor drop, needs no re-registration at all.
Registration also refuses files a line-based query engine would misread. A spreadsheet export with line breaks inside quoted cells is legal CSV under RFC 4180 and parses cleanly in every ordinary reader, but a line-based reader would tear each such row into fragments and return them as rows without any error. Plexara reads the whole file before creating anything, names the specific problem, and offers a correction: one control that writes a repaired version through the file’s own version trail, with the original preserved beneath it, and registers the result.
The governance is the same as everywhere else on the platform. Every registration writes an audit event, including the failed attempts. Registering requires the authority to change the file, not merely read it, because a registered table is readable by everyone granted the connection; the table name carries the registering persona so a shared schema stays legible; and dropping a table belongs to the person who registered it, or an administrator. Deleting the file takes every table registered over it along.


The gap this closes
The gap sits between the warehouse and the agent, where ad-hoc data lives: the attachments, the exports, the schedules, the lists. Those files used to face a choice between an engineering project and a silo. Now the path is upload, register, join, and it works in both directions, for the spreadsheet a person brings to the platform and for the dataset an agent assembles out of API calls and saves as an asset.
This does not replace pipelines, and is not trying to. Data that arrives on schedule at volume belongs in the warehouse proper, modeled and owned. The scratch schema is a working space, not a modeling layer: it is where a quarter’s analysis meets a quarter’s file. What it replaces is the ticket that was never worth filing, the one-off loader nobody wanted to own, and the analyst afternoon lost to a lookup formula.
A registered table is a pointer and a name. It puts the most common file in business on the same governed, queryable surface as everything else, the day the file arrives.
Further Reading
Hive connector
Trino Project
The query-engine mechanism behind registered tables: external tables reading CSV files in object storage, with every column typed VARCHAR by the storage format.
RFC 4180: Common format and MIME type for CSV files
IETF
Why a spreadsheet export with line breaks inside quoted cells is legal CSV everywhere except a line-based reader, which is the case registration detects and offers to correct.
