Files and documents
Download a file from a person's runtime with files.download, and read the person's public documents with memory.list and memory.get.
Download a file
runtime.files.download(path, options?) returns the file's raw bytes as a Fetch Response (200, or 206 for a range) with Content-Type, Content-Length and Content-Range, so you can pipe its body on. path is an absolute path on the person's runtime that your app's grant lets it read. Options: range (one Range header value such as bytes=0-0 or bytes=-500) and signal.
const response = await runtime.files.download('/apps/<your client id>/files/report.pdf');
res.setHeader('content-type', response.headers.get('content-type') ?? 'application/octet-stream');
await pipeline(Readable.fromWeb(response.body!), res);A non-2xx answer is thrown as an APIError, never returned as bytes. A bad range is 416, invalid_request with param: 'range'. A body cut short mid-stream means the file could not be read to the end. What a path may reach depends on the grant: see Scopes and grants. The client your app gets from oauth.client(userId) exposes only download from files; reading, writing and listing are not available to apps.
Read the person's public documents
runtime.memory is a read-only view of the knowledge and preference documents the person owns (memory and the /v1/memory routes are the API's names for this). An app reads the person's public documents with memory.list and memory.get, and needs no scope to do it. It never sees a friends or private document and cannot tell one from a document that does not exist: both answer 404 not_found. The list is what the app's agents can read about the person, so an app can show the person exactly which of their documents it draws on.
const page = await runtime.memory.list({store: 'user'});
for (const item of page.items) console.log(item.name, item.preview);
const doc = await runtime.memory.get({store: 'user', name: page.items[0].name});
console.log(doc.body);store is 'user' in this release; any other value answers 400 invalid_request with param: "store". An app whose grant holds crtr:memory:manage:user (a first-party app) sees every privacy level. Reading records nothing: no watch, no read event, no audit row. Both methods are GET requests and follow the SDK's retry rule for safe requests.
List
list({store, path?, kind?, limit?, cursor?}, options?) sends GET /v1/memory and returns {items, next_cursor}.
| Field | Meaning |
|---|---|
path | A folder: lists documents whose name starts with <path>/, at any depth |
kind | knowledge or preference; both when omitted |
limit | 1 to 100; default 50 |
cursor | The previous page's next_cursor, with the same store, path and kind |
Items are ordered by name. Each item is {name, folder, kind, preview, summary, privacy, revision, created_at, updated_at}: name has no user/ prefix, folder is the name up to its last / ("" at the top level), and updated_at is the current revision's time. Folders are not items, and deleted and unlisted documents are left out. next_cursor is null on the last page.
listAll(params, options?) takes the same fields without cursor and yields every item across pages, fetching the next page only as you iterate:
for await (const item of runtime.memory.listAll({store: 'user', path: 'work'})) render(item);Get
get({store, name}, options?) sends GET /v1/memory/document and returns a list item's fields plus body, size, truncated and grantee.
bodyis the current markdown as stored;[[links]]are not resolved. A body over 1 MiB is cut to its longest whole-character prefix of at most 1 MiB, withtruncated: true;sizeis always the full length in UTF-8 bytes.granteeisapp:<id>of the app whose agent wrote the first revision, ornullwhen the person wrote it.- An absent, deleted,
friendsorprivatename rejects withNotFoundError(code: 'not_found'); a malformed field rejects withBadRequestError.