knowledge API
Table of Contents
upsquad/knowledge/v1/knowledge.proto
AttachSourceToUnitRequest
AttachSourceToUnitRequest tags a source onto an org_unit OR org-wide. The acting member is taken from the caller's scope, not this message.
Org-attach contract (#1554): set scope='org' and leave unit_id empty to make the source retrievable org-wide (every pillar/team inherits it). For a pillar/team attach set scope='unit' (or leave it empty — 'unit' is the default) and supply unit_id. As a back-compat shim for the client placeholder (client#389), unit_id="org" with an empty scope is also treated as an org-attach; new clients SHOULD send scope='org' with an empty unit_id.
| Field | Type | Label | Description |
|---|---|---|---|
| source_id | string | source_id is the knowledge source to attach (required). | |
| unit_id | string | unit_id is the org_units.id (pillar/team) to attach it to. Required for a unit attach; MUST be empty for an org attach (scope='org'). | |
| visibility | string | visibility is one of 'inherit_down' | |
| scope | string | scope is 'unit' (default — a pillar/team attach, requires unit_id) or 'org' (an org-wide attach, unit_id must be empty). (#1554.) |
AttachSourceToUnitResponse
AttachSourceToUnitResponse returns the created (or revived) binding.
| Field | Type | Label | Description |
|---|---|---|---|
| binding | SourceUnitBinding | binding is the resulting source⇄unit binding. |
CreateSourceRequest
CreateSourceRequest creates a new knowledge source in the org-owned catalog. The owning org and the creating member are taken from the caller's scope, not from this message. A source no longer carries an owning scope at creation (HLD-C §3.1, RA2 REPLACE) — attach it to one-or-many pillars/teams afterwards with AttachSourceToUnit. Fields 1/2 (the legacy owning_scope / unit_id) were dropped in the founder-approved breaking change DC-3 (#1382/#1377); their numbers + names are reserved.
| Field | Type | Label | Description |
|---|---|---|---|
| name | string | name is the human-readable source name (required, non-empty). | |
| description | string | description is an optional free-text description. | |
| src_type | string | src_type is one of the registered source types. Only upload | |
| refresh_interval_seconds | int32 | refresh_interval_seconds is the desired auto-refresh cadence in seconds; 0 (the default) means auto-refresh is off. Persisted as NULL when 0. (#1367.) | |
| criticality | string | criticality is one of 'low' | |
| url | string | url is the connector fetch target. Required and non-empty when src_type='web' (an https URL the connector SSRF-screens at fetch time, #1375) or src_type='gdrive' (a Google Drive folder URL or raw folder id, #1430); must be empty for all other source types. The DB CHECK is the backstop. |
CreateSourceResponse
CreateSourceResponse returns the created source.
| Field | Type | Label | Description |
|---|---|---|---|
| source | Source | source is the newly created source. |
DeleteSourceRequest
DeleteSourceRequest soft-deletes a source and hard-deletes its chunks.
| Field | Type | Label | Description |
|---|---|---|---|
| id | string | id is the source UUID. |
DeleteSourceResponse
DeleteSourceResponse reports the outcome of a delete.
| Field | Type | Label | Description |
|---|---|---|---|
| chunks_removed | int32 | chunks_removed is the number of rag_chunks rows cascade-deleted. |
DetachSourceFromUnitRequest
DetachSourceFromUnitRequest soft-deletes a source⇄unit binding, or the source's org-wide binding when scope='org' (#1554).
| Field | Type | Label | Description |
|---|---|---|---|
| source_id | string | source_id is the attached source (required). | |
| unit_id | string | unit_id is the org_units.id to detach it from. Required for a unit detach; MUST be empty for an org detach (scope='org'). As a back-compat shim, unit_id="org" with an empty scope is treated as an org detach. | |
| scope | string | scope is 'unit' (default) or 'org' (detach the org-wide binding). (#1554.) |
DetachSourceFromUnitResponse
DetachSourceFromUnitResponse reports whether an active binding was removed.
| Field | Type | Label | Description |
|---|---|---|---|
| detached | bool | detached is true when an active binding was soft-deleted; false when there was no active binding to remove. |
DriveTypeBreakdown
DriveTypeBreakdown tallies the previewed files of one content category so the UI can show "12 PDFs (40 MB), 3 Google Docs, 2 unsupported".
| Field | Type | Label | Description |
|---|---|---|---|
| category | string | category is a coarse content bucket: 'gdoc' | |
| file_count | int32 | file_count is the number of files in this category. | |
| total_bytes | int64 | total_bytes is the summed binary size of files in this category. Google- native files (gdoc/gslides/gsheets) report 0 bytes in Drive (they have no binary blob until exported), so their size is not counted here. |
EffectiveSourceEntry
EffectiveSourceEntry is one resolved binding tagged with its provenance.
| Field | Type | Label | Description |
|---|---|---|---|
| binding | SourceUnitBinding | binding is the resolved source⇄unit binding. | |
| effective_source | string | effective_source is the provenance: 'direct' | |
| source_unit_id | string | source_unit_id is the unit the binding was found on (the direct unit, the inherit_down ancestor, or the shared_siblings sibling). Empty for an 'org' provenance binding. |
GetSourceRequest
GetSourceRequest fetches a single source by id.
| Field | Type | Label | Description |
|---|---|---|---|
| id | string | id is the source UUID. |
GetSourceResponse
GetSourceResponse returns the requested source.
| Field | Type | Label | Description |
|---|---|---|---|
| source | Source | source is the requested source. |
GetSourceStatusRequest
GetSourceStatusRequest fetches ingestion status for a source.
| Field | Type | Label | Description |
|---|---|---|---|
| id | string | id is the source UUID. |
GetSourceStatusResponse
GetSourceStatusResponse reports ingestion progress for a source.
| Field | Type | Label | Description |
|---|---|---|---|
| source_id | string | source_id is the source UUID. | |
| sync_status | string | sync_status is one of 'empty' | |
| doc_count | int32 | doc_count is the number of ingested documents. | |
| chunk_count | int32 | chunk_count is the total number of chunks for the source (authoritative COUNT over rag_chunks). | |
| embedded_chunk_count | int32 | embedded_chunk_count is the number of chunks with embeddings computed. (Maintained by FW3-b's embed worker; 0 until ingestion lands.) | |
| pending_chunk_count | int32 | pending_chunk_count is chunk_count - embedded_chunk_count. |
IngestDocumentRequest
IngestDocumentRequest feeds one document into a source. The owning org and the acting member are taken from the caller's scope, never from this message.
| Field | Type | Label | Description |
|---|---|---|---|
| source_id | string | source_id is the knowledge_sources UUID to ingest into (required). The source must be visible to the caller's scope and of an ingestable type (upload | |
| filename | string | filename is the original document filename, retained on each chunk's metadata for provenance (optional but recommended). | |
| content_type | string | content_type selects the text extractor: one of 'md' | |
| content | bytes | content is the raw document bytes. Size caps (founder Design Call D5): 10 MB for md |
IngestDocumentResponse
IngestDocumentResponse reports the outcome of an ingestion.
| Field | Type | Label | Description |
|---|---|---|---|
| source_doc_id | string | source_doc_id is the deterministic per-document identity (derived from the content_hash) stamped on every chunk of this document. | |
| chunk_count | int32 | chunk_count is the number of chunks created for this document (0 on an idempotent hit). | |
| token_count | int32 | token_count is the total token count across the document's chunks. | |
| idempotent_hit | bool | idempotent_hit is true when this document's content_hash was already ingested for the source; the call made no changes. | |
| content_hash | string | content_hash is the SHA-256 hex digest of the raw document bytes. |
ListEffectiveSourcesRequest
ListEffectiveSourcesRequest resolves the effective source set. Exactly one of the three selectors must be set; the others must be empty.
| Field | Type | Label | Description |
|---|---|---|---|
| unit_id | string | unit_id resolves the effective set anchored at a single pillar/team. | |
| member_id | string | member_id resolves the effective set across all units a member belongs to. | |
| agent_id | string | agent_id resolves the effective set for an agent (agents are members in the unified org_unit tree, so this resolves the same way as member_id). |
ListEffectiveSourcesResponse
ListEffectiveSourcesResponse returns the resolved, de-duplicated set.
| Field | Type | Label | Description |
|---|---|---|---|
| entries | EffectiveSourceEntry | repeated | entries are the effective sources, one per distinct source_id. |
ListSourceUnitsRequest
ListSourceUnitsRequest lists the units a source is attached to.
| Field | Type | Label | Description |
|---|---|---|---|
| source_id | string | source_id is the knowledge source (required). |
ListSourceUnitsResponse
ListSourceUnitsResponse returns a source's active bindings.
| Field | Type | Label | Description |
|---|---|---|---|
| bindings | SourceUnitBinding | repeated | bindings are the source's active source⇄unit attachments. |
ListSourcesRequest
ListSourcesRequest pages the org-owned source catalog. After the RA2 REPLACE (HLD-C §3.1) a source has no owning scope, so the owning_scope/unit_id/ include_inherited filters are retained for wire-compatibility but IGNORED by the server — use ListEffectiveSources(unit_id) for the "RAG on this pillar/team" view with provenance. They are not removed (no further proto break) but carry no semantics.
| Field | Type | Label | Description |
|---|---|---|---|
| owning_scope | string | Deprecated: ignored after HLD-C (the catalog is org-wide). Was an 'org' | |
| unit_id | string | Deprecated: ignored after HLD-C. Was a single pillar/team filter. | |
| include_inherited | bool | Deprecated: ignored after HLD-C. Was the inherit-up listing flag. | |
| page_size | int32 | page_size bounds the page (default 50, max 100). | |
| page_token | string | page_token is the opaque cursor from a previous response. |
ListSourcesResponse
ListSourcesResponse is a page of sources.
| Field | Type | Label | Description |
|---|---|---|---|
| sources | Source | repeated | sources is the page of visible sources. |
| next_page_token | string | next_page_token is the cursor for the next page; empty when exhausted. |
PreviewDriveFolderRequest
PreviewDriveFolderRequest asks the Drive folder connector to size a folder before a gdrive source is created (#1430). It carries no source id — nothing is persisted.
| Field | Type | Label | Description |
|---|---|---|---|
| folder | string | folder is the Google Drive folder URL (e.g. https://drive.google.com/drive/folders/<ID>) or a raw folder id. The folder must already be shared (Viewer) with the connector's service-account email. |
PreviewDriveFolderResponse
PreviewDriveFolderResponse reports the size of a Drive folder without ingesting it.
| Field | Type | Label | Description |
|---|---|---|---|
| total_bytes | int64 | total_bytes is the summed binary size of all INGESTABLE files (excludes unsupported types and Google-native files, which report 0 binary bytes). It is a download-size estimate so the UI can warn before a large sync. | |
| file_count | int32 | file_count is the number of ingestable files the sync would process. | |
| unsupported_count | int32 | unsupported_count is the number of files skipped because their MIME type is not ingestable. | |
| breakdown | DriveTypeBreakdown | repeated | breakdown is the per-category tally (one entry per non-empty category). |
| truncated | bool | truncated is true when the folder hit the preview scan caps (max file count or max recursion depth); the totals are then a lower bound, not exact. |
RefreshSourceRequest
RefreshSourceRequest triggers a manual re-fetch of a source.
| Field | Type | Label | Description |
|---|---|---|---|
| source_id | string | source_id is the source UUID to refresh (required). |
RefreshSourceResponse
RefreshSourceResponse reports the outcome of a refresh trigger.
| Field | Type | Label | Description |
|---|---|---|---|
| status | string | status is a machine-readable outcome: 'manual' — upload | |
| message | string | message is a human-readable explanation of the status. |
SetAgentSourceEnabledRequest
SetAgentSourceEnabledRequest toggles a per-agent disable override.
| Field | Type | Label | Description |
|---|---|---|---|
| agent_id | string | agent_id is the agent whose source visibility is being changed. | |
| source_id | string | source_id is the source being enabled/disabled for the agent. | |
| enabled | bool | enabled=false inserts a disable override; enabled=true removes it. |
SetAgentSourceEnabledResponse
SetAgentSourceEnabledResponse echoes the resulting enabled state.
| Field | Type | Label | Description |
|---|---|---|---|
| enabled | bool | enabled is the effective state after the call (true = agent retrieves the source, false = disabled). |
Source
Source is a scope-agnostic, org-owned knowledge corpus. Its retrieval visibility is decided entirely by its knowledge_source_units bindings (HLD-C §3.1), NOT by a single owning scope. Fields 4/5 (the legacy owning_scope / unit_id, HLD-A D3 1:1 model) were dropped in the RA2 REPLACE (#1382/#1377, founder-approved breaking change DC-3); their numbers + names are reserved so they can never be re-used.
| Field | Type | Label | Description |
|---|---|---|---|
| id | string | id is the source's UUID. | |
| name | string | name is the human-readable source name. | |
| description | string | description is an optional free-text description. | |
| src_type | string | src_type is one of 'upload' | |
| sync_status | string | sync_status is one of 'empty' | |
| doc_count | int32 | doc_count is the number of ingested documents in the source. | |
| chunk_count | int32 | chunk_count is the cached chunk count (authoritative count is COUNT(rag_chunks WHERE source_id = id)). | |
| created_by | string | created_by is the member id that created the source. | |
| created_at | google.protobuf.Timestamp | created_at is the source creation timestamp. | |
| updated_at | google.protobuf.Timestamp | updated_at is the last-modification timestamp. | |
| last_refreshed_at | google.protobuf.Timestamp | last_refreshed_at is the timestamp of the most recent successful refresh (manual re-fetch or scheduled connector sync). Unset until the source has been refreshed at least once. (MVP RAG refresh, #1367.) | |
| refresh_interval_seconds | int32 | refresh_interval_seconds is the desired auto-refresh cadence in seconds. 0 means auto-refresh is off (the column is NULL in the DB). The scheduled connector worker that honours this cadence is Track D; FW3 persists the value only. (MVP RAG refresh, #1367.) | |
| criticality | string | criticality is one of 'low' | |
| url | string | url is the connector fetch target. For src_type='web' it is the page URL (the Web URL connector enforces an https-only scheme allowlist + SSRF egress guard, #1375). For src_type='gdrive' it is the Google Drive folder URL or raw folder id the connector lists + ingests (the Drive folder connector, #1430). Empty for all other source types. |
SourceUnitBinding
SourceUnitBinding mirrors a knowledge_source_units row: a source attached to one org_unit with a visibility mode, OR an org-wide attachment (#1554). (RA1, #1381, migration 107; org scope migration 116.)
| Field | Type | Label | Description |
|---|---|---|---|
| id | string | id is the binding's UUID. | |
| org_id | string | org_id is the owning organisation. | |
| source_id | string | source_id is the attached knowledge source. | |
| unit_id | string | unit_id is the org_units.id the source is attached to. Empty for an org-scoped binding (owning_scope='org'). | |
| visibility | string | visibility is one of 'inherit_down' | |
| configured_by | string | configured_by is the member id that created the binding. | |
| created_at | google.protobuf.Timestamp | created_at is the binding creation timestamp. | |
| updated_at | google.protobuf.Timestamp | updated_at is the last-modification timestamp. | |
| owning_scope | string | owning_scope is 'unit' (a pillar/team attachment; unit_id is set) or 'org' (an org-wide attachment; unit_id is empty). An org binding is unioned into every scope's effective set. (#1554, migration 116.) |
UpdateSourceRequest
UpdateSourceRequest mutates a source's editable attributes. Every mutable
field is optional: when a field is unset it is left unchanged, when set it
replaces the stored value. id is required.
| Field | Type | Label | Description |
|---|---|---|---|
| id | string | id is the source UUID to update (required). | |
| name | string | optional | name, when set, replaces the source name (must be non-empty when present). |
| description | string | optional | description, when set, replaces the description (empty string clears it). |
| refresh_interval_seconds | int32 | optional | refresh_interval_seconds, when set, replaces the auto-refresh cadence; 0 turns auto-refresh off (persisted as NULL). |
| criticality | string | optional | criticality, when set, replaces the criticality ('low' |
| url | string | optional | url, when set, replaces the fetch target of a src_type='web' source. Must be a non-empty https URL; only meaningful for web sources. (#1375.) |
UpdateSourceResponse
UpdateSourceResponse returns the updated source.
| Field | Type | Label | Description |
|---|---|---|---|
| source | Source | source is the source after the update. |
KnowledgeService
KnowledgeService is the external (Connect / gRPC) surface for knowledge source lifecycle management. All operations are tenant-scoped via JWT-derived scope claims and PostgreSQL row-level security; the owning org and the acting member are taken from the request scope, never from the request body.
Access control (HLD §7, founder Design Call D6):
- CreateSource / DeleteSource / SetAgentSourceEnabled: clearance >= L3
AND the
knowledge.managerole capability. - ListSources / GetSource / GetSourceStatus: clearance >= L1 AND the
knowledge.readcapability; results are further filtered by the scope-visibility RLS policy on knowledge_sources.
| Method Name | Request Type | Response Type | Description |
|---|---|---|---|
| CreateSource | CreateSourceRequest | CreateSourceResponse | CreateSource registers a new knowledge source in the org-owned catalog (HLD-C §3.1 — sources are scope-agnostic; attach them to pillars/teams afterwards with AttachSourceToUnit). The owning org and creator are derived from the caller's scope. The source starts empty (sync_status='empty') unless its src_type is a not-yet-implemented connector, in which case it is created 'disabled'. |
| ListSources | ListSourcesRequest | ListSourcesResponse | ListSources pages the org-owned source catalog (org-isolation RLS only; after HLD-C there is no per-scope owning filter). Use ListEffectiveSources to see the resolved set for a pillar/team/agent with provenance. |
| GetSource | GetSourceRequest | GetSourceResponse | GetSource returns a single source by id, subject to the same scope-visibility policy as ListSources. |
| UpdateSource | UpdateSourceRequest | UpdateSourceResponse | UpdateSource mutates the editable attributes of a source (name, description, auto-refresh cadence, criticality). All update fields are optional: an unset field is left unchanged. Clearance >= L5 AND knowledge.manage (MVP edit floor, #1367). src_type is immutable; scope is managed via AttachSourceToUnit, not UpdateSource. (MVP RAG refresh/ criticality, #1367.) |
| RefreshSource | RefreshSourceRequest | RefreshSourceResponse | RefreshSource triggers a manual re-fetch of a source's content. For the upload |
| DeleteSource | DeleteSourceRequest | DeleteSourceResponse | DeleteSource soft-deletes the source row and hard-deletes its derived chunks via ON DELETE CASCADE (founder Design Call D2). A tamper-evident audit row records the deletion and the count of chunks removed. The retained artifact for regulated tenants is the source document, not the reproducible chunks. |
| SetAgentSourceEnabled | SetAgentSourceEnabledRequest | SetAgentSourceEnabledResponse | SetAgentSourceEnabled toggles a per-agent disable override for a source. enabled=false inserts an override row (the agent stops retrieving the source even though its scope grants availability); enabled=true removes the row. Availability can only be narrowed by an agent, never widened. |
| GetSourceStatus | GetSourceStatusRequest | GetSourceStatusResponse | GetSourceStatus reports ingestion progress for a source so the UI can render a sync indicator: total documents, total chunks, and the embedded-vs-pending split. (Embedded/pending are populated by FW3-b's embed worker; FW3-a returns the cached counts and the persisted status.) |
| PreviewDriveFolder | PreviewDriveFolderRequest | PreviewDriveFolderResponse | PreviewDriveFolder lists a Google Drive folder (the Drive folder connector, #1430) WITHOUT ingesting anything and returns the overall size + file count + a per-type breakdown so the UI can show the user how big a sync will be BEFORE they commit to creating the gdrive source. The folder must already be shared (Viewer) with the connector's service-account email; the request carries the folder URL or raw folder id. This is a read-only dry-run: no knowledge_sources row is created and nothing is chunked or embedded. Clearance >= L5 AND knowledge.manage (same floor as CreateSource — only a source manager previews a folder, and the file listing is sensitive). When the gdrive connector is not configured on the deployment (no GDRIVE_CREDENTIALS_FILE) the call returns FailedPrecondition. |
| IngestDocument | IngestDocumentRequest | IngestDocumentResponse | IngestDocument feeds one document into a source's corpus (FW3-b, #1325). The server extracts text from the supplied bytes (markdown / html / pdf / plain), chunks it with the existing headings-aware chunker, embeds the chunks via the existing embedding pipeline, and persists them to rag_chunks + context_embeddings stamped with the source_id and the source's owning scope. Ingestion is idempotent on the document's content_hash: re-sending identical bytes for the same source is a no-op that returns the prior result (idempotent_hit=true). Access control: clearance >= L2 (founder Design Call D6 Ingest floor) AND the knowledge.manage capability. Only upload |
| AttachSourceToUnit | AttachSourceToUnitRequest | AttachSourceToUnitResponse | AttachSourceToUnit tags a source onto an org_unit (pillar/team) with a visibility mode, exactly like attaching a tool to a unit (org_unit_tools, migration 064). A source may be attached to many units; availability is then computed by the same org→pillar→team inheritance walk the tool model uses. The acting member (configured_by) is taken from the caller's scope, never the request body. Clearance >= L5 (the consolidated knowledge management floor) AND knowledge.manage. (RA1, #1381, HLD-C §7.) |
| DetachSourceFromUnit | DetachSourceFromUnitRequest | DetachSourceFromUnitResponse | DetachSourceFromUnit soft-deletes a source⇄unit binding (re-attach later is allowed). Clearance >= L5 AND knowledge.manage. (RA1, #1381, HLD-C §7.) |
| ListSourceUnits | ListSourceUnitsRequest | ListSourceUnitsResponse | ListSourceUnits returns the units a source is currently attached to (its active bindings). Clearance >= L1 AND knowledge.read. (RA1, #1381.) |
| ListEffectiveSources | ListEffectiveSourcesRequest | ListEffectiveSourcesResponse | ListEffectiveSources resolves the effective source set for exactly one of {unit_id, member_id, agent_id} via the org→pillar→team inheritance walk (direct ∪ inherited-down ∪ shared-siblings; de-dup direct > inherited > sibling), each entry tagged with its provenance. Clearance >= L1 AND knowledge.read. (RA1, #1381, HLD-C §4/§7.) |
Scalar Value Types
| .proto Type | Notes | C++ | Java | Python | Go | C# | PHP | Ruby |
|---|---|---|---|---|---|---|---|---|
| double | double | double | float | float64 | double | float | Float | |
| float | float | float | float | float32 | float | float | Float | |
| int32 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) |
| int64 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. | int64 | long | int/long | int64 | long | integer/string | Bignum |
| uint32 | Uses variable-length encoding. | uint32 | int | int/long | uint32 | uint | integer | Bignum or Fixnum (as required) |
| uint64 | Uses variable-length encoding. | uint64 | long | int/long | uint64 | ulong | integer/string | Bignum or Fixnum (as required) |
| sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) |
| sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long | int64 | long | integer/string | Bignum |
| fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int | uint32 | uint | integer | Bignum or Fixnum (as required) |
| fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long | uint64 | ulong | integer/string | Bignum |
| sfixed32 | Always four bytes. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) |
| sfixed64 | Always eight bytes. | int64 | long | int/long | int64 | long | integer/string | Bignum |
| bool | bool | boolean | boolean | bool | bool | boolean | TrueClass/FalseClass | |
| string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode | string | string | string | String (UTF-8) |
| bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str | []byte | ByteString | string | String (ASCII-8BIT) |