Per-Row Dynamic Metadata Filters in Agentic Table

4 min read

Configure Agentic Table column search filters that resolve per row at run time, so different sheets (or rows) can search different slices of the knowledge base from a single shared pipeline config.

The problem this solves

An Agentic Table space shares one pipeline config across every sheet in the space. The search filter (search_config.metadata_filter) therefore lives at the space level: one space = one static filter. If several sheets in the same space each need to search a different slice of the knowledge base — for example "only documents valid as of this sheet's cutoff date" — a static filter cannot express it, especially when sheets are created programmatically via API.

Per-row dynamic metadata filters fix this by letting the filter reference a token instead of a hardcoded value. The token is resolved from the metadata of the row being processed, at run time.

How it works

The filter references a token instead of a hardcoded value, and the token is resolved from the row's metadata at run time. Walking through it with one running example — "only search documents valid as of this sheet's cutoff date":

1. Write a token in the filter. In the column's metadata_filter, put a <row.metadata.KEY> token in the value field instead of a literal value:

json
"metadata_filter": {
  "path": ["validAsOf"],
  "operator": "greaterThanOrEqual",
  "value": "<row.metadata.cutoff_date>"
}

2. Set the value as metadata. Set cutoff_date as sheet metadata (applies to the whole sheet) or row metadata (per row), via the sheet-creation UI or the metadata API:

text
cutoff_date = 2026-01-01T00:00:00Z
Screenshot 2026-08-04 at 14.54.34.png

3. Sheet metadata materializes onto rows. When a row is created, the sheet's metadata is copied onto it; whenever sheet metadata changes, node-chat re-syncs it to every row. Row metadata is therefore the ground truth at processing time.

4. Token resolves at time of search. When a cell is processed, the Agentic Table logic replaces <row.metadata.KEY> in the filter with the current row's metadata value, then runs the search with the resolved filter:

json
"value": "<row.metadata.cutoff_date>""value": "2026-01-01T00:00:00Z"

Because sheet metadata is automatically copied to every row, setting a value once per sheet covers the per-sheet use case for free. You only use row metadata directly when you want to override individual rows.

Configuration

1. Space pipeline config (once)

In the space's search_config, reference the token in the filter value:

json
"search_config": {
  "scope_ids": ["scope_xxxx"],
  "metadata_filter": {
    "path": ["validAsOf"],
    "operator": "greaterThanOrEqual",
    "value": "<row.metadata.cutoff_date>"
  }
}

More filter shapes you can use in metadata_filter:

Static value (no token) — a literal value passes through unchanged:

json
"metadata_filter": {
  "path": ["validAsOf"],
  "operator": "greaterThanOrEqual",
  "value": "2026-01-01T00:00:00Z"
}

Nested and / or with tokens — tokens resolve anywhere in the UniqueQL structure, so you can mix tokenized and static conditions:

json
"metadata_filter": {
  "and": [
    {
      "path": ["validAsOf"],
      "operator": "greaterThanOrEqual",
      "value": "<row.metadata.cutoff_date>"
    },
    {
      "path": ["fund"],
      "operator": "equals",
      "value": "<row.metadata.fund_id>"
    }
  ]
}

2. Per sheet

Set the sheet metadata key referenced by the token. However it is set, node-chat materializes it onto every row of the sheet. There are two ways to do this:

Option A — Sheet-creation UI

When creating a sheet in the Agentic Table, set the sheet metadata (e.g. cutoff_date) in the sheet-creation flow. This is the simplest path for users creating sheets manually and requires no API access.

Option B — API

For programmatic / bulk sheet creation, set the metadata via the existing createMagicTableSheetMetadata / createAndDeleteManyMagicTableSheetMetadata mutations. No new API surface is required.

text
cutoff_date = 2026-01-01T00:00:00Z

3. Per row (optional override)

To make a single row search a different slice, override that row's metadata via the row-metadata API (for example a different cutoff_date per fund or per question). All other rows continue to use the value inherited from the sheet.

Applying metadata changes: re-run the row

The <row.metadata.KEY> token is resolved only when a row is processed, not when metadata is saved. Adding or changing metadata (sheet or row) persists immediately to the database but does not re-execute the search on existing cells on its own.

After changing metadata that a filter token depends on, the user must Re-run Row for the new value to take effect. Existing answers are not recalculated automatically.

Ways to trigger a re-run (all re-fetch the row's metadata and re-resolve the token before searching):

  • UI — row context menu → Re-run Row.

  • GraphQLrerunDueDiligence(dueDiligenceId, rowOrder).

  • Public APIPOST /magic-table/:tableId/row/:rowOrder/rerun.

Re-run operates on the whole row; there is no single-cell re-run. Setting metadata before the row is first processed needs no extra step — the token resolves on that initial run.

Token reference

Token

Resolved from

Granularity

<row.metadata.KEY>

The current row's metadata (inherited from sheet metadata, or overridden per row)

Per row (and therefore per sheet)

This token composes with the platform's existing Smart Rules variables (<T-N>/<T+N>, <userMetadata.KEY>, <toolParameters.KEY>). On the subagent path the platform tokens still resolve afterwards.

Value handling and formats

  • Dates are normalized to YYYY-MM-DDTHH:MM:SSZ. Both YYYY-MM-DD and full ISO 8601 inputs are accepted.

  • Fail-open on missing/invalid values. If the referenced metadata key is missing or its value cannot be parsed, that filter statement is dropped and a warning is logged. The search runs as if the condition were not there — this avoids silently returning zero results for the cell.

  • Static filters are untouched. Filters with no tokens pass through unchanged.

  • Nested logic is supported. Tokens are resolved throughout the UniqueQL structure, including nested and / or statement lists.

Column type coverage

Token resolution is wired into both Agentic Table column paths:

  • Custom columns — the resolved filter is merged before the exclude_content_ids / scope_ids AND-merge.

  • Subagent columns — the resolved filter is AND-merged into scope_rules.

Worked example: per-sheet cutoff date

  1. Space config uses "value": "<row.metadata.cutoff_date>" with operator greaterThanOrEqual on path validAsOf.

  2. Sheet A sets cutoff_date = 2026-06-30; Sheet B sets cutoff_date = 2026-12-31 (via the sheet-creation UI or the API).

  3. Cells in Sheet A only cite documents valid on/after 2026-06-30; cells in Sheet B use the later cutoff — from the same space and the same pipeline config.

  4. To special-case one question, override cutoff_date on just that row, then re-run the row; only that row's citations shift.

Out of scope

  • <row.COLUMN_NAME> tokens that read cell values (free-text date parsing from row cells).

  • <T-N> relative-date enrichment for column-level filters.

Last updated