Chat with the research agent

Ask why a value says what it says, or request a re-check — visibly, in the customer's own thread

The dataset is the deliverable, but the research agent is what can explain or correct a cell. When your user asks "why does this say $2.4B?" or "that funding number looks stale", you don't have to guess — ask.

Needs runs:write to send and runs:read to read (both in the Agent preset), at any role in the organization: a viewer may ask, exactly as in the app.

Renaming a row (a change to its name) always waits for confirmation. Once applied, later research that finds the row under its old name updates this row rather than adding a new one, and the rename appears in GET /v1/changes (by: "user"), where it can be undone. A new name another row already has is refused: mark the two as duplicates instead. A name that only resembles another row's waits with the warning name_matches_another_row. A change the agent proposes on its own (initiated_by: model, rather than one you asked for) always waits (status: pending_confirmation, warning model_proposed). Nothing is written, and no cell is held, until someone applies it; dismissed or expired, nothing is written at all. A re-check it proposes starts its paid run only once applied.

Every change proposed in chat comes back pending and needs confirming, including one you clearly asked for: it waits with warning confirm_required ("Changes from chat wait for your OK."), or model_proposed when the agent proposed it on its own. Nothing is written, held or started until you apply it with POST /v1/chat/actions/{action_id}/confirm (MCP confirm_chat_action); a re-check starts its paid run only then.

Applying a change the agent proposes, or reverting one, needs data:write too (in the Agent preset). A key without it still gets answers, but every change a turn proposes waits (status: pending_confirmation, warning no_data_write) for a member of the organization to apply it. A viewer's data:write never takes effect, so a viewer's changes always wait, and a re-check a viewer asks for is refused (it starts a paid run). Any role may dismiss a waiting change: nothing is written.

Ask a question

bash
curl -s -X POST $BASE_URL/v1/research/runs/{run_id}/chat/messages \
  -H "Authorization: Bearer $DEEPSIEVE_API_KEY" -H "Content-Type: application/json" \
  -d '{"content": "Where did the 2024 funding figure come from? Please re-check it.",
       "row_ref": {"table_name": "companies", "record_id": "<uuid>"}}'
Response· json
{"object": "chat_message", "message_id": "…", "status": "running",
 "note": "Your message is visible in the customer's own chat history for this
          report, attributed to this API key."}

row_ref is optional — omit it to ask about the report as a whole.

Chat requires an active plan. A free run previews ten of its rows, and the agent answers from the whole dossier — so this endpoint is 402 on an account without one, including a closed account inside its read-retention year. The refusal happens before any work is started, so it costs nothing and is safe to retry after subscribing. It is not retriable on its own: treat it like the other 402s and surface it to a human.

Read the thread

bash
curl -s $BASE_URL/v1/research/runs/{run_id}/chat \
  -H "Authorization: Bearer $DEEPSIEVE_API_KEY"
Response· json
{"object": "chat_thread", "in_flight": false,
 "messages": [
   {"role": "user", "content": "Where did the 2024 funding figure come from?",
    "sent_via": "api", "sent_by_key": "claude-code", "status": "complete"},
   {"role": "agent", "content": "The $2.4B figure comes from…",
    "status": "complete", "actions": [
      {"id": "…", "type": "reverify", "summary": "Re-verifying total_funding"}]}
 ]}

Poll while in_flight is true (a turn takes seconds, not minutes). Answers that changed data list them under actions — each revertible:

bash
curl -s -X POST $BASE_URL/v1/chat/actions/{action_id}/revert \
  -H "Authorization: Bearer $DEEPSIEVE_API_KEY"

Changes that wait for confirmation

Every change proposed in chat comes back with "status": "pending_confirmation" and a warnings list, and nothing is written until someone decides. Besides the warning that says why it waits for an OK, a check may add one about the data for the person to weigh:

json
{"id": "…", "action_type": "update_cell", "status": "pending_confirmation",
 "column_name": "fee", "old_value": "70", "new_value": "60",
 "initiated_by": "user", "expires_at": "2026-10-02T12:00:00Z",
 "warnings": [{"code": "confirm_required", "message": "Changes from chat wait for your OK."},
   {"code": "conditional_adjustment",
   "message": "The cited page states an adjustment of exactly this difference, so the current value may already include it."}]}

These say who asked, and never reach the data:

  • confirm_required: the agent says you asked for this change; every change from chat waits for your OK.
  • model_proposed: the agent proposed it on its own.
  • no_data_write: the asker cannot change data, so it waits for a member.

These are about the data:

  • outside_allowed_sources: every source cited is outside the run's allowed sources.
  • conditional_adjustment: the cited page states an adjustment of exactly this difference.
  • sibling_value: the cited page prints both values for different cases.
  • unit_conversion: the new value is the old one in another unit.
  • terminal_column: the column normally changes only through a full re-research.
  • identity_column: the change would change which record the row is.

Read the warnings, then apply the change anyway or decline it:

bash
curl -s -X POST $BASE_URL/v1/chat/actions/{action_id}/confirm \
  -H "Authorization: Bearer $DEEPSIEVE_API_KEY"
curl -s -X POST $BASE_URL/v1/chat/actions/{action_id}/dismiss \
  -H "Authorization: Bearer $DEEPSIEVE_API_KEY"

Confirming re-validates the proposal and re-runs every check first, fetching the cited pages again. It returns 409 conflict if the change can no longer apply as proposed: the cell changed, the record, table or column is gone, or the change expired. The change then stops waiting. A waiting change expires after seven days, or as soon as a later change to the same cell is applied, and then reads "status": "dismissed". A dismissed change keeps its proposed value as a record, unless the value came only from a source outside the allowed sources; that value is not kept. A change applied anyway records the warnings it was applied despite on the new value's evidence, as its verdict_note: only warnings about the data, never confirm_required, model_proposed or no_data_write (they are about who asked), and never for a re-check, which writes no value.

Applying a waiting re-check starts a paid research run, so it also needs runs:write (403 insufficient_scope without it, and nothing starts). The thread's can_apply is one flag for the thread and does not check that.

A re-check that was applied but could not start (interrupted by a restart, for example) is never left reading applied: it ends failed, and its note says it was not started and that nothing was checked or billed. It is never started again on its own. Tell your human, and ask again if they still want it checked.

initiated_by is the research agent's claim: that the person asked for this exact change (user) or that it proposed the change on its own (model). It is shown to help you decide and changes nothing about what happens: either way the change waits for your OK, and both get the same checks. After a decision, confirmed_via / dismissed_via say who made it: app for a person in the app, api for an agent's key or token.

If you are an agent acting for a person, confirm only after they have seen the warnings and decided. It is their data, and the record will say the change was applied through the API.

Your messages are visible, and attributed

This is one shared thread, not a private side channel. Everything you send appears in the customer's own Chat view for that report, labelled "Sent by your agent" with the API key's name — so a person opening their report can always tell which questions they asked and which their agent did.

Two things follow for you:

  • Write for a human audience. Your questions are read by the customer.
  • Don't narrate. Ask when you need an answer or a correction; this isn't a logging channel.

Data changes an answer applies are audited and revertible by either side, and the research agent can never edit the active Blueprint — same boundary as everywhere else.

Chat with the research agent — DeepSieve API