Files and imports
With AgentDB you can:
- keep files next to your records, such as a contract PDF on a deal;
- share one file through a link that expires;
- import a spreadsheet of contacts without pasting it into a chat;
- export your data at any time.
Your AI does most of this for you. This page shows the calls it makes, so you know what happens.
#Upload a file
Your AI sends a small file as base64 with files_upload. It can attach the file to a record in the same call.
{"tool": "files_upload", "arguments": {"filename": "notes.txt", "content_type": "text/plain", "content_base64": "SGVsbG8gZnJvbSBFeGFtcGxlIEx0ZC4K", "folder": "notes", "tags": ["example"]}}The answer holds the file id, its size, its SHA-256 and its status.
- Size: inline uploads go up to 4 MiB by default.
workspace_infoshows the exact limit. - Bigger files: the REST API and the CLI upload in two steps, and resume large uploads in parts.
- Content never changes. To change a file, upload a new version. The file id stays the same.
- Folders and tags help you find files later. A folder is a label such as
contracts/2026.
From a terminal, the CLI uploads a file from disk: agentdb files upload ./contract.pdf --record rec_... --role contract.
#Attach a file to a record
One file can belong to several records. Each attachment has a role, such as invoice_pdf or photo.
In practice your AI attaches files to records you already have. The example first creates a client record:
{"tool": "schema_define_object", "arguments": {"name": "client"}}{"tool": "schema_define_field", "arguments": {"object": "client", "name": "name", "type": "text", "unique": true}}{"tool": "records_create", "arguments": {"object": "client", "data": {"name": "Example Ltd"}}}{"tool": "files_attach", "arguments": {"file_id": "$FILE_ID", "record_id": "$CLIENT_ID", "role": "contract"}}files_list with a record_id shows the files of one record. files_detach removes an attachment and keeps the file.
#Download a file
files_download returns the bytes as base64. Your AI also sees images as images.
{"tool": "files_download", "arguments": {"file_id": "$FILE_ID"}}#Share a file with a link
A signed link lets someone open one file without an API key. Use it for a dashboard, an email or a web page.
{"tool": "files_link_create", "arguments": {"file_id": "$FILE_ID", "expires_in_seconds": 3600}}- Expiry: from 60 seconds to 7 days. The default is 1 hour.
- Who can open it: anyone who has the link, until it expires.
- Stop it early:
files_link_revokeends the link at once. Deleting the file ends it too. - Access follows you: if you lose access to the file, your links stop working.
- Inline display: only images, audio and video open in the browser. Other files always download.
#File types and media
AgentDB accepts the file types it can verify. That includes images, PDF, Office documents, text, CSV, JSON, audio and video.
- AgentDB checks the first bytes of every upload against the declared type.
- A file that does not match is refused with
CONTENT_MISMATCH. - HTML, SVG and program files are refused by default.
- For images, audio and video, AgentDB reads the size and duration. You find them in the file's
metadata. - Text files are indexed.
files_searchfinds words in file names and in text content.
See File types for the full list.
Store only synthetic or non-sensitive files while the service is in beta.
#Import a CSV, JSON or JSONL file
You can import hundreds of rows in one call. The file goes straight to AgentDB over HTTPS. It does not pass through the chat.
The steps:
- Your AI defines the object and a unique field to match on, such as
email. - It calls
imports_startand gets a one-time upload link. - It uploads the file to that link. Or it gives you a browser link to drop the file.
- It calls
imports_inspectto see the columns, types and possible problems. - It calls
imports_runwithdry_run: truefirst. Then it runs the import for real.
The upload link works once, for 30 minutes. It is not an API key and cannot read data.
{"tool": "imports_start", "arguments": {"filename": "contacts.csv"}}Your AI then uploads the file with the upload_url from the answer:
curl -sS --fail-with-body -T contacts.csv '<upload_url>'A small file can also go through files_upload. The import tools accept its file_id. The next examples use that route.
{"tool": "schema_define_object", "arguments": {"name": "contact"}}{"tool": "schema_define_field", "arguments": {"object": "contact", "name": "name", "type": "text"}}{"tool": "schema_define_field", "arguments": {"object": "contact", "name": "email", "type": "email", "unique": true}}{"tool": "files_upload", "arguments": {"filename": "contacts.csv", "content_type": "text/csv", "content_base64": "bmFtZSxlbWFpbApBZGEgTG92ZWxhY2UsYWRhQGV4YW1wbGUuY29tCkdyYWNlIEhvcHBlcixncmFjZUBleGFtcGxlLmNvbQo="}}The file holds two rows: Ada Lovelace (ada@example.com) and Grace Hopper (grace@example.com).
{"tool": "imports_inspect", "arguments": {"file_id": "$CSV_ID", "object": "contact"}}imports_inspect reports per column: filled and empty counts, duplicates, the detected type and sample values. It also suggests match keys and spots spelling variants.
{"tool": "imports_run", "arguments": {"file_id": "$CSV_ID", "object": "contact", "match_on": "email", "dry_run": true}}A dry run does the whole import and then rolls it back. The report shows exactly what a real run would do.
{"tool": "imports_run", "arguments": {"file_id": "$CSV_ID", "object": "contact", "match_on": "email"}}How an import behaves:
- Matching: a row with a new
emailcreates a record. A knownemailupdates that record. - Errors: each failed row is listed with its line, identifier, field and error code.
- Partial or all-or-nothing: by default valid rows are imported. With
atomic: true, one failed row stops the whole import. - Links:
linksconnects each row to an existing record, such as a contact to its company. - Missing link targets: AgentDB never invents a missing company.
on_unresolved_linkdecides what happens to that row. - Messy values: AgentDB never changes values by itself. It suggests fixes, and applies only the
normalizerules you approve. - Large files: one call handles up to 10,000 rows. Continue with
rows.offsetfor the rest. - Retries: run the same import again and nothing is duplicated. Rows report
unchanged.
From a terminal: agentdb import contacts.csv --object contact --match-on email --dry-run.
#Export your data
Owners and admins can export records, links, schema and file metadata at any time. The export is NDJSON: one JSON object per line.
curl https://app.agentdb.link/v1/workspaces/$AGENTDB_WORKSPACE/export \
-H "Authorization: Bearer $AGENTDB_TOKEN"?objects=contact,companylimits the export to some objects.?format=bundlereturns a.tar.gzthat also holds the file bytes.- Your AI can call
records_exportfor small exports, up to 2 MiB. - From a terminal:
agentdb data-export --output backup.ndjson, or add--bundlefor files too.
workspace_import loads an export into a new workspace. It never merges into an existing one.