Use when an AI agent needs to store, retrieve, or share end-to-end encrypted JSON documents. Triggers on requests like "save this", "store memory", "encrypted storage", "track tasks as docs", or any task requiring persistent encrypted content that agents and humans can collaborate on.
Resources
11Install
npx skillscat add uriva/agentdocs Install via the SkillsCat registry.
agentdocs — Encrypted JSON Documents for AI Agents
agentdocs is an end-to-end encrypted document platform. It uses a hybrid model:
- latest full encrypted snapshot stored on the document row for fast reads
- append-only encrypted incremental patches as the edit history
The server stores only ciphertext and cannot read titles, bodies, ticket
state, or any other domain metadata.
This skill bundles safescript files — one per operation — that handle crypto
and signed HTTP requests end-to-end.
API base URL: https://agentdocs-api.uriva.deno.net
safescript language: https://safescript.dev
Step 1 — Get an identity from the user
Agents do not generate identities. Ask the user to create one in the web UI
and export it:
- Open https://agentdocs-nine.vercel.app and sign in.
- Create or choose an identity and click Export.
- Copy the base64url exported bundle.
- Pass it as the
agentdocsIdentityparameter to every function (see script signatures below).
Bundle shape (decoded JSON):
{
"id": "<identity UUID>",
"name": "<display name>",
"signing": { "privateKey": "<base64url PKCS8 Ed25519 private key>" },
"encryption": { "privateKey": "<base64url PKCS8 X25519 private key>" },
"algorithm": {
"signing": "Ed25519",
"keyExchange": "X25519",
"symmetric": "AES-GCM-256"
}
}Step 2 — Use the scripts
| Script | Purpose |
|---|---|
create-document.ss |
Create a document with initial snapshot + first patch |
add-edit.ss |
Append encrypted patch and update checkpoint snapshot |
share-document.ss |
Grant another identity access |
list-documents.ss |
Return decrypted latest snapshot per doc |
get-document.ss |
Return one decrypted latest snapshot |
search-documents.ss |
Return all decrypted latest snapshots |
Script signatures
createDocument(title: string, content: string, agentdocsIdentity: string)
-> { documentId, documentKey, status, body }
addEdit(documentId: string, documentKey: string, newSnapshotJson: string, agentdocsIdentity: string)
-> { status, body, sequenceNumber }
shareDocument(documentId: string, documentKey: string, granteeIdentityId: string, agentdocsIdentity: string)
-> { status, body }
listDocuments(agentdocsIdentity: string)
-> { documents: [{ documentId, kind, title, content, documentKey }] }
getDocument(documentId: string, agentdocsIdentity: string)
-> { documentId, kind, title, content, documentKey, sequenceNumber }
searchDocuments(agentdocsIdentity: string)
-> { documents: [{ documentId, kind, title, content, documentKey }] }How agents should modify documents
Edits are incremental patches. The latest full snapshot is also stored as a
checkpoint on the document for fast reads.
Recommended update flow:
- Read current state with
getDocument(documentId). - Parse
contentas JSON ifkindis not enough, or use known convention. - Apply changes in memory.
- Build the new full snapshot JSON.
- Call
addEdit(...)which sends areplace_snapshotpatch and updates the
encrypted checkpoint snapshot atomically.
Example: rename a doc
Read the latest snapshot, change title, keep everything else, then append:
{
"kind": "doc",
"title": "New Title",
"content": "...existing content..."
}Example: update ticket status
{
"kind": "ticket",
"title": "Fix auth timeout",
"content": "Description and acceptance criteria",
"status": "in_progress",
"priority": "high",
"assigneeIdentityId": "<identity-id>",
"labels": ["bug", "auth"],
"comments": [
{
"authorIdentityId": "<identity-id>",
"timestamp": "2026-04-17T12:34:56.000Z",
"content": "Investigating token refresh path"
}
]
}Important: preserve fields you are not changing. Current patch type isreplace_snapshot, so dropping a field means deleting it.
JSON-first model (everything is a document)
The platform has one primitive: encrypted document snapshots, with patch-based
history.
- A note/spec doc is a JSON snapshot.
- A ticket is a JSON snapshot with ticket fields.
- A spreadsheet is a JSON snapshot with
kind: "spreadsheet"anddata.
Recommended conventions are documented in:
conventions/doc.mdconventions/ticket.mdconventions/spreadsheet.md
Searching
searchDocuments decrypts every accessible latest snapshot and returns them.
Your agent filters locally (substring, embeddings, LLM ranking, etc.).
Permission surface
All scripts:
hosts:agentdocs-api.uriva.deno.netenv:timestamp(all),randomBytes(create/share grant flows)
What scripts do not cover
- Webhook lifecycle (
/api/webhooks) is not wrapped here. - Key rotation / hard revocation is not implemented by API.