Skip to content
← ALL FIELD NOTES
/9 min read/Rasul Kireev

How to choose an index column for agent-managed rows

Pick an index column agents can safely use to find, update, and link Rowset rows without guessing.

Choose an index column that uniquely identifies the same real-world row every time an agent comes back to it. Good index columns are stable, required, unique, human-recognizable, and unlikely to be rewritten by normal workflow updates. Use sku, email, slug, task_id, or external_id when those values already exist. Let Rowset generate rowset_id when no natural key is trustworthy.

For agent-managed rows, the index column is the practical answer to one question: how should the agent find this exact row again later? If the answer is clear, row updates are safer. If the answer is fuzzy, the agent has to search, guess, or rely on an internal row id that may not be present in the user's source system.

The short rule

Use the most stable business identifier the agent and the upstream workflow both recognize. If a product catalog already has sku, use sku. If a contact list uses email addresses as the real lookup handle, use email. If a content queue uses URL slugs, use slug. If the source has no reliable identifier, omit index_column and let Rowset add a generated rowset_id.

This mirrors the database idea behind primary keys. PostgreSQL describes a primary key as the column or columns that can identify rows, and says those values must be unique and not null (PostgreSQL docs, 2026). Rowset's index column is not a general SQL primary-key interface, but the same operating principle matters: an agent needs a non-blank value that points to one row and only one row.

In Rowset, that choice controls by-index operations in both hosted MCP access and the Dataset API. When the agent has the stable value, it can call by-index read, update, image, relationship, and lookup paths without first listing every row.

Why index choice matters more for agents

Humans can usually recover from messy row identity. They scan a table, notice two similar names, ask a teammate, or decide which record looks right. An agent does not have that same background context unless you put it in the dataset.

A weak index column creates three common failure modes:

  1. The agent updates the wrong row because two rows look similar.
  2. The agent creates a duplicate because it cannot tell an existing row is the same real-world item.
  3. The agent avoids updating rows directly and falls back to broad search or manual review.

Rowset is designed to make the safer path easy. A dataset response includes the headers, index column, semantic column schema, dataset instructions, metadata, and relationship summaries. MCP tools also expose names, descriptions, and input schemas to clients, which is exactly the kind of context an agent needs before it acts (MCP tools specification, draft).

The index column is the smallest part of that context, but it is usually the part that decides whether an update is deterministic.

A practical decision checklist

Use this checklist before creating an agent-managed dataset.

  1. Is the value unique? One index value should map to one row inside the dataset. If two contacts can share a family email address, email may not be safe for that dataset.
  2. Is the value required? Blank index values are not useful for row lookup. If the source often omits the field, choose another column or generate an index.
  3. Is the value stable? Status, score, owner, priority, title, and price change during normal work. They should not identify the row.
  4. Does the agent naturally know the value? If users ask "update task T-104," then task_id is better than an internal database id nobody says out loud.
  5. Does the value survive exports and imports? A good index should remain present when rows move through CSV, JSONL, SQLite, Parquet, API calls, or an agent's own scratch files.
  6. Will the value work in relationships? If another dataset needs to point at this row, choose a value that can be stored clearly in that other dataset.

If a candidate fails any of those tests, it can still be a useful column. It just should not be the index.

Good index columns by workflow

The right index depends on the job the dataset is doing.

Workflow Good index Usually avoid Why
Product catalog sku, product_id, external_id name, price, category Products need a stable handle even when names or prices change.
Personal CRM email, person_id, contact_id name, company, last_contacted Names collide and companies change; a contact id or email is easier to update by meaning.
Content pipeline slug, content_id, brief_id title, status, owner Titles and statuses move during editing, while slugs or ids anchor the piece.
Feedback triage feedback_id, ticket_id, source_id message, sentiment, priority Feedback text and priority are the thing being interpreted, not the row identity.
Agent task board task_id, issue_key title, assignee, state Task names can be rewritten; task ids make status updates precise.
Research notes source_url, note_id, citation_key summary, topic, rating The source or note id survives re-summarization better than derived analysis fields.

These examples are deliberately boring. A good index column should be boring. It is not the most descriptive column in the table. It is the value you trust when the agent needs to say, "this row, not a similar row."

When to let Rowset generate rowset_id

Let Rowset generate rowset_id when the dataset does not have a natural key you trust. In the Dataset API, omitting index_column causes Rowset to add a generated rowset_id column so the dataset is ready for row operations immediately.

Generated indexes are useful for:

  • quick scratch datasets from messy source material
  • research tables where the source has no stable id
  • one-off review lists that still need safe updates
  • imported rows where the apparent identifier is optional or duplicated

The tradeoff is that rowset_id is Rowset-owned identity. It is stable inside the Rowset dataset, but it may not mean anything to the upstream system unless you export it and keep it with the source. If the upstream workflow already has a durable id, use that instead.

Rowset treats generated index columns as managed metadata. Generated indexes cannot be renamed, and generated index values cannot be rewritten to arbitrary custom values. That guardrail keeps the row identity from drifting after agents start using it.

What not to use as the index

Do not use a column that describes the row's current state instead of its identity.

Avoid:

  • status, because it is supposed to change
  • priority, because agents may reorder work
  • owner, because ownership changes
  • title or name, because humans rewrite them
  • description, because it is too long and too likely to change
  • price, score, or rating, because those are measurements
  • image or audio columns, because Rowset stores private assets as managed metadata

Rowset rejects image and audio columns as dataset indexes. Asset cells are meant to hold private asset:{key} references after a file is attached, not a stable row identifier.

Also be careful with email addresses. email is often a strong index for a personal CRM, but it is not universal. Use person_id or contact_id when a person can have multiple emails, shared inboxes matter, or the upstream CRM already has a durable contact id.

How the index works with relationships

Relationships in Rowset use index values. One dataset can store another dataset's row index value and Rowset can resolve the link through MCP or REST.

For example, a personal CRM might use:

  • People.person_id as the People dataset index
  • Messages.message_id as the Messages dataset index
  • Messages.person_id as the source column that points back to People

With relationship integrity enabled, Rowset can reject non-blank relationship values that do not match an existing target row index. That makes the target dataset's index part of your data model, not just a convenience for lookup. For a deeper walkthrough of when to split datasets and enforce those links, read How to model relationships between agent-managed datasets.

This is another reason to avoid display names as indexes. If People.name is the target index, a name change can break message links. If People.person_id is the target index, names can change while the relationship stays intact.

How to tell an agent what to do

The index column should be explicit in the setup prompt or dataset instructions. Agents should not infer row identity from whichever column looks important.

A good instruction is narrow:

Use sku as the stable index column. Before updating a product row, call
get_dataset, confirm the headers and instructions, then update by index_value.
Do not use name or price to identify products because both can change.

For a task board:

Use task_id as the stable index. When I ask for a status change, update the row
by task_id. If a task has no task_id, create one before using the row in later
updates.

This is also where agent discovery matters. The agent should inspect the dataset before mutation so it sees the current index column, schema, instructions, relationships, and allowed choices.

The simplest safe pattern

For a new Rowset dataset, start with this pattern:

  1. Choose the stable business key if one exists.
  2. Put that key in index_column at creation time.
  3. Add column descriptions for ambiguous fields.
  4. Store workflow rules in instructions or metadata.
  5. Tell the agent to call get_dataset before row mutations.
  6. Use by-index row operations when the user or source system provides the stable value.

If step 1 is uncertain, do not force it. Let Rowset generate rowset_id, then add a better business key later when the workflow proves one exists. For the narrower tradeoff between generated Rowset identity and source-system identity, use the guide to Rowset rowset_id vs business keys.

The goal is not a clever schema. The goal is a dataset an agent can operate on without guessing which row the user meant.

This matters most when a workflow outgrows a spreadsheet. The guide to Google Sheets alternatives for AI-agent-managed datasets explains when a human-edited sheet should stay in Sheets and when the agent-operated rows should move into a private Rowset dataset.

FAQ

Is an index column the same as a database primary key?

No. A Rowset index column is the dataset-level row identity used by Rowset's MCP and REST workflows. It follows the same practical rule as a primary key, unique and non-blank values identify rows, but Rowset is not asking you to model a full relational database.

Should I use rowset_id or my own id?

Use your own stable id when it exists and the agent will know it later. Use Rowset's generated rowset_id when the source data has no reliable identifier, has duplicated values, or has optional ids that would make by-index updates unsafe.

Can the index column change later?

Some schema changes are possible, but changing row identity after agents have started using a dataset is risky. Treat the index as part of the workflow contract. If you are unsure, start with generated rowset_id and keep the candidate business key as a normal column until it proves stable.

Can an index value be blank?

No. For explicit index columns, Rowset requires a non-blank value when creating or updating rows. A blank index would give the agent no safe way to find that row by meaning.

Why not always use an internal id?

Internal ids are safe inside one system, but agents often receive instructions from humans, source files, tickets, URLs, or external systems. A useful index is the stable value the workflow naturally carries. Use an internal id when that is the value the workflow already knows; otherwise prefer the real business key.