How to Embed Excel and CSV Reports Into a Knowledge Base From FTP

Build a scheduled Spojit workflow that downloads spreadsheet reports from an FTP server, embeds each Excel and CSV file into a persistent knowledge collection, and leaves you with an archive you can ask questions of in plain language.

What This Integration Does

Many teams receive operational reports as spreadsheets dropped onto an FTP server: nightly sales exports, inventory counts, finance summaries, supplier price lists. Those files pile up where nobody can search them. This workflow turns that folder into a living knowledge base. On a schedule, Spojit lists the report folder on FTP, downloads each spreadsheet, and embeds it as an Excel or CSV document into a persistent collection. Once embedded, anyone in your workspace can run a Knowledge query node (or ask Miraxa, the intelligent layer across your automation) and get answers synthesized from the numbers inside those files.

The workflow runs unattended on a Schedule trigger. Each run lists the FTP directory, loops over the files it finds, and embeds them one at a time into a long-lived collection. Because the collection is persistent and workspace-scoped, every embedded report stays available to any other workflow that queries it, run after run. Embedding the same file name again overwrites the previous version, so a daily report that keeps the same name stays current rather than producing duplicates. The downloading and embedding logic lives in a child workflow you call with a Subworkflow node, so you can reuse it from other workflows and keep the parent small.

Prerequisites

  • An FTP connection added under Connections → Add connection, with read access to the folder where your reports are delivered (for example /reports/daily).
  • A persistent knowledge collection created ahead of time in the Knowledge section of the sidebar (New Collection), for example named operational-reports. Note the embedding model chosen at creation; it is fixed for the life of the collection.
  • Reports delivered to FTP as .xlsx, .xls, or .csv files with predictable names.
  • Permission to create workflows in your workspace. You will build two: a child workflow that embeds one file, and a parent workflow that schedules and orchestrates.

Step 1: Create the child workflow that embeds one file

Start with the reusable piece. Create a new workflow named embed-one-ftp-report and give it a Manual trigger so it can be invoked by a parent. The parent will pass in the file path and the document type, so the child reads them from {{ input.path }} and {{ input.documentType }}. Keeping the embed logic here means you can call it from any future workflow without rebuilding it.

Step 2: Download the spreadsheet from FTP

In the child workflow, add a Connector node in Direct mode using the FTP connector and the download-file tool. Map path to {{ input.path }}. Spreadsheets are binary, so set encoding to base64 so the bytes survive transport intact (CSV files are technically text, but downloading them as base64 keeps a single code path that works for every report type). Set the node's Output Variable to ftp_file. The result exposes the downloaded bytes at {{ ftp_file.data.content }}, along with {{ ftp_file.data.size }} and {{ ftp_file.data.encoding }}.

tool: download-file
path: {{ input.path }}
encoding: base64

Step 3: Embed the file into the persistent collection

Add a Knowledge node in Embed mode. Set Collection to your persistent collection (operational-reports). Set Document Type from the value the parent passes, {{ input.documentType }} (it will be Excel for .xlsx/.xls files and CSV/TSV for .csv files). Set File Name to the file's name so re-embedding the same report overwrites the prior copy rather than duplicating it. Feed the bytes from Step 2 into Document Input as {{ ftp_file.data.content }}. Leave the embedding model on the collection default. Set the Output Variable to embedding; it returns the chunk count and document metadata, which the parent can log.

mode: Embed
collection: operational-reports
fileName: {{ input.fileName }}
documentType: {{ input.documentType }}
documentInput: {{ ftp_file.data.content }}

That is the entire child. It downloads one file and embeds it. Save the workflow.

Step 4: Build the parent and add the Schedule trigger

Create a second workflow named sync-ftp-reports-to-knowledge. Add a Trigger node of type Schedule. Use a 5-field Unix cron expression and an IANA timezone so the workflow runs after your reports land. For example, run at 6am on weekdays in Sydney with cron 0 6 * * 1-5 and timezone Australia/Sydney. A single Schedule trigger can hold multiple schedules if reports arrive at different times. The trigger output is {{ trigger.scheduledAt }}, handy for logging which run touched which files.

Step 5: List the report folder on FTP

Add a Connector node in Direct mode using the FTP connector and the list-directory tool. Set path to your report folder, for example /reports/daily. Set the Output Variable to listing. The result returns one entry per item at {{ listing.data.entries }}, where each entry has a name, type, size, and modification date. You will loop over these entries next.

tool: list-directory
path: /reports/daily

Step 6: Loop over files and call the child workflow

Add a Loop node in ForEach mode over {{ listing.data.entries }}, exposing each item as entry. Inside the loop, first add a Condition node so you only process spreadsheets: continue when {{ entry.type }} is a file and {{ entry.name }} ends with .xlsx, .xls, or .csv. On the matching branch, add a Subworkflow node, pick your embed-one-ftp-report child as the Workflow, and pass the file details as Input. Build the full path by joining your folder and the entry name, and set the document type from the file extension so the child embeds it correctly.

workflow: embed-one-ftp-report
input:
  path: /reports/daily/{{ entry.name }}
  fileName: {{ entry.name }}
  documentType: Excel   # use CSV/TSV when {{ entry.name }} ends with .csv

If you prefer to branch the document type cleanly, split the matching branch with a second Condition node: one path passes Excel for .xlsx/.xls names, the other passes CSV/TSV for .csv names. The child workflow runs once per file and returns its chunk count, which appears as a separate entry in your execution history.

Step 7: Confirm the reports are queryable

After a run, open the operational-reports collection in the Knowledge section and check the document table: each embedded file should show a row with its name, type, size, chunk count, and a READY status. To use the data in a workflow, add a Knowledge node in Query mode pointed at the same collection, set a natural-language Prompt, pick a Model for synthesis, and read the answer from its Output Variable. You can also ask Miraxa directly on any page, for example "Which product had the highest returns in last week's report?"

Tips

  • Keep report file names stable across days. Because File Name overwrites on re-embed, a daily file with a constant name stays current instead of accumulating duplicate copies in the collection.
  • Use the same embedding model for embed and query. The model is fixed when you create the collection, so any Knowledge query node must read the collection that holds your reports rather than a Transient one.
  • Centralize the embed logic in the child workflow. If you later add a second report folder, you call the same embed-one-ftp-report child from a new loop instead of rebuilding the FTP and Knowledge nodes.
  • If you only ever need to answer a question once and discard the data, choose a Transient collection in the Knowledge node instead of a persistent one; for a long-lived archive, keep the persistent collection as described here.

Common Pitfalls

  • Downloading spreadsheets with utf8 encoding corrupts the bytes. Always set encoding to base64 on the FTP download-file tool for .xlsx and .xls files.
  • Setting the wrong Document Type in the Knowledge node produces poor chunks. Map Excel to .xlsx/.xls and CSV/TSV to .csv; do not embed a spreadsheet as Plain Text.
  • Forgetting the Condition filter means the loop tries to embed sub-folders or stray non-spreadsheet files returned by list-directory. Check {{ entry.type }} and the file extension before calling the child.
  • Schedule timezones bite. A cron of 0 6 * * 1-5 fires at 6am in the timezone you set, so confirm the IANA value matches where your reports are produced, or a run may start before the files arrive.

Testing

Before turning the schedule on, validate end to end on a small scope. Place one known spreadsheet in the FTP folder, open the child embed-one-ftp-report workflow, and use the Run button on its Manual trigger with an input that points at that one file and its document type. Confirm the document appears with READY status in the collection. Then run the parent workflow manually once and watch the execution history: you should see one child execution entry per matching file and a chunk count returned from each. Only after a clean manual pass should you enable the Schedule trigger so it begins running on its own.

Learn More

Did this answer your question? Thanks for the feedback There was a problem submitting your feedback. Please try again later.