Context Engine (context) API
Table of Contents
upsquad/context/v1/context.proto
AssembleContextRequest
AssembleContextRequest is the input to the primary hot-path RPC. The engine assembles a cache-friendly prompt from immutable layers, pinned chunks, and retrieved semantic context within the token budget.
| Field | Type | Label | Description |
|---|---|---|---|
| scope | ScopePath | scope is the caller's position in the tenant hierarchy (from JWT). | |
| session_id | string | session_id identifies the active conversation session. | |
| task_description | string | task_description is the current agent task used to drive semantic retrieval. | |
| token_budget | int32 | token_budget is the maximum number of tokens the assembled prompt may use. | |
| model_id | string | model_id identifies the target LLM so token counting uses the correct tokenizer. | |
| hints | AssembleContextRequest.HintsEntry | repeated | hints carry optional directives such as pinned_chunk_ids or must_include keys. |
AssembleContextRequest.HintsEntry
| Field | Type | Label | Description |
|---|---|---|---|
| key | string | ||
| value | string |
AssembleContextResponse
AssembleContextResponse is the result of context assembly. It includes the assembled prompt, cache boundary metadata, quality attestation, and savings metrics.
| Field | Type | Label | Description |
|---|---|---|---|
| prompt_id | string | prompt_id is the SHA-256 content hash of the assembled prompt, usable as a stable cache key for provider-side prompt caching. | |
| assembled_prompt | string | assembled_prompt is the full prompt string ready for LLM dispatch. The stable prefix (layers L1–L4 + pinned chunks) is placed first to maximise provider cache hit rate. | |
| cache_prefix_bytes | int32 | cache_prefix_bytes is the byte offset marking the boundary between the stable prefix and the unstable tail. Callers should apply cache_control up to this boundary. | |
| assembled_tokens | int32 | assembled_tokens is the token count of the assembled prompt. | |
| baseline_tokens | int32 | baseline_tokens is the naive token count (no optimisation) sampled on a percentage of calls. Zero when not sampled this call. | |
| savings_ratio | double | savings_ratio is (baseline_tokens - assembled_tokens) / baseline_tokens. Zero when not sampled. | |
| version_hash | string | version_hash is the Merkle hash of all included chunks; used for delta reuse. | |
| chunk_ids | string | repeated | chunk_ids lists the IDs of every chunk included in the assembled prompt. |
| quality | QualityAttestation | quality contains attestation data about retrieval confidence. |
CompactRequest
CompactRequest triggers synchronous compaction for a session. Async compaction is triggered automatically via Redis Streams when session tokens exceed 80% of the token budget.
| Field | Type | Label | Description |
|---|---|---|---|
| scope | ScopePath | scope is the caller's position in the tenant hierarchy. | |
| session_id | string | session_id identifies the session to compact. | |
| strategy | string | strategy selects the compaction algorithm. Only 'sliding_window' is supported in MVP. |
CompactResponse
CompactResponse reports compaction results including quality metrics.
| Field | Type | Label | Description |
|---|---|---|---|
| version_hash | string | version_hash is the content hash of the post-compaction session state. | |
| original_tokens | int32 | original_tokens is the token count before compaction. | |
| compacted_tokens | int32 | compacted_tokens is the token count after compaction. | |
| fact_retention_score | double | fact_retention_score is the self-evaluated quality score in [0, 1]. Compaction is rejected (QUALITY_GUARDRAIL_TRIGGERED) if this falls below 0.98. |
CreateShareRequest
CreateShareRequest grants a grantee scope access to a specific resource. The grantor scope is inferred from the caller's JWT claims. Requires clearance L3+; cross-pillar shares require L4+.
| Field | Type | Label | Description |
|---|---|---|---|
| scope | ScopePath | scope is the grantor's position in the tenant hierarchy. | |
| resource_id | string | resource_id is the UUID of the resource (chunk, snapshot, layer) to share. | |
| resource_type | string | resource_type identifies the kind of resource: 'chunk', 'snapshot', 'layer'. | |
| grantee_scope | string | grantee_scope is the hierarchical scope type of the grantee: 'org', 'pillar', 'team', or 'agent'. | |
| grantee_scope_id | string | grantee_scope_id is the UUID of the grantee entity within grantee_scope. | |
| permissions | string | repeated | permissions is the list of allowed operations: 'read', 'use_in_assembly'. |
| reason | string | reason is an optional audit-trail annotation for the share grant. |
CreateShareResponse
CreateShareResponse confirms the share grant creation.
| Field | Type | Label | Description |
|---|---|---|---|
| share_id | string | share_id is the UUID of the created share grant record. | |
| created_at | google.protobuf.Timestamp | created_at is the server-side timestamp of the grant. |
CreateSnapshotRequest
CreateSnapshotRequest creates a named, immutable snapshot of the current session state. Requires clearance L2 or above.
| Field | Type | Label | Description |
|---|---|---|---|
| scope | ScopePath | scope is the caller's position in the tenant hierarchy. | |
| session_id | string | session_id identifies the session to snapshot. | |
| snapshot_name | string | snapshot_name is the human-readable label for this snapshot. |
CreateSnapshotResponse
CreateSnapshotResponse confirms snapshot creation.
| Field | Type | Label | Description |
|---|---|---|---|
| snapshot_id | string | snapshot_id is the UUID of the created snapshot record. | |
| version_hash | string | version_hash is the content hash of the snapshotted state. | |
| created_at | google.protobuf.Timestamp | created_at is the server-side timestamp of the snapshot. |
EmbedRequest
EmbedRequest generates embeddings for one or more text inputs. Results are cached by content hash (30-day TTL).
| Field | Type | Label | Description |
|---|---|---|---|
| scope | ScopePath | scope is the caller's position in the tenant hierarchy. | |
| texts | string | repeated | texts is the list of strings to embed. Batches up to 100 items. |
| model_version | string | model_version does NOT select a model. The server always uses the embedder it is configured with, and this field is only an assertion about which one that is: leave it empty, or set it to the exact value a previous response reported. Anything else is rejected INVALID_ARGUMENT. |
It was a selector once, and the selected value keyed the embedding cache — a namespace the RAG ingest path shares at a 30-day TTL — so a request could file vectors from the running model under a different model's name and have a later ingest store them under a correct-looking stamp. See LLD #2714 section 3 G-c, PRD 996 FR-12: model identity is derived from the running embedder, never supplied by a caller. |
EmbedResponse
EmbedResponse returns one embedding vector per input text.
| Field | Type | Label | Description |
|---|---|---|---|
| embeddings | EmbeddingVector | repeated | embeddings is the list of float32 vectors, in the same order as the request texts. |
| model_version | string | model_version records which model revision produced these embeddings. |
EmbeddingVector
EmbeddingVector holds a single dense embedding vector.
| Field | Type | Label | Description |
|---|---|---|---|
| values | float | repeated | values is the float32 representation. Dimension is model-dependent (default 1536). |
| cached | bool | cached is true when this embedding was served from the Redis embedding cache. |
GuardrailLayer
GuardrailLayer describes one immutable guardrail layer (L1-L4) as it stands right now in the guardrail store. The version is the freshness oracle the orchestrator uses to decide whether to re-pin at a turn boundary.
| Field | Type | Label | Description |
|---|---|---|---|
| layer_level | int32 | layer_level is the chain-of-trust level, 1..4 (L1 platform, L2 tenant, L3 team, L4 agent). | |
| content_hash | string | content_hash is the current SHA-256 of the active layer content. | |
| version | int64 | version is monotonic per (scope, layer_level): a higher version is always a strictly later revision. Re-pin only auto-adopts forward versions. | |
| effective_at | int64 | effective_at is the unix-milliseconds timestamp at which this version became active (derived from the layer's signed_at). |
IngestEventRequest
IngestEventRequest persists a single conversation event.
| Field | Type | Label | Description |
|---|---|---|---|
| scope | ScopePath | scope is the caller's position in the tenant hierarchy. | |
| session_id | string | session_id identifies the active conversation session. | |
| event_type | string | event_type categorises the event: 'message', 'tool_output', 'workflow_event'. | |
| content | bytes | content is the raw event payload; encoding is caller-defined (typically UTF-8 JSON). | |
| metadata | IngestEventRequest.MetadataEntry | repeated | metadata carries optional key-value annotations (e.g. role, tool_name, latency_ms). |
IngestEventRequest.MetadataEntry
| Field | Type | Label | Description |
|---|---|---|---|
| key | string | ||
| value | string |
IngestEventResponse
IngestEventResponse confirms ingestion and returns the content hash for deduplication and delta tracking.
| Field | Type | Label | Description |
|---|---|---|---|
| event_id | string | event_id is the UUID of the persisted event record. | |
| version_hash | string | version_hash is the SHA-256 of the event content; used for deduplication. | |
| token_count | int32 | token_count is the tiktoken-computed token count of the content. |
ListSharesRequest
ListSharesRequest retrieves all share grants visible to the caller.
| Field | Type | Label | Description |
|---|---|---|---|
| scope | ScopePath | scope is the caller's position in the tenant hierarchy. | |
| page | int32 | page is the 1-based page number for pagination. | |
| page_size | int32 | page_size is the maximum number of results per page. Max 100. |
ListSharesResponse
ListSharesResponse returns a paginated list of share grants.
| Field | Type | Label | Description |
|---|---|---|---|
| shares | ShareGrant | repeated | shares is the list of share grant records visible to the caller. |
| total_count | int32 | total_count is the total number of matching grants (for pagination). |
PullContextRequest
PullContextRequest retrieves a memory snapshot from the version store. Always reads from primary DB — never from cache.
| Field | Type | Label | Description |
|---|---|---|---|
| scope | ScopePath | scope is the caller's position in the tenant hierarchy. | |
| agent_id | string | agent_id identifies the agent whose memory is being retrieved. | |
| session_id | string | session_id optionally scopes the pull to a specific session. | |
| snapshot_name | string | snapshot_name optionally targets a named snapshot instead of the latest version. |
PullContextResponse
PullContextResponse returns the memory snapshot payload.
| Field | Type | Label | Description |
|---|---|---|---|
| version_hash | string | version_hash identifies the version of the returned snapshot. | |
| memory_type | string | memory_type categorises the returned content. | |
| content | bytes | content is the serialised memory payload. | |
| created_at | google.protobuf.Timestamp | created_at is the timestamp of the snapshot. | |
| metadata | PullContextResponse.MetadataEntry | repeated | metadata carries annotations stored with the snapshot. |
PullContextResponse.MetadataEntry
| Field | Type | Label | Description |
|---|---|---|---|
| key | string | ||
| value | string |
PushContextRequest
PushContextRequest persists a memory snapshot to the version store.
| Field | Type | Label | Description |
|---|---|---|---|
| scope | ScopePath | scope is the caller's position in the tenant hierarchy. | |
| session_id | string | session_id identifies the session whose memory is being pushed. | |
| memory_type | string | memory_type categorises the content: 'episodic', 'semantic', 'working'. | |
| content | bytes | content is the serialised memory payload. | |
| metadata | PushContextRequest.MetadataEntry | repeated | metadata carries optional annotations. |
PushContextRequest.MetadataEntry
| Field | Type | Label | Description |
|---|---|---|---|
| key | string | ||
| value | string |
PushContextResponse
PushContextResponse confirms the push and returns the new version hash.
| Field | Type | Label | Description |
|---|---|---|---|
| version_hash | string | version_hash is the SHA-256 of the pushed content; acts as a version tag. | |
| created_at | google.protobuf.Timestamp | created_at is the server-side timestamp of the push. |
QualityAttestation
QualityAttestation captures retrieval quality signals attached to every AssembleContextResponse. It REPORTS what the retrieval leg did; nothing in the engine branches on it.
This header previously said "used by the guardrail engine to decide whether
to expand retrieval or fall back to recency-only", and that was false in both
halves — corrected in core#3079 because it is where the claim was being read
from. internal/context/guardrail never touches these fields (its Evaluate
takes a prompt and a rule set), and the expansion decision is made inside
retrieval from results[0].Score via ConfidenceGate.NeedsExpansion, before
any attestation exists. The known consumers are the agent worker's
AssembledContext.metadata and one structured log field
(services/agent-worker/src/agent_worker/context/client.py).
Telemetry, in other words — which is a reason to keep it honest, not a reason to care less: a wrong value here is read by a human deciding how hard to look.
| Field | Type | Label | Description |
|---|---|---|---|
| confidence_score | double | confidence_score is the mean retrieval similarity score in [0, 1], over the chunks the caller actually received. Zero when none were. | |
| expansion_applied | bool | expansion_applied is true when the engine broadened the retrieval pool due to a low initial confidence score. | |
| fallback_used | bool | fallback_used is true when the engine fell back to recency-only retrieval because semantic retrieval failed or returned no results. | |
| fallback_reason | string | fallback_reason describes why the fallback was triggered. |
When no fallback ran but the assembled prompt still carries no retrieved chunks, this holds the retrieval_outcome's name (no_results / below_threshold) rather than being left empty — an empty reason beside an empty retrieval is the silent state US-9 forbids. Prefer retrieval_outcome: it is the closed enumeration, this field is prose. |
| retrieval_outcome | RetrievalOutcome | | retrieval_outcome names why the retrieval leg contributed what it did (PRD #2995 US-9). It is the SAME classification ContextEngine.Search puts on SearchResponse.outcome, produced by the same code path, so the two surfaces cannot disagree about one retrieval.
UNSPECIFIED here means the retrieval leg did not run or did not complete — no retrieval service wired, no task description, or a hard retrieval failure — and in every one of those cases fallback_used is true and fallback_reason names the cause. | | effective_min_score | double | | effective_min_score is the relevance floor the retrieval leg applied. Same meaning as SearchResponse.effective_min_score; on this surface it is the resolved value of the tenant's retrieval_min_score knob (core#2618). | | results_below_threshold | int32 | | results_below_threshold is how many retrieved candidates effective_min_score removed. Same meaning as SearchResponse.results_below_threshold.
Non-zero with an empty retrieval section is the "the corpus has this, just not above your floor" signal — the one an operator previously had to go and reconstruct by hand with a second Search call at a lower floor. |
ResolveGuardrailLayersRequest
ResolveGuardrailLayersRequest asks the engine for the current guardrail layer set for the caller's scope. It carries only the scope; the engine resolves the active L1-L4 layers under the same RLS GUC as ValidatePrompt.
| Field | Type | Label | Description |
|---|---|---|---|
| scope | ScopePath | scope is the caller's position in the tenant hierarchy (from JWT). |
ResolveGuardrailLayersResponse
ResolveGuardrailLayersResponse returns the current L1-L4 guardrail layers, each labelled with its monotonic store version. Layers are returned in ascending layer_level order (L1..L4). A layer that has no active row for the scope is simply absent from the list.
| Field | Type | Label | Description |
|---|---|---|---|
| layers | GuardrailLayer | repeated | layers is the current guardrail set, L1-L4, ascending by layer_level. |
RevokeShareRequest
RevokeShareRequest removes an existing share grant. Requires clearance L3+ or being the original grant creator.
| Field | Type | Label | Description |
|---|---|---|---|
| scope | ScopePath | scope is the caller's position in the tenant hierarchy. | |
| share_id | string | share_id is the UUID of the share grant to revoke. | |
| reason | string | reason is an optional audit-trail annotation for the revocation. |
RevokeShareResponse
RevokeShareResponse confirms share grant revocation.
| Field | Type | Label | Description |
|---|---|---|---|
| revoked_at | google.protobuf.Timestamp | revoked_at is the server-side timestamp of the revocation. |
RollbackContextRequest
RollbackContextRequest reverts a session to a previous version. Requires clearance L3 or above (team lead).
| Field | Type | Label | Description |
|---|---|---|---|
| scope | ScopePath | scope is the caller's position in the tenant hierarchy. | |
| session_id | string | session_id identifies the session to roll back. | |
| target_version_hash | string | target_version_hash is the content hash of the version to restore. |
RollbackContextResponse
RollbackContextResponse confirms the rollback and reports the restored state.
| Field | Type | Label | Description |
|---|---|---|---|
| restored_version_hash | string | restored_version_hash is the hash of the now-active version after rollback. | |
| rolled_back_at | google.protobuf.Timestamp | rolled_back_at is the server-side timestamp of the rollback operation. |
ScopePath
ScopePath identifies the caller's position in the tenant hierarchy. Every RPC must carry a ScopePath extracted from the caller's JWT claims. The engine validates that the scope in the request matches the JWT scope and enforces hierarchical isolation: Org > Pillar > Team > Agent.
| Field | Type | Label | Description |
|---|---|---|---|
| org_id | string | org_id is always required; identifies the tenant organisation. | |
| pillar_id | string | pillar_id is empty when operating at org level. | |
| team_id | string | team_id is empty when operating at pillar level or above. | |
| agent_id | string | agent_id is empty when operating at team level or above. |
SearchRequest
SearchRequest performs a hybrid (vector + BM25 + recency) search.
| Field | Type | Label | Description |
|---|---|---|---|
| scope | ScopePath | scope is the caller's position in the tenant hierarchy. | |
| query | string | query is the natural-language search string. | |
| domain | string | domain optionally restricts the search to a specific knowledge domain. | |
| top_k | int32 | top_k is the maximum number of results to return. Default: 10. | |
| min_score | double | min_score is the minimum similarity threshold for inclusion. Default: 0.7. |
SearchResponse
SearchResponse wraps a ranked list of search results.
| Field | Type | Label | Description |
|---|---|---|---|
| results | SearchResult | repeated | results is the ranked list of matching chunks. |
| effective_min_score | double | effective_min_score is the relevance floor the server ACTUALLY applied to this search, stated so a caller never has to infer it (PRD #2995 TK-5.5). |
It is not an echo of the request. A request that omits min_score — or sends 0, which proto3 cannot tell from omitted — selects the server's default, and that default is the STRICTEST floor the engine has rather than the loosest (core#2618). Before this field the only way to learn which floor ran was to re-issue the query at a known floor and compare the two result sets.
Strictly positive on any response from this server. A zero means the responder did not state a floor, which is a fact about the responder. | | results_below_threshold | int32 | | results_below_threshold is how many candidates effective_min_score removed.
The denominator is the fused candidate set retrieval produced for this query, BEFORE the caller's floor and before the top_k cap. It counts rows the FLOOR dropped and nothing else: rows left out because the caller asked for fewer than were available are above the floor and are not counted here. | | outcome | RetrievalOutcome | | outcome names why this response holds what it holds. See RetrievalOutcome. |
SearchResult
SearchResult is a single retrieved chunk with its provenance and score.
| Field | Type | Label | Description |
|---|---|---|---|
| chunk_id | string | chunk_id is the UUID of the stored chunk. | |
| content | string | content is the decoded text content of the chunk. | |
| score | double | score is the final hybrid relevance score in [0, 1]. | |
| source | string | source identifies the origin document or event that produced this chunk. | |
| metadata | SearchResult.MetadataEntry | repeated | metadata carries additional key-value annotations on the chunk. |
SearchResult.MetadataEntry
| Field | Type | Label | Description |
|---|---|---|---|
| key | string | ||
| value | string |
ShareGrant
ShareGrant is a single share grant record as returned by ListShares.
| Field | Type | Label | Description |
|---|---|---|---|
| share_id | string | share_id is the UUID of this grant. | |
| resource_id | string | resource_id is the UUID of the shared resource. | |
| resource_type | string | resource_type identifies the kind of resource. | |
| grantor_scope_id | string | grantor_scope_id is the UUID of the entity that created the grant. | |
| grantee_scope | string | grantee_scope is the hierarchical scope type of the grantee. | |
| grantee_scope_id | string | grantee_scope_id is the UUID of the grantee entity. | |
| permissions | string | repeated | permissions is the list of allowed operations. |
| reason | string | reason is the audit annotation recorded at grant creation. | |
| created_at | google.protobuf.Timestamp | created_at is when the grant was created. |
ValidatePromptRequest
ValidatePromptRequest submits an assembled prompt for tampering and injection detection against the 4-layer hash chain.
| Field | Type | Label | Description |
|---|---|---|---|
| scope | ScopePath | scope is the caller's position in the tenant hierarchy. | |
| prompt | string | prompt is the assembled prompt string to validate. | |
| layer_hashes | string | repeated | layer_hashes contains the expected SHA-256 hashes of layers L1–L4 in order. The engine verifies the prompt contains these layers verbatim. |
ValidatePromptResponse
ValidatePromptResponse reports the validation result.
| Field | Type | Label | Description |
|---|---|---|---|
| valid | bool | valid is true when the prompt passes all validation checks. | |
| violation_code | string | violation_code is set when valid is false; maps to the error code taxonomy. | |
| violation_detail | string | violation_detail provides a human-readable explanation of the violation. |
RetrievalOutcome
RetrievalOutcome names WHY a retrieval returned what it returned.
It exists because an empty result set is not one fact, it is several, and a caller that cannot tell them apart has to guess — which for an LLM agent means inventing an answer. PRD #2995 US-9: "a named, actionable error instead of an empty result, so that I can tell the user WHY I have nothing rather than inventing something."
The member names ARE the vocabulary US-9 enumerates: strip the
RETRIEVAL_OUTCOME_ prefix and lowercase, and RETRIEVAL_OUTCOME_BELOW_THRESHOLD
is below_threshold. Consumers that need the string should DERIVE it that way
rather than transcribing a second table — a transcribed copy is a second thing
to keep in step (internal/context/retrieval.OutcomeName does the derivation).
The enumeration is CLOSED on purpose (PRD #2995 TK-5.5): a future outcome has to be added here, deliberately, rather than arriving at a caller as a bare empty result set that has quietly started to mean something new.
| Name | Number | Description |
|---|---|---|
| RETRIEVAL_OUTCOME_UNSPECIFIED | 0 | The server did not classify this retrieval. |
Zero is UNSPECIFIED and not OK deliberately. proto3 gives a bare enum no field presence, so "the server never set it" and "the server set the zero value" are the same byte — which means the zero value has to be the one it is safe to forget. An unclassified empty response reads as "nobody said why", which a caller can surface; if zero meant OK it would read as "here are your zero results", and that is the silent-empty failure this whole enumeration exists to remove. Same reasoning as SearchRequest.min_score, arrived at from the other side (core#2618). | | RETRIEVAL_OUTCOME_OK | 1 | At least one result cleared the effective floor and is carried in this response. results_below_threshold may still be non-zero — a partial answer is an outcome worth naming as one. | | RETRIEVAL_OUTCOME_NO_RESULTS | 2 | No candidate was produced at all: the rankers found nothing in the caller's effective corpus for this query. The floor removed nothing, and results_below_threshold is 0. | | RETRIEVAL_OUTCOME_BELOW_THRESHOLD | 3 | Candidates were produced and EVERY one of them scored below the effective floor. results_below_threshold says how many; effective_min_score says what they fell under. This is the state that used to be indistinguishable from NO_RESULTS, and telling the two apart is what lets an agent widen the query, ask for a lower floor, or say plainly that the corpus holds nothing above the bar — instead of answering from silence. | | RETRIEVAL_OUTCOME_ACCESS_REVOKED_UPSTREAM | 4 | The upstream system revoked the platform's access to a source that would have answered. Declared so the enumeration is closed; produced by F3 (access parity), not by Phase 1. | | RETRIEVAL_OUTCOME_SOURCE_UNAVAILABLE | 5 | A source that would have answered could not be reached. Declared so the enumeration is closed; produced by F4 (live fetch), not by Phase 1. | | RETRIEVAL_OUTCOME_DOCUMENT_NO_LONGER_EXISTS | 6 | The document was OBSERVED to be gone upstream. Declared so the enumeration is closed; produced by F4, not by Phase 1. | | RETRIEVAL_OUTCOME_DOCUMENT_REF_UNRESOLVED | 7 | A document reference could not be resolved to a document — a moved page, a path-shaped ref whose path changed. Distinct from DOCUMENT_NO_LONGER_EXISTS, which asserts an upstream deletion we have actually observed (PRD #2995 v1.2 renamed the two apart for exactly that reason). Declared so the enumeration is closed; produced by F4, not by Phase 1. |
ContextEngine
ContextEngine is the central gRPC service for all context, memory, and retrieval operations. It sits between the Agent Runtime and the data layer.
--- Hot path (called before every LLM call) ---
| Method Name | Request Type | Response Type | Description |
|---|---|---|---|
| AssembleContext | AssembleContextRequest | AssembleContextResponse | AssembleContext assembles an optimised prompt from the 4-layer immutable chain of trust plus retrieved semantic chunks. Target latency: p95 < 500ms. |
| IngestEvent | IngestEventRequest | IngestEventResponse | IngestEvent persists a conversation event, computes its content hash, counts tokens, and enqueues async embedding. |
| Compact | CompactRequest | CompactResponse | Compact summarises older session history via the compaction LLM (Gemini 2.5 Flash-Lite) when session tokens exceed 80% of the token budget. Only the sliding_window strategy is supported in MVP. |
| PushContext | PushContextRequest | PushContextResponse | PushContext persists a memory snapshot to the version-controlled store. |
| PullContext | PullContextRequest | PullContextResponse | PullContext retrieves a memory snapshot. Reads from primary DB (never cache). |
| RollbackContext | RollbackContextRequest | RollbackContextResponse | RollbackContext reverts a session to a previous version hash. Requires clearance L3 or above. |
| CreateSnapshot | CreateSnapshotRequest | CreateSnapshotResponse | CreateSnapshot creates a named, immutable snapshot of the current session state. Requires clearance L2 or above. |
| ValidatePrompt | ValidatePromptRequest | ValidatePromptResponse | ValidatePrompt checks an assembled prompt against the 4-layer hash chain to detect tampering and prompt-injection patterns. |
| Search | SearchRequest | SearchResponse | Search performs a hybrid (vector + BM25 + recency) search across the caller's accessible context corpus. |
| Embed | EmbedRequest | EmbedResponse | Embed generates embeddings for the provided texts using the configured embedding model (default: text-embedding-3-small). Results are cached by content hash with a 30-day TTL. |
| CreateShare | CreateShareRequest | CreateShareResponse | CreateShare grants a named grantee scope access to a specific resource. Requires clearance L3+; cross-pillar shares require L4+. |
| RevokeShare | RevokeShareRequest | RevokeShareResponse | RevokeShare removes an existing share grant. Requires clearance L3+ or being the original grant creator. |
| ListShares | ListSharesRequest | ListSharesResponse | ListShares returns share grants where the caller is owner or grantee. |
| ResolveGuardrailLayers | ResolveGuardrailLayersRequest | ResolveGuardrailLayersResponse | ResolveGuardrailLayers returns the current 4-layer guardrail set (L1-L4) for the caller's scope, each labelled with its monotonic store version. This is the same layer set ValidatePrompt compares against, but exposes the version that already exists in the guardrail store so the orchestrator can distinguish a forward (tightening) update from a backward/sideways mutation at a turn boundary. Additive; ValidatePrompt is unchanged. Resolves under the same RLS GUC (app.org_id) as every other RPC. |
upsquad/context/v1/stream.proto
AuditAccessEvent
AuditAccessEvent is the payload carried in audit:access stream messages. Published by any service that performs a cross-scope access operation. Consumed by the Audit Writer for async persistence to the audit log.
| Field | Type | Label | Description |
|---|---|---|---|
| actor_scope | ScopePath | actor_scope is the scope of the entity performing the access. | |
| target_resource_id | string | target_resource_id is the UUID of the accessed resource. | |
| target_resource_type | string | target_resource_type identifies the kind of accessed resource. | |
| operation | string | operation describes the action performed (e.g. 'read', 'create_share'). | |
| share_id | string | share_id is set when the access was via a share grant. | |
| outcome | string | outcome is 'allowed' or 'denied'. | |
| denial_reason | string | denial_reason is set when outcome is 'denied'. | |
| occurred_at | google.protobuf.Timestamp | occurred_at is the timestamp of the access attempt. |
BaselineMetricEvent
BaselineMetricEvent is the payload carried in metrics:baseline stream messages. Published by the Assembly Pipeline on sampled calls to measure naive token usage. Consumed by the Baseline Calculator for savings ratio computation.
| Field | Type | Label | Description |
|---|---|---|---|
| prompt_id | string | prompt_id is the content hash of the assembled prompt being measured. | |
| scope | ScopePath | scope is the caller's position in the tenant hierarchy. | |
| session_id | string | session_id identifies the session. | |
| assembled_tokens | int32 | assembled_tokens is the optimised token count. | |
| naive_tokens | int32 | naive_tokens is the unoptimised (baseline) token count. | |
| model_id | string | model_id is the target LLM that will consume this prompt. | |
| sampled_at | google.protobuf.Timestamp | sampled_at is when this sample was taken. |
CompactionJob
CompactionJob is the payload carried in compaction:{org_id} stream messages. Published by the Assembly Pipeline when session tokens exceed 80% of budget. Consumed by the Compaction Worker Pool.
| Field | Type | Label | Description |
|---|---|---|---|
| session_id | string | session_id identifies the session that requires compaction. | |
| scope | ScopePath | scope is the session owner's position in the tenant hierarchy. | |
| current_token_count | int32 | current_token_count is the token count that triggered the compaction. | |
| token_budget | int32 | token_budget is the configured budget that was exceeded. | |
| strategy | string | strategy is the requested compaction strategy (currently 'sliding_window'). | |
| triggered_at | google.protobuf.Timestamp | triggered_at is the timestamp when the threshold was crossed. |
EmbeddingJob
EmbeddingJob is the payload carried in embedding:{org_id} stream messages. Published by the Ingestion Service for async chunk embedding. Consumed by the Embedding Pipeline.
| Field | Type | Label | Description |
|---|---|---|---|
| event_id | string | event_id is the UUID of the ingested event whose content needs embedding. | |
| chunk_ids | string | repeated | chunk_ids are the UUIDs of the text chunks to embed. |
| scope | ScopePath | scope is the caller's position in the tenant hierarchy. | |
| model_version | string | model_version selects the embedding model revision. Empty = default. | |
| queued_at | google.protobuf.Timestamp | queued_at is the timestamp when this job was enqueued. |
ReindexJob
ReindexJob is the payload carried in reindex:{org_id} stream messages. Published by the Admin API when the embedding model version changes or when corruption is detected. Consumed by the Reindex Worker.
| Field | Type | Label | Description |
|---|---|---|---|
| scope | ScopePath | scope identifies which org/pillar/team scope needs re-embedding. | |
| old_model_version | string | old_model_version is the model revision being replaced. | |
| new_model_version | string | new_model_version is the target model revision. | |
| initiated_by | string | initiated_by is the user/agent ID that triggered the reindex. | |
| initiated_at | google.protobuf.Timestamp | initiated_at is the timestamp of the reindex request. |
StreamEnvelope
StreamEnvelope is the common wrapper for every message published to a Redis Stream. It carries routing metadata (message_id, stream name, ScopePath) alongside the opaque serialised payload.
Stream → Payload type mapping: compaction:{org_id} → CompactionJob embedding:{org_id} → EmbeddingJob reindex:{org_id} → ReindexJob metrics:baseline → BaselineMetricEvent audit:access → AuditAccessEvent
| Field | Type | Label | Description |
|---|---|---|---|
| message_id | string | message_id is the unique identifier for this stream message (UUID). Consumers use this for idempotency and ACK tracking. | |
| stream | string | stream is the full Redis Stream key this message was published to (e.g. "compaction:org-123"). | |
| scope | ScopePath | scope is the ScopePath of the originating caller; used by consumers to re-establish tenant context without decoding the payload. | |
| created_at | google.protobuf.Timestamp | created_at is the server-side timestamp of publication. | |
| payload | bytes | payload is the stream-specific Protobuf message serialised to bytes. Consumers must decode it based on the stream field. |
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) |