Workspaces
Search
nace search and nace qa answer questions from the files in a workspace that are ingested. Each creates a job, waits for it, and prints the answer and the evidence it cites. Pricing is to be announced. Automatic searches are limited to 60 per account every 10 minutes: past that, a command exits 1 with 429 rate_limited, and stderr says when to run it again. See Search.
Automatic search
Use --mode auto for general questions or --mode agent for totals, counts, complete lists and questions that join several files. Fast search (--mode fact) is for a fact stated in the documents: it can return a successful job with an incomplete or incorrect count or calculation. Exit code 0 confirms the job finished; it does not verify the answer.
nace search "What were total liabilities at year end?" --path-prefix reports/2025
# Total liabilities were 4,215,300 USD at 31 December 2025.
# evidences (1):
# 1. reports/2025/annual-report.pdf, page 12
# Total liabilities 4,215,300
nace search "Which invoices from Q4 are over 10,000?" --mode agent -o result > answer.jsonnace search QUERY answers one question, with no follow-ups. Stdout gets the answer as the ndi CLI printed it, in this order:
clarification: <text>, when the agent says how it read an ambiguous question.- The answer. With
--output-schema, the answer is thestructured_answeras JSON. evidences (<n>):, even when there are none, then each evidence numbered as<n>. <path>, with, page <page>when it has one, and its quote on the next line, indented three spaces.receipts: <n>, when an agent answer ran SQL.- For a fact answer, the Ground jobs that locate the evidences. See below.
- Each table the answer refers to, and the catalog the agent answered from, if any. See Tables and catalogs.
Where each evidence is in its file depends on the route that answered:
- A fact answer prints
grounding_job_ids (poll each with nace job <id>):and each Ground job's id, indented two spaces, when the search planned some;grounding_job_ids: none plannedwhen it planned none. Read each job withnace job <id> --wait -o result. - An agent answer, and every QA turn, has no Ground jobs: ground the evidences yourself. Run
nace groundon each cited file, with its quotes as targets. Each run is a Ground job, billed like any other. See Ground an agent answer yourself.
Other output:
- A search that found nothing to answer from prints
evidences (0):and still exits0. Over files that aren't ingested yet, an agent search can instead cite file status or a read error to explain why it cannot answer; those citations do not mean it read the file's content. Check each file'singestion_statusbefore searching: neither a successful search job nor a nonzero evidence count proves ingestion is complete. - A result of a kind
nacedoesn't render prints the job's line,<status> <kind> <job_id>, instead. - Stderr shows the job's status and the route that answered, as
route: fact — <reason>orroute: agent — <reason>, thenoutput job: <job_id>, the job that owns the answer's receipts.
See Automatic search for the result's fields.
| Flag | What it does |
|---|---|
--workspace ID | The workspace to search. See Choose a workspace. |
--path-prefix, --prefix PATH | Search only the files under this folder. |
--path PATH | Search this uploaded file too, by its path. Repeatable. With --path-prefix, the search covers both. |
--top-k N | How many evidences a fact answer cites, 1 to 50 (default 6). The agent ignores it. |
--mode {auto,fact,agent} | Which route answers. auto lets the document service choose; fact and agent run that route. Default auto. |
--context TEXT | Background the answer should take as given; without it, none. Not with --no-context. |
--no-context | Send an empty background: the same as --context "". |
--output-schema JSON | A JSON Schema the answer must follow: inline JSON, @FILE, a path, or -. |
--wait-seconds N | Ask Drex to hold the create open up to N seconds, 0 to 60. |
--idempotency-key KEY | Retry identical inputs with the same key to get the original job; use a new key for a changed question or mode. Without it, every run starts a new search. |
--async | Print only the job id and return at once. |
--wait-timeout SECONDS | How long to wait for the job (default 600). Past it, the command prints the job id on stdout and exits 1. |
-o, --output {auto,json,result,payload,id} | What to print: auto, the answer and its evidence; json, the whole job; result (or payload), only its result; id, only the job id. Default auto. --json is the same as -o json. |
--save PATH | Write the output to PATH instead of stdout, and print saved <path> on stderr. Not with -o id. |
Tables and catalogs
Tables. Each table the answer refers to comes after a blank line: table: <title> — <n> rows from <result_id>, with (truncated; the full result is on its receipt) when it was cut, then its columns and rows, tab-separated.
Catalogs. When the agent answered from a catalog of the workspace's documents, the catalog comes after a blank line:
matches: <n>, with(<n> files)and| confidence: <level>when the result has them.query: <the query it ran>.- Then
rows (<n>):and every row, indented two spaces, as<path>,[<component>]and(page <n>)or(pages <a>-<b>). Under each row, the values its match rests on, as<field>: <value>. - Lines that say what limits the table, such as
not exhaustive: ...,truncated: ...ornote: <n> candidate(s) withheld by access controls.
A value the extraction couldn't read says why: examined; field absent, present, not normalizable or extraction could not say. -o result has every cell, citation and column.
QA
nace qa "What was total freight spend in FY2024?"
# Total freight spend in FY2024 was 1,284,000 USD.
# evidences (0):
# session 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f
nace qa "And for FY2023?" --session 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4fnace qa QUERY asks one turn of a conversation. Every turn runs the agent, and prints as nace search does, with the turn's session_id on stderr as session <id>. Pass it as --session to follow up. While a turn is still running, the next is refused with 409 session_busy; only the API key that started a conversation can continue it. See QA for the result's fields.
When the question is ambiguous, the agent may ask back instead of answering: stdout then gets each question, numbered, with its suggested options below it as - <option>, and the command exits 0. Reply with the same QUERY, --session, and --clarification-answers holding one {"question", "answer"} per question.
| Flag | What it does |
|---|---|
--workspace ID | The workspace to search. See Choose a workspace. |
--session ID | Continue a conversation: an earlier turn's session_id. Without it, start one. |
--no-clarification | Answer with the best reading instead of asking back. |
--clarification-answers JSON | Answers to the last turn's clarifying questions, as a JSON list of {"question", "answer"}, in order: inline, @FILE, a path or -. An answer of null skips a question, and the agent states what it assumed. Needs --session; without it, the command exits 2 before any request. |
--path-prefix, --prefix PATH | Ask only about the files under this folder. Changing it starts a fresh conversation. |
--path PATH | Ask about this uploaded file too, by its path. Repeatable. With --path-prefix, the question covers both. Changing it starts a fresh conversation. |
--context TEXT | Background the agent should take as given, such as the entity or period. --context "" uses none. Not with --no-context. |
--no-context | Use no background at all: the same as --context "". |
--output-schema JSON | A JSON Schema this turn's answer must follow: inline JSON, @FILE, a path, or -. It applies to this turn only. |
--wait-seconds N | Ask Drex to hold the create open up to N seconds, 0 to 60. |
--idempotency-key KEY | Retry the same request with the same key to get the original job; use a new key for a new question. Without it, every run starts a new turn. |
--async | Print only the job id and return at once. |
--wait-timeout SECONDS | How long to wait for the job (default 600). |
-o, --output {auto,json,result,payload,id} | What to print: auto, the answer and its evidence; json, the whole job; result (or payload), only its result; id, only the job id. Default auto. |
--save PATH | Write the output to PATH instead of stdout, and print saved <path> on stderr. Not with -o id. |
Evidences and where they are
nace search and nace qa print each evidence numbered under evidences (<n>):, with its path, page and quote. Whether you also get where each quote is in its file depends on the route that answered: stderr shows it as route: fact or route: agent, and with -o result it is the result's .routing.final. Read that, not the --mode you sent: a search in auto mode can go either way, and a QA turn always comes from the agent.
| Route | Locations |
|---|---|
fact | The search already ran Ground jobs to locate the quotes, and lists them after the evidence under grounding_job_ids (poll each with nace job <id>):. Read each one. |
agent, and every QA turn | None. Run nace ground yourself on each cited file. |
Read the Ground jobs of a fact answer
nace search "What were total liabilities at year end?" --mode fact
nace job <job_id> --wait -o result > ground.json
jq '.targets[] | {id, status, location: .matches[0].location}' ground.jsonnace job --wait -o result waits for a Ground job and prints its result; one may still be running when the answer arrives. In it, a target's id is the number of its evidence in the list ("3"), or "3#1" for one part of a quote stitched together from several places. A target whose status is found has the location in matches[0].location; see Ground for its keys.
Ground an agent answer yourself
An agent answer runs no Ground jobs, so its quotes come without locations. To locate them, run nace ground once per cited file, with the file as ws:<workspace_id>/<source_file_id> and its quotes as targets. Each run is a Ground job, billed like any other. The file ids are in the result, not in the default output:
nace search "Which leases end in 2026?" --mode agent -o result > answer.json
jq -r '.output.answer.evidences | to_entries[] | "\(.key + 1)\t\(.value.source_file_id)\t\(.value.page)\t\(.value.quote)"' answer.json
nace ground ws:<workspace_id>/<source_file_id> --targets '[{"id": "1", "text": "<quote>", "hint": "page 3"}]' --max-matches 1For a QA turn, the evidence is under .answer.evidences instead. Give each target its evidence's number as the id, so you can match the results back, and its page as a hint when it has one. An agent may join parts of a passage with …, and the whole quote then matches nowhere: send each part as its own target, 1#0, 1#1 and so on.