openapi: 3.1.0 info: title: Bem Buckets File System API version: 1.0.0 description: "Buckets are named partitions of the knowledge graph within an\naccount+environment. Entities, mentions, and relations are scoped to a\nbucket so a single account+environment can host multiple isolated graphs\n— for example one per data source or workspace.\n\nEvery account+environment has exactly one **default** bucket, used by\nunscoped flows. The default bucket can be renamed but never deleted.\n\nUse these endpoints to create, list, fetch, rename, and delete buckets:\n\n- **`POST /v3/buckets`** creates a non-default bucket.\n- **`GET /v3/buckets`** lists buckets with cursor pagination\n (`startingAfter` / `endingBefore` over `bucketID`).\n- **`PATCH /v3/buckets/{bucketID}`** updates `name` and/or `description`.\n- **`DELETE /v3/buckets/{bucketID}`** soft-deletes a bucket. A non-empty\n bucket is rejected with `409 Conflict` unless `?cascade=true` is\n passed; the default bucket can never be deleted." servers: - url: https://api.bem.ai description: US Region API variables: {} - url: https://api.eu1.bem.ai description: EU Region API variables: {} security: - API Key: [] tags: - name: File System description: 'Unix-shell-style nav over parsed documents and the cross-doc memory store. `POST /v3/fs` is a single op-driven endpoint designed for LLM agents and programmatic consumers that want to walk a corpus the way they''d walk a filesystem. ## Doc-level ops (every parsed document) - `ls` — list parsed documents with rich per-doc metadata. - `cat` — read one doc''s parse JSON, sliced (`range`) or projected (`select`). - `head` — first N sections of one doc. - `grep` — substring or regex search; `scope`, `path`, `countOnly` available. - `stat` — metadata only (page/section/entity counts, timestamps). ## Memory-level ops (require `linkAcrossDocuments: true` on the parse function) - `find` — list canonical entities across the corpus. - `open` — entity + mentions. - `xref` — for one entity, sections across docs that mention it (with content). Memory ops return an empty list with a `hint` when no docs in this environment have been memory-linked. ## Pagination List ops paginate by cursor — pass the previous response''s `nextCursor` back as `cursor`; `hasMore: false` signals the last page. Same idiom as `/v3/calls` and `/v3/outputs`.' paths: /v3/fs: post: operationId: v3-fs summary: File System Operations description: '**Navigate parsed documents and the cross-doc memory store via Unix-shell verbs.** `POST /v3/fs` is a single op-driven endpoint that lets an LLM agent (or any programmatic client) walk a corpus the way it would walk a filesystem — `ls` to list, `cat` to read, `grep` to search, `head` for a quick peek, `stat` for metadata, and `find` / `open` / `xref` for the cross-doc entity memory layer. The body always carries an `op` field; other fields apply per op. The response envelope is uniform: `{op, data, hasMore?, nextCursor?, count?, hint?}`. ## Quick reference | Op | `path` | Other fields | What it does | |----|--------|-------------|--------------| | `ls` | — | `filter`, `limit`, `cursor` | List parsed documents | | `grep` | referenceID *(optional)* | `pattern`, `scope`, `countOnly` | Search across documents | | `cat` | referenceID | `range`, `select` | Read a document''s parsed content | | `head` | referenceID | `n` | First N sections (default 10) | | `stat` | referenceID *or* entityID | — | Metadata only | | `find` | — | `filter`, `limit`, `cursor` | List canonical entities | | `open` | entityID | — | Entity detail + all mentions | | `xref` | entityID | `limit`, `cursor` | Sections across docs mentioning an entity | **`path`** is the positional identifier. For doc ops (`cat`, `head`, `stat`), pass a `referenceID` from `ls`. For entity ops (`open`, `xref`), pass an `entityID` from `find`. `grep` optionally takes a `path` to scope search to one document. ## Examples **List documents:** `{"op": "ls"}` **Search one document:** `{"op": "grep", "path": "my-doc-001", "pattern": "holiday", "scope": "sections"}` **Read one page:** `{"op": "cat", "path": "my-doc-001", "range": {"page": 7}}` **Read a page range:** `{"op": "cat", "path": "my-doc-001", "range": {"pageRange": [5, 10]}}` **Project section labels and pages only:** `{"op": "cat", "path": "my-doc-001", "select": ["sections.label", "sections.page", "sections.type"]}` **Preview first 5 sections:** `{"op": "head", "path": "my-doc-001", "n": 5}` **Document metadata:** `{"op": "stat", "path": "my-doc-001"}` **List entities:** `{"op": "find"}` **Entity detail + mentions:** `{"op": "open", "path": "ent_abc123"}` **Cross-document sections for an entity:** `{"op": "xref", "path": "ent_abc123"}` ## Key details `range` is an **object** with optional keys: `page` (integer), `pageRange` (two-element array `[from, to]`), `sectionTypes` (array of strings like `["table", "heading"]`). `select` is an **array of strings** — dotted paths like `["sections.label", "sections.page"]`. `scope` (grep) is one of `"sections"`, `"entities"`, `"relationships"`, or `"all"` (default). ## Pagination List ops (`ls`, `find`) paginate by cursor: pass the last item''s `nextCursor` from a previous response to fetch the next page; `hasMore: false` signals the last page. Same idiom as `/v3/calls` and `/v3/outputs`.' parameters: [] responses: '200': description: The request has succeeded. content: application/json: schema: $ref: '#/components/schemas/FSResponse' tags: - File System requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/FSRequest' components: schemas: FSResponse: type: object required: - op - data properties: op: allOf: - $ref: '#/components/schemas/FSOp' description: The op echoed back. data: description: Op-specific payload. See per-op shapes below. hasMore: type: boolean description: True when more pages exist for cursor-paginated ops. nextCursor: type: string description: 'Cursor to pass as `cursor` in the next request to fetch the next page. Empty when `hasMore=false`.' count: type: integer description: 'Set for ops that return a count rather than a list (`grep` with `countOnly=true`) or as a sanity check on lists.' hint: type: string description: 'Optional human-readable note. Surfaced on memory-level ops (`find` / `open` / `xref`) when the corpus has no memory-linked docs, pointing users at the `linkAcrossDocuments` toggle on the parse function.' description: 'Uniform response shape returned for every `op`. `data` is op-specific JSON (a list, an object, or a string), but the wrapper is constant so a client only learns one parse path.' FSContext: type: object properties: bucket: type: string description: 'Bucket KSUID (prefix `bkt_`) to scope the request to — a named partition of the knowledge graph within the caller''s account+environment. **Optional.** Omitting it (or passing an empty value) leaves the request UNSCOPED: memory-level reads (`find` / `open` / `xref`) return entities across every bucket in the account+environment, so pre-bucket callers keep their original all-entities behavior unchanged. (Writes are different: a parse call with no bucket targets the account default bucket.) When a bucket IS supplied, memory-level ops return only entities in that bucket; doc-level ops (`ls`/`cat`/`head`/`stat`/`grep`) are unaffected either way — documents are not bucket-partitioned. A bucket that does not belong to the caller''s account+environment is rejected.' description: 'Request-scoping concerns that are orthogonal to the op itself. Carried on a `context` object so future scoping hints (e.g. as-of timestamps, read consistency) can slot in without reshaping the op-specific fields.' FSRange: type: object properties: page: type: integer description: Restrict sections to one page (1-indexed). pageRange: type: array items: type: integer minItems: 2 maxItems: 2 description: 'Restrict sections to an inclusive page range. Two-element array of `[from, to]` (both 1-indexed).' sectionTypes: type: array items: type: string description: 'Keep only sections whose `type` matches one of these (e.g. `["table", "list"]`).' description: Slice the parse output along page or section dimensions. Used with `op=cat`. FSOp: type: string enum: - ls - find - open - cat - grep - xref - stat - head description: 'Operations exposed by `POST /v3/fs`. The verbs and their flag names mirror Unix tools so an LLM agent''s existing vocabulary maps directly: - `ls` — list parsed documents - `cat` — read one parsed doc (optionally sliced by range / projected by select) - `grep` — substring or regex search across parse outputs - `head` — first N sections of one doc - `stat` — metadata only (page count, section count, parsed at, ...) - `find` — list canonical entities (cross-doc memory) - `open` — entity + mentions - `xref` — entity → sections across docs that mention it Doc-level ops (ls, cat, grep, head, stat) work on every parsed document, regardless of how the parse function was configured. Memory-level ops (find, open, xref) operate on the global entities table which is only populated when the parse function had `linkAcrossDocuments: true`. On environments with no memory-linked docs they return empty data with a hint pointing at the toggle.' FSFilter: type: object properties: type: type: string description: Match an entity's `type` field exactly (e.g. `"drug"`, `"study"`). search: type: string description: 'Substring match on canonical name (entities) or `referenceID` (parsed docs). Case-insensitive.' functionName: type: string description: Match a parsed doc's source function name exactly. since: type: string format: date-time description: Restrict to resources created at or after this timestamp. description: Filter options for `op=ls` and `op=find`. FSRequest: type: object required: - op properties: op: allOf: - $ref: '#/components/schemas/FSOp' description: The operation to run. Required. context: allOf: - $ref: '#/components/schemas/FSContext' description: 'Request-scoping context (currently just the bucket scope). Optional; when omitted the request resolves against the account+environment default bucket. See `FSContext`.' path: type: string description: 'Identifier for ops that operate on a single resource: - cat / head / stat: a parsed document, by `referenceID` or `transformationID`. - open / xref / stat: an entity, by `entityID`.' pattern: type: string description: Substring or regex pattern for `op=grep`. regex: type: boolean description: When true, `pattern` is interpreted as a Go regex. Default false. ignoreCase: type: boolean description: When true (default), substring/regex matching is case-insensitive. scope: type: string description: 'Restricts grep to one part of the parse output. One of `"sections"`, `"entities"`, `"relationships"`, `"all"` (default).' countOnly: type: boolean description: 'When true, return only the hit count without snippet payload. Cheaper than fetching matches when the agent only wants a yes/no.' filter: allOf: - $ref: '#/components/schemas/FSFilter' description: Narrows results for `op=ls` and `op=find`. range: allOf: - $ref: '#/components/schemas/FSRange' description: Slices the parse output for `op=cat`. select: type: array items: type: string description: 'Project the parse output to specific dotted paths (e.g. `["sections.label", "sections.page"]`), letting an agent map a doc''s structure cheaply before reading content. Used with `op=cat`.' n: type: integer description: First-N count for `op=head`. Defaults to 10. limit: type: integer description: Maximum results to return. Defaults vary per op (25–50). cursor: type: string description: 'Pagination cursor. Pass the last item''s ID from a previous response (`nextCursor`) to fetch the next page.' description: Request body for `POST /v3/fs`. Op-specific fields apply per op. securitySchemes: API Key: type: apiKey in: header name: x-api-key description: Authenticate using API Key in request header