Free: the two fixes for "my AI Agent only reads the first row" contradict each other — here's how to tell which one you need

Hey all — the “my AI Agent only reads the first row of my Google Sheet” question comes up constantly here, and the thing that got me is that the two standard answers contradict each other:

  • the community answer: add an Aggregate node, consolidate all rows into a single item before the AI Agent
  • n8n’s own official template #2085: “because models have a context window… we can’t pass the whole Google Sheet to GPT — at least not for big sheets”

Both are correct. They just apply at different table sizes, and nothing tells you which side of the line you’re on — you find out in production when the sheet grows and answers quietly get worse.

So I built a small kit around that boundary and I’m sharing the free version.

Repo: GitHub - mad-ton/t007-table-context-router-lite: Free: the two fixes for "my n8n AI Agent only reads the first row" contradict each other — this shows both regimes and proves what the agent actually received. No API keys, no Docker, no Google account. · GitHub

What the free version is

An importable workflow where one table fixture flows down three paths side by side — broken, aggregate regime, query-tool regime — with an Audit output node that prints, for each:

  • agent_runs — did it run once, or once per row?
  • rows_in / rows_seen — did every row actually reach it?
  • context_chars vs context_budget — does the table still fit?
  • tool_called / returned_rows — did the tool run, return anything, and did the answer actually use it?

Plus a Node.js harness with 10 scenarios: 2 pass and 8 fail on purpose. The negatives are the point — a checker that cannot fail is worthless, so you can watch each check actually fire on the defect it’s meant to catch.

Setup

  1. Import templates/T007-table-context-router-LITE.json, hit Test workflow, read the Audit output for each of the three paths.
  2. node src/run.js --dir scenarios/lite — 2 pass, 8 fail, exit 0 when every scenario matched its expected outcome.
  3. node tests/harness.test.js if you want to see the checks tested themselves.

No credentials of any kind — no API keys, no Docker, no Google account. Import-verified on n8n 2.25.7.

Being straight about what it is

There’s no AI Agent node in the demo workflow and no LLM call. The three paths are Code nodes that reproduce what an agent’s item flow does to your rows. That’s why it runs with no credentials — the routing decision and the audit trace are properties of the item flow, not of the model. If you want to see the failure and the two fixes side by side, this shows you exactly that.

It asserts observable behaviour only — executed once with N rows in context, or called the tool and used the returned fact. It does not read the model’s reasoning and won’t tell you your agent is “reliable”.

The table source is a plain JS fixture node. Swapping in a Google Sheets Get Rows node is the intended path, but I haven’t run it against a live Sheets node, so I’m calling that design rather than a tested result.

Not in scope on purpose: a tool that looks connected but is unavailable internally (that’s n8n editor state — refresh/reconnect/recreate the node), and an agent that answers from memory instead of calling the tool. One kit, one root cause.

The thing that surprised me most

Row count is the wrong intuition. A 20-row table in my fixtures serialises to ~82,000 characters — bigger than the 400-row one, and 417% of a 16k-token budget. So “just aggregate, it’s only 20 rows” is wrong in a way you cannot see by looking at the sheet. Measure characters, not rows.

Happy to answer questions on any of it — and if you hit a table-context failure mode the 10 scenarios don’t cover, I’d genuinely like to hear about it.