Your corpus stays with its keeper.
Run a data node beside your agent: immutable records, content-addressed blobs, SQLite full-text search, provenance, and an append-only change feed. The base node reads local indexes only and advertises peer_sync: false; the optional explicit-pull wrapper advertises only its bounded agent-data-sync/v1 profile.
AgentTool may help an agent find or call a node. It does not have to own the raw bytes.
There is no hosted AgentTool data node in this release. Do not send these paths to api.agenttool.dev, and do not look for data.agenttool.dev. Each operator runs or selects a node and discovers it at that node's own /.well-known/agent-data. The default reference CLI binds to 127.0.0.1:7742.
Two related layers, two separate jobs
| Layer | What it does | What it does not do |
|---|---|---|
@agenttool/dataagent-data/v1 |
Collects bounded content into local collections, stores immutable envelopes and blobs, indexes text, queries, and emits resumable local changes. | No hosted storage, discovery, push, general federation, automatic memory projection, or general signature/schema enforcement. Optional sync is explicit bounded pull between configured peers. |
@agenttool/addsadds/v0.1 · experimental |
Encrypts immutable content-addressed Blocks and signs Manifests and direct read Grants for offline, provider-independent exchange. | No collection query API, peer discovery, global revocation, proof of storage, secure deletion, or provider durability guarantee. |
@agenttool/repo-archiveagent-repo-archive/v0.1 · experimental |
Captures committed Git history into an encrypted, signed bundle and counts only zones that independently pass a complete restore drill. | No workspace backup, hosted archive, cloud adapter, key custody, physical-domain proof, retention proof, or durability guarantee. |
SDK at.data |
Calls a separately configured agent-data/v1 node from the TypeScript or Python AgentTool SDK. |
Does not discover a hosted node implicitly and never implicitly forwards the AgentTool project bearer as the node bearer. |
sources ──collect──> your @agenttool/data node
├── SQLite metadata + FTS
├── content-addressed local blobs
└── dedicated node bearer
optional @agenttool/adds ──> encrypted Blocks + signed control records
@agenttool/sdk at.data ──HTTP──> that node's URL
api.agenttool.dev ──X────> no implicit raw-data path
Optional exact npm convenience. npm install --save-exact @agenttool/data@0.3.1 @agenttool/adds@0.2.3 @agenttool/data-sync@0.1.2. These exact versions are public and independently byte-verified against the checked-in LOVE line. The data and sync packages still require Bun where stated. See Packages → Verify for the authoritative LOVE size/SHA-256 workflow; npm latest is not release authority.
Run the local reference node
The reference node requires Bun because it uses bun:sqlite and Bun.serve. The CLI creates a default private collection and local .agent-data/ directory. Use a dedicated random node token. The SDK configures that token separately and never implicitly forwards AT_API_KEY; a caller can still explicitly supply the same value and should not do so.
bun add https://docs.agenttool.dev/packages/v1/@agenttool/data/0.3.1/agenttool-data-0.3.1.tgz
export AGENT_DATA_NODE_TOKEN='<dedicated-random-node-token>'
bunx --bun --no-install --package @agenttool/data agenttool-data --root=./.agent-data
# agent-data/v1 node ... listening at http://127.0.0.1:7742
Network boundary. Discovery and the capability manifest are public at the node. Every data route requires the dedicated node bearer. The CLI refuses a non-loopback bind unless that bearer is configured. TLS, firewalling, backups, and remote exposure remain operator responsibilities.
Check a node with the executable profile
agenttool-data doctor, introduced in @agenttool/data@0.2.0 and retained through 0.3.1, is a bounded black-box runner for agent-data/v1-slice1-http. Its JSON report follows the public conformance report schema and validates only the observed HTTP profile at that target and time; it is not a security certification, durability proof, or secure-erasure claim.
# Public discovery and synthetic auth-boundary probes bunx --bun --no-install --package @agenttool/data agenttool-data \ doctor http://127.0.0.1:7742 --profile public # Supply a dedicated node bearer through stdin, never argv printf '%s' "$AGENT_DATA_NODE_TOKEN" | \ bunx --bun --no-install --package @agenttool/data agenttool-data \ doctor http://127.0.0.1:7742 --profile read --token-stdin
Mutation is opt-in. The full slice1 lifecycle requires an expected node ID, a dedicated scratch collection, and explicit acknowledgement that immutable records, change events, and tombstones can remain. The runner never auto-selects a collector or claims physical cleanup.
Discover, collect, and query
# Public capability truth curl http://127.0.0.1:7742/.well-known/agent-data # Collect one local text item curl -X POST http://127.0.0.1:7742/v1/data/collect \ -H "Authorization: Bearer $AGENT_DATA_NODE_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "collection_id": "default", "collector_id": "text", "input": { "text": "Local-first agents keep their corpus close." } }' # Query the node-local FTS index curl -X POST http://127.0.0.1:7742/v1/data/query \ -H "Authorization: Bearer $AGENT_DATA_NODE_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "collections": ["default"], "text": "corpus", "consistency": "local" }'
Use the optional encrypted-object plane
@agenttool/adds is the experimental reference implementation of the separate adds/v0.1 working draft. It can encrypt, address, sign, store, and share exact objects offline through memory, filesystem, or caller-provided stores. A CID and signature prove bytes and key control; they do not prove a claim is true or that a provider will retain the object.
bun add https://docs.agenttool.dev/packages/v1/@agenttool/adds/0.2.3/agenttool-adds-0.2.3.tgz import { AgentData, MemoryBlockStore, generateIdentity } from "@agenttool/adds"; const data = new AgentData({ identity: generateIdentity("did:example:agent"), store: new MemoryBlockStore(), }); const published = await data.put("private agent context", { mediaType: "text/plain; charset=utf-8", }); console.log(published.ref); // ciphertext/control-document CID reference
ADDS 0.2.3 requires @noble/ed25519@^2.3.0, matching the verifier's Point API, and propagates programming/environment faults instead of misreporting them as an invalid signature. Immutable 0.2.2 could resolve Noble 2.2.3 and reject a valid signed object; that was a fail-closed availability defect, not acceptance of an invalid signature. The current JavaScript maps embed their TypeScript sources and the tarball omits declaration maps rather than pointing at an excluded source tree.
Two protocols, no sleight of hand. agent-data/v1 is the higher collection/query contract. adds/v0.1 is an optional lower encrypted-object plane. Implementations must not validate one protocol under the other's signing domains or claim ADDS peer discovery that does not exist.
Archive committed Git history across named zones
@agenttool/repo-archive composes a self-contained Git bundle with ADDS encryption, signed archive records, and per-zone read-back drills. A zone is counted only after that zone alone decrypts, validates, restores into a fresh no-checkout repository, verifies the bundle, and passes strict git fsck.
npm install --save-exact @agenttool/repo-archive@0.1.0-dev.0 @agenttool/adds@0.2.3 npx agent-repo-archive simulate --repo /absolute/path/to/clean/repository
A restore drill is evidence, not future durability. The included simulator places three copies in directories on one device, erases its process-held recovery key at exit, and captures committed Git history rather than dirty or untracked workspace bytes. Production provider adapters, scheduling, repair, and recovery-key custody remain outside v0.1. Read the overview, normative profile, schema, and vectors.
Pull encrypted pages from an explicit peer
@agenttool/data-sync composes the data node and ADDS packages. It discovers no peers and accepts no caller-supplied peer URL or credential: the operator configures the exact origin, source node and publisher keys, page-only bearer, collection allow-list, and recipient key. Verified records are retained in the destination node for offline query.
bun add \ https://docs.agenttool.dev/packages/v1/@agenttool/adds/0.2.3/agenttool-adds-0.2.3.tgz \ https://docs.agenttool.dev/packages/v1/@agenttool/data/0.3.1/agenttool-data-0.3.1.tgz \ https://docs.agenttool.dev/packages/v1/@agenttool/data-sync/0.1.2/agenttool-data-sync-0.1.2.tgz import { DataSyncService } from "@agenttool/data-sync";
Data-sync 0.1.2 peers on repaired ADDS ^0.2.3 and data ^0.3.1. It rejects imported objects whose signed manifest lacks the exact sync media type or schema, requires the reference node's strict uppercase, non-leap-second RFC 3339 change-time profile to match the decrypted record or tombstone time, and permits an explicit plaintext page up to the default data-node 10 MiB record ceiling with 32 MiB encoded-response headroom. The ordinary requested page remains 1 MiB; larger pages are still deliberate. Its shipped JavaScript maps embed TypeScript text and omit declaration maps.
Bounded profile, not global replication. The bridge is pull-only, pins the exact origin/node/publisher/feed checkpoint identity, separates page authority from local admin authority, and exposes no raw cursor through the SDK. It does not provide discovery, push, consensus, multi-master conflict resolution, CAR transport, or a hosted sync service.
Use at.data with separate configuration
The SDK integration has two independent configuration fields. apiKey authorizes the hosted AgentTool project. dataNode.token authorizes the node you selected. The SDK never implicitly substitutes or forwards one as the other.
import { AgentTool } from "@agenttool/sdk"; const at = new AgentTool({ apiKey: process.env.AT_API_KEY, dataNode: { baseUrl: "http://127.0.0.1:7742", token: process.env.AGENT_DATA_NODE_TOKEN, }, }); const hits = await at.data.query({ collections: ["default"], text: "local-first", consistency: "local", });
from agenttool import AgentTool import os at = AgentTool( api_key=os.environ["AT_API_KEY"], data_node_url="http://127.0.0.1:7742", data_node_token=os.environ["AGENT_DATA_NODE_TOKEN"], ) hits = at.data.query( collections=["default"], text="local-first", consistency="local", )
For data-only use with no AgentTool account, instantiate the exported TypeScript or Python DataClient directly with the node URL and token. It does not require AT_API_KEY.
Take a copy home: the exit door
The exit door copies an agent's hosted continuity into a collection on a node you run. It goes one way, hosted → local. Hosted reads are GET-only through the project's own credentials, and every write goes through at.data, so the project bearer never reaches the node.
const plan = await at.exitDoor.plan(); // hosted reads only; needs no node const { manifest_record_id, manifest } = await at.exitDoor.export({ collection_id: "default", // an existing collection on the node }); console.log(plan.overall, manifest.overall); // complete | partial | failed const check = await at.exitDoor.verify(manifest_record_id); // re-reads, re-hashes
plan = at.exit_door.plan() result = at.exit_door.export(collection_id="default") check = at.exit_door.verify(result["manifest_record_id"])
agenttool-exit-door export \ --hosted-token-env AT_API_KEY \ --node-url http://127.0.0.1:7742 --node-token-env AGENT_DATA_NODE_TOKEN \ --collection default
What v1 copies: memories, chronicle, strands with their ciphertext thoughts, correspondence events, covenants, identities and keys (as context), and the vault and identity-backup indexes. Vault secret values and backup blobs are not exported: their custody decision is still open, and every manifest says so.
What it promises: each hosted item becomes one immutable record keyed <store>/<hosted id>, and the manifest reports completeness per store from the host's own end-of-walk signal. An unchanged re-run inserts nothing. The exporter never decrypts, never deletes, never calls search (search costs credits), and never reads single memories (that read updates accessed_at). Putting any of the copy back into hosted memory is a separate, explicit step (agent-data/v1 §11).
What it refuses before the first write: a node that does not report agent-data/v1 with the text collector, a target collection that does not already exist (the exporter never creates one), a non-loopback node URL unless you pass allow_remote_node, a node on the hosted API's own origin, and a node token equal to the project API key. CLI tokens come only from environment variables or stdin, never from argv.
Availability, 2026-10-13. The cursor-paged hosted walks it reads are live on api.agenttool.dev. The client first ships in SDK 0.23.0, tagged sdk-v0.23.0 in the public agenttool-packages source repository. npm and PyPI still serve 0.22.1, which has no exit door, so check the installed version before relying on it.
What a delete does today
Taking a copy and deleting are separate acts. Before deleting anything hosted, read GET /public/retention: an unauthenticated, static answer to how long each kind of record is kept and what a delete does to it now. Every value names its basis (measured, source, config, declared or unknown). Three deletes hide a record but keep its content (inbox messages, vault secrets and identity backups), and their responses say so with content_retained: true. RETENTION.md explains how to read it.
Reference node HTTP surface
| Method | Path | Authority | Purpose |
|---|---|---|---|
| GET | /.well-known/agent-data | Public | Discover this node's exact capabilities and peer_sync: false status. |
| GET | /v1/data/manifest | Public | Same node capability manifest. |
| GET | /v1/data/collections | Node bearer | List locally configured collections. |
| POST | /v1/data/collect | Node bearer | Run a registered bounded collector. |
| POST | /v1/data/query | Node bearer | Query local materialized indexes. |
| GET | /v1/data/records/:id | Node bearer | Resolve one immutable record and its verified local content. |
| GET | /v1/data/changes | Node bearer | Read the append-only change feed with an opaque cursor. |
| POST | /v1/data/records/:id/tombstone | Node bearer | Append a tombstone; this is not physical blob erasure. |
Slice 1 capability truth
| Capability | Status | Boundary |
|---|---|---|
| Immutable records, SHA-256 blobs, SQLite FTS5, change cursors | Implemented | Local reference node. |
| Text, local-file, and bounded HTTP collectors | Implemented | File paths become provenance and may be sensitive. HTTP SSRF checks are best-effort, not a network sandbox. |
| Collection size and media-type policy | Enforced | Node-wide limits may be stricter. |
| JSON Schema, visibility, TTL, retention, DID ACL, supplied signatures | Stored declarations | Not enforced or verified by Slice 1. |
| Explicit encrypted peer pull | Optional profile | The base node remains peer_sync: false. @agenttool/data-sync advertises true only when its bounded configured-peer wrapper is installed. |
| Hosted AgentTool storage or automatic memory projection | Not implemented | Projection into AgentTool memory must be an explicit caller action. |
| ADDS encrypted Blocks, signed Manifests, direct read Grants, and offline vectors | Experimental package | Separate adds/v0.1 layer; provider records, Heads, and Receipts are specified but the reference package intentionally exposes only its strict first profile. |
| Encrypted multi-zone committed-history archive and independent restore drills | Experimental local package | Same-device simulator only; no provider adapter, scheduled repair, recovery-key custody, physical-domain proof, or durability guarantee. |
Protocol and wire references
AGENT-DATA-PROTOCOL.md— normativeagent-data/v1collection, record, query, and change contract.ADDS-0.1-DRAFT.md— experimental encrypted-object working draft, with a machine-readable schema and pinned vectors.AGENT-REPO-ARCHIVE.md— encrypted committed-history archive overview, with the normative 0.1 profile, machine-readable schema, and pinned vectors.- Memory — hosted, project-bearer-gated memory records; a separate surface from raw local corpora.