Workspaces
Navigate tools
Give your own code agent the tools the search agent works with - locate, read-file and run-sql, plus folder-metadata and catalog for questions about the whole workspace - over a workspace's ingested files.
Search answers a question for you. The navigate tools let your own agent find the answer itself, with the tools the document service's search agent works with:
- Locate names the pages and tables most likely to hold a piece of information. A decision model walks the workspace's files, sections and pages, built at ingestion, and answers with each piece, the read that opens it and its opening text, then the tables to query. It also runs a workspace search on the need, so an exact name, number or phrase leads it to the file that holds it.
- Read-file returns a file's text: all of it, one tab or section, some pages, or a span of lines.
- Run-sql runs one read-only
SELECT(DuckDB dialect) over the workspace's tables.
Two more answer questions about the workspace as a whole, which no single page holds:
- Folder-metadata describes a folder without reading its files: how many it holds, their counts per category and ingestion status, its subfolders and one page of its files' paths.
- Catalog queries the fields ingestion extracted from every document: one table per document type (
invoice,contract, ...), for questions asking for every document that meets conditions, such as each invoice over an amount.
Each answers inline, with nothing to wait for, and reads only files that are Ready. They are free. Call them over HTTP or with the nace CLI; the Python and TypeScript SDKs and the MCP server have no method for them. Locates are limited to 150 per account every 10 minutes, and file reads, SQL queries, folder listings and catalog queries together to 600. For a code agent such as Claude Code, Codex, Cursor or Pi, install the agent skill: it teaches the agent the loop below with the nace CLI.
Search or navigate tools
Search (automatic_search, qa) | Navigate tools (locate, read-file, run-sql, folder-metadata, catalog) | |
|---|---|---|
| Who searches | The document service's search agent | Your own agent |
| What comes back | An answer with cited evidence | Pages, text and query results; your agent reads them, decides and cites |
| Calls per question | One job | Several quick calls, each answered inline |
| Price | To be announced | Free, within the limits above |
| Use it when | You want the answer | Your agent should steer the search, check each page itself, or use what it finds in its own work |
| From a code agent | The MCP server's automatic_search and qa, or nace search and nace qa | nace locate, nace read-file, nace run-sql, nace folder-metadata and nace catalog, with the agent skill |
Both read the same ingested files, so a workspace set up for one works with the other.
The loop
- Locate the question: send what it needs as
need, and the whole question asquestion. - Read the pages it names with read-file, exactly as it names them: by
pagesfor a paged document, byline_startandline_end(andcomponent) for a text file or a tab. - Query a table it names with run-sql, under its
sql_tablename. When the answer needs every file of a kind (a count, a list or a total over each invoice, statement or contract), locate that kind once withevery: true:populationlists the members, and you read each. - Locate again for a part still missing, naming the gap in a few words. Locate keeps no memory between calls: send back the pieces earlier calls offered as
excludeand what you read asalready_read, and it shows something new. ThenaceCLI keeps that memory for you. - Stop when every figure comes from a page you read or a query you ran.
Locate
curl "https://console.nace.ai/v1/workspaces/$WORKSPACE_ID/tools/locate" \
-H "Authorization: Bearer $NACE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"need": "total liabilities at year end 2024",
"question": "How did total liabilities change from 2023 to 2024?",
"exclude": [{"path": "reports/2024/annual-report.pdf", "number": 41}]
}'text is the answer as the search agent reads it, and pages, tables and population hold the same as fields. It gives the best pages in full and the rest by their opening lines; send "pointer": true to name every page by its opening lines only, as a task's later locates should, so page text does not pile up in an agent's context. Its reads are written as ndi read-file ..., the document service's own CLI; nace locate prints them as nace read-file ..., with the same arguments. The first locate after the workspace's files change reads them first and can take a minute or more. A workspace whose files are kept in your own storage can't be located (422). See Locate information.
Read a file
curl "https://console.nace.ai/v1/workspaces/$WORKSPACE_ID/tools/read-file" \
-H "Authorization: Bearer $NACE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"path": "reports/2024/annual-report.pdf", "pages": [41, 42]}'A file with several tabs or sections answers with each under a header line naming it. truncated says max_chars (200,000 by default) cut the text, and sql_tables names the tables holding the rows of the long tables printed. A file that isn't ingested yet answers 409 file_not_ingested. See Read a file.
Run a SQL query
curl "https://console.nace.ai/v1/workspaces/$WORKSPACE_ID/tools/run-sql" \
-H "Authorization: Bearer $NACE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"sql": "SELECT account, amount FROM tb_2024_trial_balance WHERE amount > 10000"}'The answer holds the first rows. Every result is kept:
result.handle(res_…) is a table the next query in the same workspace may join, total or page withLIMITandOFFSET. It resolves for any caller that sees the same tables of that workspace, such as another key of your account or a member you invited, and never in another workspace or account.result_citation.result_fileis the whole result as a Parquet file: download it fromdownload_urlwithout the API key untildownload_url_expires_at. It is not one of the workspace's files.
Table names come from locate's tables, read-file's sql_tables, and the refusal of a query that names an unknown table, which lists them all. See Run a SQL query.
Timeouts and retries
A tool call keeps running on the document service when the caller stops waiting. Send an Idempotency-Key (up to 200 characters, unique per account), and if a call times out, send it again with the same key and body: you get the first call's answer instead of running it twice. Drex waits up to 270 seconds for an answer and then answers 503; retry that the same way. The CLI mints the key and retries for up to 15 minutes on its own.
Each reply's job_id is the job the call ran as, and GET /v1/documents/jobs/{job_id} reads it back. The calls don't appear in Usage › Logs.
Errors
| Error | When |
|---|---|
404 workspace_not_found | The workspace isn't one you can use, or it was deleted. |
404 file_not_found | A path names no uploaded file in the workspace. |
403 access_denied | A path names a file you aren't allowed to read. |
409 file_not_ingested | Read-file on a file whose ingestion hasn't finished. |
422 invalid_request | A field breaks its rule; run-sql refused the statement or names an unknown table or handle; locate on a workspace kept in your own storage. |
429 rate_limited | Over 150 locates, or 600 file reads, SQL queries, folder listings and catalog queries together, for the account in 10 minutes. Wait retry-after seconds. |
503 service_unavailable | The document service didn't answer in time, or is down. Retry with the same Idempotency-Key. |
Every other error is on Errors.
Describe a folder
curl "https://console.nace.ai/v1/workspaces/$WORKSPACE_ID/tools/folder-metadata" \
-H "Authorization: Bearer $NACE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"directory": "invoices", "recursive": true}'The answer counts every file in scope (overall_files, with counts per category and ingestion status), names the folder's subfolders, and lists one page of its files' paths (file_entries, files_truncated when there are more). It covers the folder's own files unless a narrow (category, ingestion_status, kind, name_contains) or recursive is given. To find what a folder's files say, locate inside it with path_prefix. See Describe a folder.
Query the metadata catalog
curl "https://console.nace.ai/v1/workspaces/$WORKSPACE_ID/tools/catalog" \
-H "Authorization: Bearer $NACE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"sql": "SELECT source_path, page_start, total_amount FROM invoice WHERE total_amount > 50000"}'Without sql, the answer lists the catalog's tables: catalog_document, with a row per document section or tab, and one table per document type the workspace holds, with its typed fields and record count; empty_tables names the types with no records here. With sql, it runs one read-only SELECT (DuckDB dialect) over them: columns and at most 200 rows, with truncated when there were more. Each row can name its source_path and page_start, for read-file. The rows are what ingestion extracted, so read the page before a figure goes into an answer. See Query the metadata catalog.