datanotes 2.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE +9 -0
- package/README.md +207 -28
- package/SECURITY.md +92 -45
- package/dist/THIRD-PARTY-NOTICES.txt +682 -0
- package/dist/api/catalog.d.cts +69 -0
- package/dist/api/catalog.d.ts +50 -2
- package/dist/api/cli-options.d.cts +39 -0
- package/dist/api/cli-options.d.ts +39 -0
- package/dist/api/client.d.cts +89 -0
- package/dist/api/client.d.ts +19 -30
- package/dist/api/docs.d.cts +211 -0
- package/dist/api/docs.d.ts +211 -0
- package/dist/api/guidance.d.cts +81 -0
- package/dist/api/guidance.d.ts +81 -0
- package/dist/api/index.cjs +6610 -2247
- package/dist/api/index.d.cts +13 -0
- package/dist/api/index.d.ts +10 -7
- package/dist/api/index.js +6610 -2247
- package/dist/api/local.cjs +118 -6
- package/dist/api/local.d.cts +95 -0
- package/dist/api/local.d.ts +70 -6
- package/dist/api/local.js +104 -6
- package/dist/api/mcp.cjs +17384 -0
- package/dist/api/mcp.d.cts +108 -0
- package/dist/api/mcp.d.ts +108 -0
- package/dist/api/mcp.js +17334 -0
- package/dist/api/otlp.d.cts +65 -0
- package/dist/api/redact.d.cts +17 -0
- package/dist/api/redact.d.ts +17 -0
- package/dist/api/requests.d.cts +26 -0
- package/dist/api/requests.d.ts +14 -16
- package/dist/api/results.d.cts +16 -0
- package/dist/api/results.d.ts +2 -1
- package/dist/api/tokens.d.cts +7 -0
- package/dist/datanotes.cjs +62911 -28409
- package/dist/docs/administration/configuration.md +59 -0
- package/dist/docs/administration/docker.md +80 -0
- package/dist/docs/administration/git-sync.md +71 -0
- package/dist/docs/administration/limits.md +69 -0
- package/dist/docs/administration/run-the-service.md +219 -0
- package/dist/docs/administration/status.md +61 -0
- package/dist/docs/administration/use-with-obsidian.md +75 -0
- package/dist/docs/api/operations/add_column.md +49 -0
- package/dist/docs/api/operations/add_constraint.md +55 -0
- package/dist/docs/api/operations/adopt_rows.md +50 -0
- package/dist/docs/api/operations/align_relations.md +41 -0
- package/dist/docs/api/operations/alter_column.md +46 -0
- package/dist/docs/api/operations/alter_table.md +67 -0
- package/dist/docs/api/operations/batch.md +48 -0
- package/dist/docs/api/operations/changes_stream.md +28 -0
- package/dist/docs/api/operations/check_table.md +29 -0
- package/dist/docs/api/operations/clone_table.md +48 -0
- package/dist/docs/api/operations/comment_on.md +42 -0
- package/dist/docs/api/operations/configure_database.md +52 -0
- package/dist/docs/api/operations/create_table.md +78 -0
- package/dist/docs/api/operations/create_view.md +54 -0
- package/dist/docs/api/operations/create_webhook.md +37 -0
- package/dist/docs/api/operations/define_base.md +52 -0
- package/dist/docs/api/operations/delete_rows.md +43 -0
- package/dist/docs/api/operations/delete_webhook.md +31 -0
- package/dist/docs/api/operations/describe_database.md +30 -0
- package/dist/docs/api/operations/describe_history.md +40 -0
- package/dist/docs/api/operations/describe_semantic_index.md +24 -0
- package/dist/docs/api/operations/describe_table.md +38 -0
- package/dist/docs/api/operations/docs.md +13 -0
- package/dist/docs/api/operations/drop_column.md +41 -0
- package/dist/docs/api/operations/drop_constraint.md +39 -0
- package/dist/docs/api/operations/drop_table.md +43 -0
- package/dist/docs/api/operations/drop_view.md +38 -0
- package/dist/docs/api/operations/engine_status.md +23 -0
- package/dist/docs/api/operations/graph_neighbors.md +32 -0
- package/dist/docs/api/operations/graph_path.md +32 -0
- package/dist/docs/api/operations/graph_traverse.md +43 -0
- package/dist/docs/api/operations/identify_session.md +24 -0
- package/dist/docs/api/operations/infer_table.md +43 -0
- package/dist/docs/api/operations/insert_row.md +48 -0
- package/dist/docs/api/operations/list_changes.md +35 -0
- package/dist/docs/api/operations/list_folder.md +28 -0
- package/dist/docs/api/operations/list_link_targets.md +44 -0
- package/dist/docs/api/operations/list_migrations.md +35 -0
- package/dist/docs/api/operations/list_tables.md +32 -0
- package/dist/docs/api/operations/list_webhooks.md +23 -0
- package/dist/docs/api/operations/manual_index.md +14 -0
- package/dist/docs/api/operations/manual_page.md +22 -0
- package/dist/docs/api/operations/merge_rows.md +44 -0
- package/dist/docs/api/operations/move_rows.md +52 -0
- package/dist/docs/api/operations/openapi.md +13 -0
- package/dist/docs/api/operations/openapi_post.md +20 -0
- package/dist/docs/api/operations/read_note.md +29 -0
- package/dist/docs/api/operations/recompute_columns.md +44 -0
- package/dist/docs/api/operations/record_tool_call.md +36 -0
- package/dist/docs/api/operations/rename_column.md +44 -0
- package/dist/docs/api/operations/rename_value.md +45 -0
- package/dist/docs/api/operations/restore_database.md +51 -0
- package/dist/docs/api/operations/restore_table.md +46 -0
- package/dist/docs/api/operations/search_notes.md +28 -0
- package/dist/docs/api/operations/select_rows.md +61 -0
- package/dist/docs/api/operations/semantic_search.md +34 -0
- package/dist/docs/api/operations/semantic_search_docs.md +26 -0
- package/dist/docs/api/operations/set_table_bases.md +44 -0
- package/dist/docs/api/operations/status.md +13 -0
- package/dist/docs/api/operations/stop_engine.md +23 -0
- package/dist/docs/api/operations/sync_semantic_index.md +33 -0
- package/dist/docs/api/operations/table_changes.md +31 -0
- package/dist/docs/api/operations/tags/auxiliary.md +14 -0
- package/dist/docs/api/operations/tags/change-feed.md +8 -0
- package/dist/docs/api/operations/tags/history.md +17 -0
- package/dist/docs/api/operations/tags/queries.md +15 -0
- package/dist/docs/api/operations/tags/rows-dml.md +16 -0
- package/dist/docs/api/operations/tags/schema-ddl.md +22 -0
- package/dist/docs/api/operations/tags/service.md +15 -0
- package/dist/docs/api/operations/tags/tokens.md +13 -0
- package/dist/docs/api/operations/tokens_create.md +34 -0
- package/dist/docs/api/operations/tokens_delete.md +29 -0
- package/dist/docs/api/operations/tokens_list.md +21 -0
- package/dist/docs/api/operations/tokens_me.md +20 -0
- package/dist/docs/api/operations/tokens_rotate.md +29 -0
- package/dist/docs/api/operations/tokens_update.md +34 -0
- package/dist/docs/api/operations/undo_migration.md +46 -0
- package/dist/docs/api/operations/update_row.md +60 -0
- package/dist/docs/api/operations/update_rows.md +46 -0
- package/dist/docs/api/operations/vacuum_table.md +37 -0
- package/dist/docs/api.md +135 -0
- package/dist/docs/develop/build-an-app.md +320 -0
- package/dist/docs/develop/build-on-datanotes.md +138 -0
- package/dist/docs/develop/change-feed-and-webhooks.md +70 -0
- package/dist/docs/develop/client.md +116 -0
- package/dist/docs/develop/concurrency.md +153 -0
- package/dist/docs/develop/http-api.md +79 -0
- package/dist/docs/develop/telemetry.md +86 -0
- package/dist/docs/guides/agents/docs-offline.md +99 -0
- package/dist/docs/guides/agents/how-agents-use-datanotes.md +124 -0
- package/dist/docs/guides/agents/prompts.md +495 -0
- package/dist/docs/guides/agents/reading-errors.md +112 -0
- package/dist/docs/guides/data-quality/check-constraints.md +379 -0
- package/dist/docs/guides/data-quality/check-table.md +63 -0
- package/dist/docs/guides/data-quality/hand-edits.md +507 -0
- package/dist/docs/guides/data-quality/sync-between-devices.md +51 -0
- package/dist/docs/guides/data-quality/validation.md +90 -0
- package/dist/docs/guides/database-objects/bases.md +480 -0
- package/dist/docs/guides/database-objects/catalogs-and-schemas.md +897 -0
- package/dist/docs/guides/database-objects/columns.md +1332 -0
- package/dist/docs/guides/database-objects/relations.md +1454 -0
- package/dist/docs/guides/database-objects/tables.md +1404 -0
- package/dist/docs/guides/database-objects/views.md +1003 -0
- package/dist/docs/guides/history/back-up.md +195 -0
- package/dist/docs/guides/history/change-data-feed.md +247 -0
- package/dist/docs/guides/history/journal-and-undo.md +262 -0
- package/dist/docs/guides/history/restore.md +341 -0
- package/dist/docs/guides/history/table-history.md +657 -0
- package/dist/docs/guides/history/vacuum.md +35 -0
- package/dist/docs/guides/read-and-write/automatic-links.md +768 -0
- package/dist/docs/guides/read-and-write/batch.md +139 -0
- package/dist/docs/guides/read-and-write/import-notes.md +896 -0
- package/dist/docs/guides/read-and-write/joins-and-aggregates.md +251 -0
- package/dist/docs/guides/read-and-write/read-and-filter.md +536 -0
- package/dist/docs/guides/read-and-write/write-rows.md +573 -0
- package/dist/docs/guides/search/link-graph.md +146 -0
- package/dist/docs/guides/search/semantic.md +133 -0
- package/dist/docs/guides/search/text.md +142 -0
- package/dist/docs/guides/security/security-model.md +110 -0
- package/dist/docs/guides/security/tokens.md +60 -0
- package/dist/docs/guides/security/who-did-what.md +42 -0
- package/dist/docs/index.md +113 -0
- package/dist/docs/llms.txt +33 -0
- package/dist/docs/reference/cli.md +136 -0
- package/dist/docs/reference/compatibility.md +63 -0
- package/dist/docs/reference/errors.md +72 -0
- package/dist/docs/reference/glossary.md +161 -0
- package/dist/docs/reference/operations/auxiliary.md +116 -0
- package/dist/docs/reference/operations/history.md +168 -0
- package/dist/docs/reference/operations/queries.md +169 -0
- package/dist/docs/reference/operations/rows.md +185 -0
- package/dist/docs/reference/operations/schema.md +316 -0
- package/dist/docs/reference/operations.md +96 -0
- package/dist/docs/reference/settings.md +31 -0
- package/dist/docs/release-notes.md +67 -0
- package/dist/docs/start/connect-agents.md +204 -0
- package/dist/docs/start/how-it-works.md +317 -0
- package/dist/docs/start/quick-start.md +126 -0
- package/package.json +59 -14
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# How agents work with your vault
|
|
2
|
+
|
|
3
|
+
> What an agent reads first, how it finds tables and views, why the engine validates its writes, and how the journal records and undoes what each agent did.
|
|
4
|
+
|
|
5
|
+
An agent connected through `datanotes mcp`, the Model Context Protocol (MCP) server of Datanotes, works with your vault the way a careful colleague works with a shared database. It reads the descriptions before it writes, writes only through operations the engine checks, and signs every change with its name in the journal. This page follows that path, from the instructions the agent receives to undoing what it did; the [prompts](https://datanotes.dev/guides/agents/prompts/) show it on concrete requests.
|
|
6
|
+
|
|
7
|
+
## The agent starts with the server’s instructions
|
|
8
|
+
|
|
9
|
+
When an MCP client connects, `datanotes mcp` sends instructions with its list of tools. The engine’s part is short:
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
Database of Markdown notes: tables defined in metastore.yaml, a row is a note whose front matter key `table` names its table, and each front matter key is a column. Use list_tables / describe_table first, select_rows to read, insert_row / update_row / update_rows / batch to write (validated, journaled, undo with undo_migration). Change the schema only with its operations (create_table, add_column, alter_column, create_view, ...); never edit metastore.yaml. Every table and column needs a `description` of what it holds, or it is refused: descriptions are how agents and people understand the schema. Fill those describe_table lists in `missing_descriptions` with alter_table / alter_column. A body you write links the notes it mentions by name (a one-word name only with a capital, inside a sentence): when a write returns ambiguous_mentions, read the candidate notes and link the right one with update_row and autolink: false, or leave the text. Read the docs of this version with search_docs and read_docs.
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The tools are every [operation](https://datanotes.dev/reference/operations/) of the engine, plus three that [read the docs of the installed version](#the-agent-reads-the-docs-of-its-version). To give agents rules and tools of your own, serve [your own MCP server](https://datanotes.dev/develop/build-on-datanotes/#build-your-own-mcp-server) next to it. Each tool’s description says when to call it: `list_tables` asks the agent to call it first, and `add_column` asks the agent to read `describe_table` before it adds a column.
|
|
16
|
+
|
|
17
|
+
## The agent finds tables by their descriptions
|
|
18
|
+
|
|
19
|
+
Before it reads or writes, the agent matches your words against what the tables say about themselves:
|
|
20
|
+
|
|
21
|
+
* **`list_tables`**: every table and view, with its `description`, `aliases` and `tags`, so “my watchlist” leads to `film`, whose aliases include `watchlist`
|
|
22
|
+
* **`describe_table`**: the columns, each with its type, `description`, `aliases`, limits and, for an enum, the meaning of each value, plus the table’s row count
|
|
23
|
+
|
|
24
|
+
The meanings come from `value_descriptions`, which you give when you create the column. On the film diary, `describe_table` answers this for `status`:
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"name": "status",
|
|
29
|
+
"type": "enum",
|
|
30
|
+
"values": ["to watch", "watched"],
|
|
31
|
+
"value_descriptions": {
|
|
32
|
+
"to watch": "on my watchlist, not seen yet",
|
|
33
|
+
"watched": "I saw it at least once"
|
|
34
|
+
},
|
|
35
|
+
"ordered": true,
|
|
36
|
+
"default": "to watch"
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Every table and every column has a description, because the engine refuses one without. Agents and people understand the schema through them, so write each for a reader who never saw your notes. Good aliases help too: the better both are, the less the agent guesses. You set them with `create_table`, `add_column`, `alter_table`, `alter_column` and, for catalogs and schemas, `comment_on`.
|
|
41
|
+
|
|
42
|
+
A table created before descriptions were required may lack some. `describe_table` lists them in `missing_descriptions`, and the agent fills them with `alter_table` and `alter_column`. [Describe every table and column](https://datanotes.dev/guides/database-objects/tables/#describe-every-table-and-column) shows the rule in use.
|
|
43
|
+
|
|
44
|
+
## The agent reads views first
|
|
45
|
+
|
|
46
|
+
A view is a stored query with a name, a description and aliases, such as `vw_to_watch`: the films whose status is `to watch`, shortest first. `list_tables` returns views next to tables, and `select_rows` reads a view like a table and can narrow it further. When a view answers the question, the agent reads it instead of rebuilding the filter, so the answer follows your definition of “to watch” and not the agent’s. [Views](https://datanotes.dev/guides/database-objects/views/) shows views with joins, groups and filters on the note they’re shown for.
|
|
47
|
+
|
|
48
|
+
## The agent writes only through checked operations
|
|
49
|
+
|
|
50
|
+
Rows change through `insert_row`, `update_row`, `update_rows`, `delete_rows` and `batch`; the schema changes through operations such as `create_table`, `add_column` and `add_constraint`. The engine checks every one against the table’s column types, limits, links and CHECK constraints, and writes nothing when a check fails. Three arguments make an agent’s writes safer:
|
|
51
|
+
|
|
52
|
+
* **`dry_run`**: reports what would change, without writing
|
|
53
|
+
* **`batch`**: a group of writes that succeed or fail together, and that you undo as one
|
|
54
|
+
* **`expect`** on `update_row`: writes only if the row still has the values the agent read, so it doesn’t overwrite an edit you made in the meantime
|
|
55
|
+
|
|
56
|
+
The agent never edits `metastore.yaml`: a hand edit skips validation and has no undo. [Concurrent writes](https://datanotes.dev/develop/concurrency/) explains what happens when agents, programs and people write at the same time.
|
|
57
|
+
|
|
58
|
+
## A refusal tells the agent what to fix
|
|
59
|
+
|
|
60
|
+
A refused write names the note, the column or rule, and the values the engine accepts. It ends with a hint on how to fix it and a link to the page that shows the fix. For a film with the status `seen`, the engine answers:
|
|
61
|
+
|
|
62
|
+
```text
|
|
63
|
+
insert_row refused — nothing was written:
|
|
64
|
+
invalid datanotes/main/public/film/Sunrise.md: status must be one of: to watch (on my watchlist, not seen yet); watched (I saw it at least once)
|
|
65
|
+
Hint: Use one of the allowed values listed in the message, written exactly; describe_table shows what each one means. To add a value, alter_column the enum. Then call insert_row again (dry_run: true checks without writing).
|
|
66
|
+
Docs: read_docs("guides/database-objects/columns#describe-what-each-enum-value-means")
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
The agent can correct the value and try again, or ask you. Every other error follows the same pattern: a misspelled table or column gets the closest real name, a wrong filter operator gets the one meant, and a tool argument the tool doesn’t take gets the tool’s arguments. [Read the engine’s errors](https://datanotes.dev/guides/agents/reading-errors/) shows them all. Before it writes a link, the agent can call `list_link_targets`, which returns the rows the link column accepts, such as the genres a film may link to. Over HTTP, a refused write comes back with status 422 and the reasons in the body.
|
|
70
|
+
|
|
71
|
+
## The agent reads the docs of its version
|
|
72
|
+
|
|
73
|
+
`datanotes mcp` also serves this documentation, read from the installed `datanotes` package, with three tools: `list_docs`, `read_docs` and `search_docs`. The agent looks up an operation or an example without internet access, and the pages always match the version it talks to. [Read the docs offline](https://datanotes.dev/guides/agents/docs-offline/) shows the tools.
|
|
74
|
+
|
|
75
|
+
## Every write names the agent that made it
|
|
76
|
+
|
|
77
|
+
The engine records an actor with every change. Through `datanotes mcp`, the actor comes from the MCP connection:
|
|
78
|
+
|
|
79
|
+
* **`harness`** and **`harness_version`**: the client’s name and version from the MCP handshake, such as `claude-code`
|
|
80
|
+
* **`session`**: the MCP session, shortened to 16 characters
|
|
81
|
+
* **`tool`**: the tool the agent called
|
|
82
|
+
* **`auth`**: `owner`, or the token’s name for a [named token](https://datanotes.dev/start/connect-agents/#give-each-agent-its-own-token)
|
|
83
|
+
* **`model`**: the model, when an MCP server reports it with `POST /datanotes/sessions/identify/`
|
|
84
|
+
|
|
85
|
+
`describe_history` shows the actor of each commit:
|
|
86
|
+
|
|
87
|
+
```json
|
|
88
|
+
{
|
|
89
|
+
"table": "main.public.film",
|
|
90
|
+
"version": 10,
|
|
91
|
+
"operation": "UPDATE",
|
|
92
|
+
"migration_id": "20261009T215306-update_rows-update-film",
|
|
93
|
+
"actor": {
|
|
94
|
+
"session": "5d8c0456-3b15-40",
|
|
95
|
+
"harness": "claude-code",
|
|
96
|
+
"harness_version": "2.5.0",
|
|
97
|
+
"tool": "batch",
|
|
98
|
+
"auth": "owner"
|
|
99
|
+
},
|
|
100
|
+
"batch": "20261009T215306-batch-log-the-screening-of-metropoli"
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Three operations read this record:
|
|
105
|
+
|
|
106
|
+
* **`list_migrations`**: the journal, newest first, each operation with `by`, the agent’s name
|
|
107
|
+
* **`describe_history`**: the commits of one table or of every table, with the full actor; it needs history on
|
|
108
|
+
* **`list_changes`**: every row change with its actor, and with `kinds: ["tool_call"]` every tool call the MCP server reported, reads included
|
|
109
|
+
|
|
110
|
+
A script records its own actor with the `X-Datanotes-Actor` header or the client’s `actor` option, as the [HTTP API guide](https://datanotes.dev/develop/http-api/#record-who-makes-each-write) shows.
|
|
111
|
+
|
|
112
|
+
## Undo what an agent did
|
|
113
|
+
|
|
114
|
+
Because the journal records every write, you can take back one operation or a whole run:
|
|
115
|
+
|
|
116
|
+
* **One operation**: `undo_migration` with its `migration_id`; for a `batch`, it reverts every write in it
|
|
117
|
+
* **A whole run**: `restore_database` with `before_migration` set to the agent’s first operation or batch; every table with history goes back to its state before that operation (run it with `dry_run` first)
|
|
118
|
+
* **One table**: `restore_table` to a version or a time
|
|
119
|
+
|
|
120
|
+
The journal records an undo too, so you can undo the undo. The engine refuses an undo that would overwrite a note you edited since, and lists the conflicts. [Restore a table or the database](https://datanotes.dev/guides/history/restore/) shows each operation with the engine’s answers, and the [prompts](https://datanotes.dev/guides/agents/prompts/#safety-and-history-prompts) show how to ask for them.
|
|
121
|
+
|
|
122
|
+
## Give each agent only what it needs
|
|
123
|
+
|
|
124
|
+
The owner token can do everything. A [named token](https://datanotes.dev/guides/security/tokens/) limits an agent to the tables in `write`, to schema changes only with `ddl`, and to configuration, undo and restore only with `maintain`. The journal then names the token with each of its writes. [Connect agents](https://datanotes.dev/start/connect-agents/) shows how to create one and pass it to an MCP client.
|
|
@@ -0,0 +1,495 @@
|
|
|
1
|
+
# Prompts for your agent
|
|
2
|
+
|
|
3
|
+
> Copy prompts for everyday notes, schema changes, history and imports, with the tools the agent calls and the same calls from code.
|
|
4
|
+
|
|
5
|
+
Once your agent is [connected](https://datanotes.dev/start/connect-agents/), you talk to your vault in plain words. This page gives prompts to copy, grouped by task. They all use one example: a diary of classic films with the tables `film`, `actor`, `genre` and `watch`.
|
|
6
|
+
|
|
7
|
+
For each prompt you see what happens, the [operations](https://datanotes.dev/reference/operations/) the agent calls, in order, and what you get. Each one ends with the same call from code, for when you’d rather script it.
|
|
8
|
+
|
|
9
|
+
The tool sequences and answers come from runs against a real engine through `datanotes mcp`, the Model Context Protocol (MCP) server. Your agent may add a read here and there, such as a second `describe_table`, but the writes are the ones shown.
|
|
10
|
+
|
|
11
|
+
## Call the same operations from code
|
|
12
|
+
|
|
13
|
+
Every tool of the agent is an operation of the [HTTP API](https://datanotes.dev/develop/http-api/), so a script makes the calls the agent makes. The snippets on this page use one client of [`datanotes/client`](https://datanotes.dev/develop/client/):
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { DatanotesClient } from "datanotes/client";
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
const db = new DatanotesClient({
|
|
20
|
+
url: "http://127.0.0.1:27150",
|
|
21
|
+
token: process.env.DATANOTES_TOKEN ?? "",
|
|
22
|
+
actor: { harness: "my-script" },
|
|
23
|
+
});
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`db.call(name, args)` takes the agent’s tool name and arguments, and sends the request the [HTTP API reference](https://datanotes.dev/api/) lists for it. With curl, you send the same JSON to the operation’s route, `POST /datanotes/operations/<operation>/`. The body holds the operation’s arguments, with the same names as the agent’s tool.
|
|
27
|
+
|
|
28
|
+
## Prompts for everyday notes
|
|
29
|
+
|
|
30
|
+
These prompts read and write rows of your diary. They need the `watch` table and the `vw_to_watch` view, which the [schema prompts](#schema-prompts) create.
|
|
31
|
+
|
|
32
|
+
### Log a viewing with where, when and who
|
|
33
|
+
|
|
34
|
+
```text
|
|
35
|
+
I watched Metropolis tonight at 20:30 at the film club downtown, with
|
|
36
|
+
Anna. Live organ accompaniment. Five stars. Log it in my film diary.
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The agent finds the film, adds a `watch` row and marks the film watched, in one `batch`, so both writes succeed or fail together.
|
|
40
|
+
|
|
41
|
+
* **Tools**: `list_tables`, `describe_table` on `watch`, `select_rows` on `film` for `Metropolis`, then `batch` with `insert_row` and `update_row`
|
|
42
|
+
* **You get**: a new note, `main/public/watch/2026-10-09T2030.md`, and `Metropolis` with `status: watched`, `rating: 5` and `watched_on: 2026-10-09`; one `undo_migration` on the batch’s `migration_id` reverts both
|
|
43
|
+
|
|
44
|
+
From code, the batch is `POST /datanotes/operations/batch/`:
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
await db.call("batch", {
|
|
48
|
+
summary: "Log the screening of Metropolis",
|
|
49
|
+
operations: [
|
|
50
|
+
{
|
|
51
|
+
op: "insert_row",
|
|
52
|
+
table: "watch",
|
|
53
|
+
values: {
|
|
54
|
+
film: "[[Metropolis]]",
|
|
55
|
+
occurred_at: "2026-10-09T20:30:00",
|
|
56
|
+
where: "cinema",
|
|
57
|
+
place: "the film club downtown",
|
|
58
|
+
with: "Anna",
|
|
59
|
+
},
|
|
60
|
+
body: "Live organ accompaniment.\n",
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
op: "update_row",
|
|
64
|
+
table: "film",
|
|
65
|
+
path: "main/public/film/Metropolis.md",
|
|
66
|
+
set: { status: "watched", rating: 5, watched_on: "2026-10-09" },
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Mark a film to watch
|
|
73
|
+
|
|
74
|
+
```text
|
|
75
|
+
Put Battleship Potemkin on my watchlist: 1925, 75 minutes, directed by
|
|
76
|
+
Sergei Eisenstein, Soviet montage.
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
The agent matches “watchlist” against the aliases of the `film` table, checks that the film isn’t there yet, and adds it.
|
|
80
|
+
|
|
81
|
+
* **Tools**: `list_tables`, `select_rows` on `film` for the title, then `insert_row`
|
|
82
|
+
* **You get**: `main/public/film/Battleship Potemkin.md`, with `status: to watch` and a link to the `Soviet montage` genre
|
|
83
|
+
|
|
84
|
+
From code, `POST /datanotes/operations/insert_row/`:
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
await db.call("insert_row", {
|
|
88
|
+
table: "film",
|
|
89
|
+
values: {
|
|
90
|
+
title: "Battleship Potemkin",
|
|
91
|
+
year: 1925,
|
|
92
|
+
minutes: 75,
|
|
93
|
+
director: "Sergei Eisenstein",
|
|
94
|
+
genre: "[[Soviet montage]]",
|
|
95
|
+
status: "to watch",
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Ask what to watch tonight
|
|
101
|
+
|
|
102
|
+
```text
|
|
103
|
+
What should I watch tonight? I have about an hour and a half.
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
The agent finds the view of your watchlist and narrows it to films that fit the evening.
|
|
107
|
+
|
|
108
|
+
* **Tools**: `list_tables`, which lists `vw_to_watch` under `views`, then `select_rows` on the view with a filter on `minutes`
|
|
109
|
+
* **You get**: Battleship Potemkin, 75 minutes; Metropolis, at 153 minutes, waits for a longer evening
|
|
110
|
+
|
|
111
|
+
From code, `POST /datanotes/operations/select_rows/`:
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
const tonight = await db.call("select_rows", {
|
|
115
|
+
table: "vw_to_watch",
|
|
116
|
+
where: { minutes: { lte: 100 } },
|
|
117
|
+
});
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Find the films you saw with someone
|
|
121
|
+
|
|
122
|
+
```text
|
|
123
|
+
Which films did I see with Anna this year?
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
The agent reads the `watch` table, where `with` holds who came along, and matches the name case-insensitively.
|
|
127
|
+
|
|
128
|
+
* **Tools**: `list_tables`, `describe_table` on `watch`, then `select_rows` with `icontains` on `with` and `gte` on `occurred_at`
|
|
129
|
+
* **You get**: Sherlock Jr. at home in February, His Girl Friday at the cinema in March, Nosferatu at an outdoor screening in June, and Metropolis tonight
|
|
130
|
+
|
|
131
|
+
From code, `POST /datanotes/operations/select_rows/`:
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
await db.call("select_rows", {
|
|
135
|
+
table: "watch",
|
|
136
|
+
where: { with: { icontains: "anna" }, occurred_at: { gte: "2026-01-01" } },
|
|
137
|
+
columns: ["occurred_at", "film", "where"],
|
|
138
|
+
order_by: "occurred_at",
|
|
139
|
+
});
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Write your review
|
|
143
|
+
|
|
144
|
+
```text
|
|
145
|
+
Add my review of Charade under a "My review" heading: Grant and Hepburn
|
|
146
|
+
trade lines across Paris while everyone lies about the money.
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
The agent reads the note’s body first, then writes the review under its own heading and keeps the rest of the note.
|
|
150
|
+
|
|
151
|
+
* **Tools**: `select_rows` on `film` with `include_body`, then `update_row` with `body_sections`
|
|
152
|
+
* **You get**: a `## My review` section at the end of `Charade.md`, below the text the note already had
|
|
153
|
+
|
|
154
|
+
From code, `POST /datanotes/operations/update_row/`:
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
await db.call("update_row", {
|
|
158
|
+
table: "film",
|
|
159
|
+
path: "main/public/film/Charade.md",
|
|
160
|
+
body_sections: {
|
|
161
|
+
"My review":
|
|
162
|
+
"Grant and Hepburn trade lines across Paris while everyone lies " +
|
|
163
|
+
"about the money.",
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Schema prompts
|
|
169
|
+
|
|
170
|
+
These prompts change the tables themselves. The agent changes `metastore.yaml` only through schema operations, which check the change against the rows, journal it and make it undoable. To limit which agents may change the schema, give them a [named token](https://datanotes.dev/start/connect-agents/#give-each-agent-its-own-token) without `ddl`.
|
|
171
|
+
|
|
172
|
+
### Create the watch table
|
|
173
|
+
|
|
174
|
+
```text
|
|
175
|
+
Create a table for each time I watch a film: when, the film, where
|
|
176
|
+
(cinema, home or outdoor screening), the place in my words, and who came
|
|
177
|
+
along.
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
The agent checks that no table records viewings yet, then creates one named by the date and time of each viewing.
|
|
181
|
+
|
|
182
|
+
* **Tools**: `list_tables`, `describe_table` on `film` to link to it, then `create_table`
|
|
183
|
+
* **You get**: `main.public.watch` in `metastore.yaml`, with `occurred_at` as its time column, so the engine names each note like `2026-10-09T2030.md`; its description and aliases lead an agent to it from words such as “diary”, and each column says what it holds
|
|
184
|
+
|
|
185
|
+
The engine refuses a table or a column without a description, so the agent writes one for each.
|
|
186
|
+
|
|
187
|
+
From code, `POST /datanotes/operations/create_table/`:
|
|
188
|
+
|
|
189
|
+
```ts
|
|
190
|
+
await db.call("create_table", {
|
|
191
|
+
name: "watch",
|
|
192
|
+
description: "Each time I watch a film: when, where and with whom",
|
|
193
|
+
time_column: "occurred_at",
|
|
194
|
+
columns: [
|
|
195
|
+
{
|
|
196
|
+
name: "occurred_at",
|
|
197
|
+
type: "datetime",
|
|
198
|
+
required: true,
|
|
199
|
+
description: "When the film started",
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
name: "film",
|
|
203
|
+
type: "link",
|
|
204
|
+
ref: "main.public.film",
|
|
205
|
+
required: true,
|
|
206
|
+
description: "The film I watched",
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
name: "where",
|
|
210
|
+
type: "enum",
|
|
211
|
+
values: ["cinema", "home", "outdoor screening"],
|
|
212
|
+
required: true,
|
|
213
|
+
description: "The kind of place I watched it in",
|
|
214
|
+
},
|
|
215
|
+
{ name: "place", type: "string", description: "Where, in my words" },
|
|
216
|
+
{ name: "with", type: "string", description: "Who came along" },
|
|
217
|
+
],
|
|
218
|
+
aliases: ["viewings", "screenings", "diary"],
|
|
219
|
+
});
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Add a column
|
|
223
|
+
|
|
224
|
+
```text
|
|
225
|
+
Add a column to my film diary for what the ticket cost.
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
The agent reads the table first, to reuse a column that already means the same, and adds a new one only when none does.
|
|
229
|
+
|
|
230
|
+
* **Tools**: `describe_table` on `watch`, then `add_column`
|
|
231
|
+
* **You get**: a `price` column, a number of 0 or more with two decimals; existing rows stay as they are, because the engine writes a sparse column only on rows that have a value
|
|
232
|
+
|
|
233
|
+
From code, `POST /datanotes/operations/add_column/`:
|
|
234
|
+
|
|
235
|
+
```ts
|
|
236
|
+
await db.call("add_column", {
|
|
237
|
+
table: "watch",
|
|
238
|
+
column: {
|
|
239
|
+
name: "price",
|
|
240
|
+
type: "number",
|
|
241
|
+
min: 0,
|
|
242
|
+
step: 0.01,
|
|
243
|
+
description: "What the ticket cost",
|
|
244
|
+
},
|
|
245
|
+
});
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Add the CHECK rated_when_watched
|
|
249
|
+
|
|
250
|
+
```text
|
|
251
|
+
A film I've watched must have a rating. Make that a rule of the film table.
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
The agent writes the rule as a filter every row must pass: a film is either not watched, or has a rating.
|
|
255
|
+
|
|
256
|
+
* **Tools**: `describe_table` on `film`, then `add_constraint`
|
|
257
|
+
* **You get**: the CHECK `rated_when_watched`; the engine refuses it while a row breaks it, listing the rows, and from then on refuses any write that breaks it
|
|
258
|
+
|
|
259
|
+
Once the rule exists, the engine refuses to mark Battleship Potemkin as watched without a rating, and writes nothing:
|
|
260
|
+
|
|
261
|
+
```text
|
|
262
|
+
update_row refused — nothing was written:
|
|
263
|
+
invalid main/public/film/Battleship Potemkin.md: rated_when_watched violates CHECK rated_when_watched: {"or":[{"status":{"ne":"watched"}},{"rating":{"exists":true}}]}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
The agent then asks you for a rating. From code, the CHECK is `POST /datanotes/operations/add_constraint/`:
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
curl -s http://127.0.0.1:27150/datanotes/operations/add_constraint/ \
|
|
270
|
+
-H "Authorization: Bearer your_owner_token" \
|
|
271
|
+
-H "Content-Type: application/json" \
|
|
272
|
+
-d '{"table": "film",
|
|
273
|
+
"name": "rated_when_watched",
|
|
274
|
+
"check": {"or": [{"status": {"ne": "watched"}},
|
|
275
|
+
{"rating": {"exists": true}}]}}'
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### Make a view of the films to watch
|
|
279
|
+
|
|
280
|
+
```text
|
|
281
|
+
Make a view of the films I still have to watch, shortest first.
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
The agent stores the query as a view, with a description and aliases so that later questions such as “what’s on my watchlist?” find it.
|
|
285
|
+
|
|
286
|
+
* **Tools**: `list_tables`, to reuse a view that exists, then `create_view`
|
|
287
|
+
* **You get**: `vw_to_watch` in `metastore.yaml`, which `list_tables` lists under `views` and `select_rows` reads like a table
|
|
288
|
+
|
|
289
|
+
From code, `POST /datanotes/operations/create_view/`:
|
|
290
|
+
|
|
291
|
+
```ts
|
|
292
|
+
await db.call("create_view", {
|
|
293
|
+
name: "vw_to_watch",
|
|
294
|
+
query: {
|
|
295
|
+
table: "film",
|
|
296
|
+
where: { status: "to watch" },
|
|
297
|
+
columns: ["title", "year", "minutes", "director"],
|
|
298
|
+
order_by: "minutes",
|
|
299
|
+
},
|
|
300
|
+
description: "Films on my watchlist, shortest first",
|
|
301
|
+
aliases: ["watchlist", "what to watch"],
|
|
302
|
+
});
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
## Safety and history prompts
|
|
306
|
+
|
|
307
|
+
These prompts show what an agent changed and take it back. Every write is in the journal, so `undo_migration` works on any table. Reading a table as it was and restoring the whole database need the tables’ history. A database the engine creates has it on. A database whose `metastore.yaml` lacks the setting, such as one from a version before 3.0.0, has it off. Turn it on once:
|
|
308
|
+
|
|
309
|
+
```text
|
|
310
|
+
Turn history on for every table.
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
The agent calls `configure_database` with `history: true`. The journal doesn’t record database settings, so an agent changes them only when you ask. From code, it’s `POST /datanotes/operations/configure_database/` with `{"history": true}`.
|
|
314
|
+
|
|
315
|
+
### Ask what the agent changed today
|
|
316
|
+
|
|
317
|
+
```text
|
|
318
|
+
What did you change in my vault today?
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
The agent reads the journal, where every operation names the agent that made it.
|
|
322
|
+
|
|
323
|
+
* **Tools**: `list_migrations` with `since`, or `describe_history` without a table for the commits of every table with their full actor
|
|
324
|
+
* **You get**: one line per operation, each with `by: "claude-code"`, such as `batch` “Log the screening of Metropolis” or `add_constraint` on `film`; your own writes from an editor or a script name their own source
|
|
325
|
+
|
|
326
|
+
From code, `POST /datanotes/operations/list_migrations/`:
|
|
327
|
+
|
|
328
|
+
```ts
|
|
329
|
+
const today = await db.call("list_migrations", { since: "2026-10-09" });
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Undo the agent’s last change
|
|
333
|
+
|
|
334
|
+
```text
|
|
335
|
+
Undo your last change.
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
The agent finds its newest operation in the journal and reverts it.
|
|
339
|
+
|
|
340
|
+
* **Tools**: `list_migrations`, then `undo_migration` with its `migration_id`
|
|
341
|
+
* **You get**: the notes as they were before that operation, and the undo’s own `migration_id`, since the journal records the undo too; if you edited one of the notes since, the engine refuses and lists the conflicts instead of overwriting your edit
|
|
342
|
+
|
|
343
|
+
From code, `POST /datanotes/operations/undo_migration/`:
|
|
344
|
+
|
|
345
|
+
```ts
|
|
346
|
+
await db.call("undo_migration", {
|
|
347
|
+
migration_id: "20261009T215306-batch-log-the-screening-of-metropoli",
|
|
348
|
+
});
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### Put everything back as it was before the agent started
|
|
352
|
+
|
|
353
|
+
```text
|
|
354
|
+
Put everything back as it was before you started this evening. Show me
|
|
355
|
+
what would change first.
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
The agent finds its first operation of the session, previews the restore, and runs it once you agree.
|
|
359
|
+
|
|
360
|
+
* **Tools**: `describe_history` without a table, then `restore_database` with `before_migration` and `dry_run: true`, then `restore_database` again without `dry_run`
|
|
361
|
+
* **You get**: every table with history back to that moment, in one operation that `undo_migration` can revert; in the run behind this page, the restore removed Battleship Potemkin and tonight’s `watch` row, and gave Metropolis and Charade their old content back
|
|
362
|
+
|
|
363
|
+
The dry run lists what changes in each table before the engine writes anything. Here is its answer, trimmed:
|
|
364
|
+
|
|
365
|
+
```json
|
|
366
|
+
{
|
|
367
|
+
"ok": true,
|
|
368
|
+
"dry_run": true,
|
|
369
|
+
"planned_deletes": [
|
|
370
|
+
"main/public/film/Battleship Potemkin.md",
|
|
371
|
+
"main/public/watch/2026-10-09T2030.md"
|
|
372
|
+
],
|
|
373
|
+
"planned_texts": [
|
|
374
|
+
"main/public/film/Metropolis.md",
|
|
375
|
+
"main/public/film/Charade.md"
|
|
376
|
+
],
|
|
377
|
+
"unchanged": ["main.public.actor", "main.public.genre"],
|
|
378
|
+
"skipped": []
|
|
379
|
+
}
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
The restore doesn’t rewind views or database settings, and lists a table without history in `skipped`. From code, `POST /datanotes/operations/restore_database/`:
|
|
383
|
+
|
|
384
|
+
```ts
|
|
385
|
+
await db.call("restore_database", {
|
|
386
|
+
before_migration: "20261009T215329-insert_row-insert-into-film",
|
|
387
|
+
dry_run: true,
|
|
388
|
+
});
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
### Read a note as it was last week
|
|
392
|
+
|
|
393
|
+
```text
|
|
394
|
+
Show me Nosferatu as it was last week.
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
The agent reads the `film` table at a past time and picks the row.
|
|
398
|
+
|
|
399
|
+
* **Tools**: `select_rows` on `film` with `timestamp`, and `describe_history` on `film` when you ask what changed since
|
|
400
|
+
* **You get**: the row with the values it had then, and the table `version` the engine read; if the table didn’t exist yet at that time, the engine answers `main.public.film did not exist at 2026-10-02T09:00:00Z`
|
|
401
|
+
|
|
402
|
+
From code, `POST /datanotes/operations/select_rows/`:
|
|
403
|
+
|
|
404
|
+
```ts
|
|
405
|
+
await db.call("select_rows", {
|
|
406
|
+
table: "film",
|
|
407
|
+
where: { title: "Nosferatu" },
|
|
408
|
+
timestamp: "2026-10-02T09:00:00Z",
|
|
409
|
+
});
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
## Import prompts
|
|
413
|
+
|
|
414
|
+
This prompt turns notes you already have into rows, without moving them.
|
|
415
|
+
|
|
416
|
+
### Turn a folder of notes into a table
|
|
417
|
+
|
|
418
|
+
```text
|
|
419
|
+
Turn my Films/ folder into a table. Show me the columns you propose
|
|
420
|
+
before you create anything.
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
The agent reads the notes’ front matter, proposes a table, and waits for your review. Review it: on five notes, `infer_table` marked `director` and `minutes` as `unique`, because no two notes shared a value. The engine would then refuse a sixth film by the same director, so ask the agent to drop `unique` there.
|
|
424
|
+
|
|
425
|
+
The notes can’t say what each key means, so the proposal leaves every `description` `null`. The agent writes them and asks you when a key isn’t clear. `create_table` refuses a table or a column without one.
|
|
426
|
+
|
|
427
|
+
* **Tools**: `list_folder` on `Films`, `infer_table` with `folder: "Films"`, then, after your review, `create_table` with the reviewed and described proposal, `adopt_rows` with `dry_run: true`, `adopt_rows`, and `check_table`
|
|
428
|
+
* **You get**: a `film` table whose rows are your notes, moved to the table’s folder with the links to them rewritten; each note gets `table` and an `id`, and keeps its body; `check_table` reports no violations
|
|
429
|
+
|
|
430
|
+
`infer_table` returns `proposal`, the arguments of `create_table`, and `adopt`, the arguments of `adopt_rows`. From code, the inference is `POST /datanotes/operations/infer_table/`:
|
|
431
|
+
|
|
432
|
+
```ts
|
|
433
|
+
const inferred = await db.call("infer_table", {
|
|
434
|
+
folder: "Films",
|
|
435
|
+
name: "film",
|
|
436
|
+
});
|
|
437
|
+
const { proposal, adopt } = inferred.value as {
|
|
438
|
+
proposal: { columns: { name: string }[] };
|
|
439
|
+
adopt: Record<string, unknown>;
|
|
440
|
+
};
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
After you review `proposal`, create the table. The notes keep the title in their file name, so add a `title` column with `identity: "filename"` and name the rows with `filename: "{title}"`. Write a description for every column, or `create_table` refuses the table:
|
|
444
|
+
|
|
445
|
+
```ts
|
|
446
|
+
const meaning: Record<string, string> = {
|
|
447
|
+
year: "Year the film first came out",
|
|
448
|
+
minutes: "Running time in minutes",
|
|
449
|
+
director: "Who directed the film",
|
|
450
|
+
// … one for each column of the proposal
|
|
451
|
+
};
|
|
452
|
+
const created = await db.call("create_table", {
|
|
453
|
+
...proposal,
|
|
454
|
+
description: "Classic films I watched or want to watch",
|
|
455
|
+
filename: "{title}",
|
|
456
|
+
columns: [
|
|
457
|
+
{
|
|
458
|
+
name: "title",
|
|
459
|
+
type: "string",
|
|
460
|
+
identity: "filename",
|
|
461
|
+
description: "The film's title, which is also its note's name",
|
|
462
|
+
},
|
|
463
|
+
...proposal.columns.map((c) => ({
|
|
464
|
+
...c,
|
|
465
|
+
unique: false,
|
|
466
|
+
description: meaning[c.name],
|
|
467
|
+
})),
|
|
468
|
+
],
|
|
469
|
+
});
|
|
470
|
+
if (!created.ok) throw new Error(String(created.value));
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
Then adopt the notes with `POST /datanotes/operations/adopt_rows/`. `relocate` moves them to the table’s folder and rewrites the links to them:
|
|
474
|
+
|
|
475
|
+
```ts
|
|
476
|
+
const { paths, rename } = adopt as {
|
|
477
|
+
paths: string[];
|
|
478
|
+
rename: Record<string, string>;
|
|
479
|
+
};
|
|
480
|
+
const adopted = await db.call("adopt_rows", {
|
|
481
|
+
table: "film",
|
|
482
|
+
paths,
|
|
483
|
+
rename,
|
|
484
|
+
relocate: true,
|
|
485
|
+
});
|
|
486
|
+
if (!adopted.ok) throw new Error(String(adopted.value));
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
## Learn more about agents and operations
|
|
490
|
+
|
|
491
|
+
These pages go deeper into what the prompts use:
|
|
492
|
+
|
|
493
|
+
* [How agents work with your vault](https://datanotes.dev/guides/agents/how-agents-use-datanotes/): what the agent reads first, how it finds tables and what the journal records
|
|
494
|
+
* [Guides](https://datanotes.dev/guides/database-objects/tables/): every operation in use, with the engine’s real answers
|
|
495
|
+
* [Operations](https://datanotes.dev/reference/operations/): every tool and its arguments
|