> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nora.my/llms.txt
> Use this file to discover all available pages before exploring further.

# Resources

> Read and write memory spaces and knowledge folders, with an on-behalf-of subject for access rules

Memory and knowledge are **content** surfaces. Reading and writing them requires **PAT `content` scope** and — for scoped resources — an `onBehalfOf` subject so the server can evaluate access rules for a specific user, org, or role.

## Why `onBehalfOf`

PATs are **service tokens** with no end user attached. Scoped memory spaces and knowledge folders have access rules keyed to subjects (`user_id`, `org_id`, `role`, …). Without a subject, the server has nothing to evaluate — and refuses the request rather than silently returning everything.

**Pass `onBehalfOf` for every read and write on a scoped resource.** Un-scoped spaces / folders work without it, but the audit trail is thinner (you get the PAT owner, not the end user).

## `memory`

### `memory.read`

```ts theme={null}
await nora.memory.read("space_1", {
  onBehalfOf: { user_id: "u_1", role: "member" },
  scope: { topic: "billing" },      // optional extra filter
});
```

Options:

* `onBehalfOf` — subject asserted by your app. Required on scoped spaces. Rejected requests give `NoraAccessError`.
* `scope` — optional additional filter (a `{ key: value }` map matched against the space's scope schema).

Returns the memory entries the subject is allowed to see under the given scope. Same shape the UI's memory viewer renders.

### `memory.write`

```ts theme={null}
await nora.memory.write(
  "space_1",
  { path: "notes/billing", body: "…" },
  { onBehalfOf: { user_id: "u_1" } },
);
```

Writes take the **same curator / paradigm / supersede path as the UI** — Wiki notes go through the wiki paradigm, Index nodes through the index paradigm, and superseded entries are marked (not deleted).

The write payload's shape depends on the space's paradigm — see [Memory](/build/memory/overview) for the paradigm reference.

## `knowledge`

### `knowledge.upload`

```ts theme={null}
await nora.knowledge.upload(fileBlob, {
  folder: "policies",
  onBehalfOf: { org_id: "acme" },
});
```

Options:

* `folder` — knowledge folder tag the document lands in. Required.
* `onBehalfOf` — subject for the folder's access rule. Required on folders with access rules.

Same server path as `nora documents upload` in the CLI — the file gets chunked and vectorised, and the row is audited with both the PAT owner and the `onBehalfOf` subject.

### `knowledge.list`

```ts theme={null}
await nora.knowledge.list();
```

Lists the documents the caller (via PAT + `onBehalfOf` if given) is allowed to see. Not paginated in the SDK yet — for large libraries prefer [`nora documents list`](/cli/documents) which supports `--limit` / `--offset`.

## Common patterns

### Per-request subject from your auth layer

Pass whatever your app already knows about the caller:

```ts theme={null}
async function readNotes(userId: string, topic: string) {
  const user = await yourAuth.get(userId);
  return nora.memory.read("space_notes", {
    onBehalfOf: { user_id: userId, role: user.role, org_id: user.orgId },
    scope: { topic },
  });
}
```

The server evaluates the space's access rule against the subject you pass. If your caller's role can't see the space, you get `NoraAccessError` — you can catch and downgrade rather than throwing:

```ts theme={null}
try {
  return await readNotes(userId, topic);
} catch (e) {
  if (e instanceof NoraAccessError) return { entries: [], reason: "access-denied" };
  throw e;
}
```

### Bulk upload with a shared subject

For a batch ingest triggered by one operator, the subject is the operator — not the end users the documents are *about*.

```ts theme={null}
for (const file of files) {
  await nora.knowledge.upload(file, {
    folder: "policies",
    onBehalfOf: { user_id: operatorId, role: "admin" },
  });
}
```

For scale, prefer [`nora documents upload-folder`](/cli/documents#upload-folder) — it batches through the same server path with retry and progress.

### Un-scoped spaces / folders

Some spaces and folders have no access rules attached. `onBehalfOf` is optional there — but passing it anyway improves your audit trail (the entry is stamped with the subject the operator was acting for).

## Scope

* `memory.read` / `memory.write` — **PAT `content`**.
* `knowledge.upload` / `knowledge.list` — **PAT `content`**.
* Scoped resources without `onBehalfOf` — **rejected** with `NoraAccessError`.
