Skip to main content
Version: 1.0.0

Context Service

Overview

The Context Service (ContextService, accessed via client.context) is the SDK wrapper for the Kamiwaza Context Service. Located in kamiwaza_sdk/services/context.py, it manages workroom-scoped vector databases, ontologies (knowledge graphs), ingestion pipelines, and retrieval against the documents and knowledge held inside a Workroom.

Every Context Service resource lives inside exactly one workroom. The SDK targets a workroom by passing workroom_id to a method (sent to the server as the X-Workroom-ID header). Some methods make workroom_id a required keyword-only argument (e.g. list_collections, create_pipeline_job, search, retrieve, upload_file); others accept it optionally, and when it is omitted the server resolves the caller's default workroom.

For PAT/API-key automation that makes several calls against the same workroom, derive a local scoped client instead of calling workrooms.enter():

with client.workroom_scope(my_workroom_id) as scoped:
db = scoped.context.create_vectordb(name="project-vdb", engine="milvus")
scoped.context.insert_vectors(
db["id"],
collection_name="project_docs",
vectors=[embedding],
metadata=[{"source": "seed"}],
)

The scoped client only adds the explicit workroom header on SDK requests; it does not change the parent client or mutate server-side selected-session state. It is not a client-side security boundary; the server must still authorize the caller for the requested workroom on every request.

Workrooms and the Global Workroom

A Workroom is the collaboration and isolation boundary for context: vector collections, ontologies, ingested files, and pipeline jobs all belong to a workroom, and access is scoped to that workroom's members.

The Global Workroom is a special, well-known workroom (the all-f sentinel ffffffff-ffff-ffff-ffff-ffffffffffff, exposed as ContextService.DEFAULT_WORKROOM_ID). It holds the platform's shared, read-only catalog of context — knowledge that is visible to everyone but owned by no single member.

The Global Workroom is read-only for tenant writes

Key semantics: Any direct write that targets the Global Workroom is rejected by the server with HTTP 403 and a body of Global Workroom is read-only for <operation> (for example Global Workroom is read-only for ontology creation). This is intentional and by design, not a bug — the Global Workroom is a shared catalog, so it is populated only by the platform's own ingestion paths, never by ad-hoc tenant writes.

Reads against the Global Workroom are always allowed (results are requester-scoped where appropriate). Writes are blocked. The table below lists the server-side policy categories — some (e.g. pipeline retry/rerun/delete, workroom archive/restore/purge) are enforced by the Context Service but are not all surfaced as client.context methods; the SDK exposes a subset (see the method lists below).

Operation categoryAgainst a normal workroomAgainst the Global Workroom
List / get / query / search / retrieve (reads)✅ allowed✅ allowed
VectorDB create / update / delete / insert✅ allowed❌ 403 read-only
Ontology create / delete / add_knowledge / add_entity / delete_group✅ allowed❌ 403 read-only
Collection create / delete, chunk indexing / deletion✅ allowed❌ 403 read-only
Pipeline job create / cancel / retry / rerun / delete✅ allowed❌ 403 read-only
Raw file upload✅ allowed❌ 403 read-only
Workroom archive / restore / purge (lifecycle)✅ allowed❌ 403 read-only

Note on *_global helpers. query_vectors_global() is a read against the shared catalog and works for any caller. insert_vectors_global() targets the same shared catalog and is reserved for the platform's connector-runtime ingestion path — a direct tenant call will hit the same 403 read-only policy. To store your own vectors, create or use a normal (non-global) workroom.

If you are migrating tests or code that assumed the Global Workroom was writable: point the write at a workroom you own (pass its workroom_id), and only read from the Global Workroom.

VectorDB

Available Methods

  • list_vectordbs(*, workroom_id=None)
  • get_vectordb(vectordb_id, *, workroom_id=None)
  • create_vectordb(*, workroom_id=None, ...)
  • update_vectordb(vectordb_id, *, workroom_id=None, ...)
  • scale_vectordb(vectordb_id, *, workroom_id=None, ...)
  • delete_vectordb(vectordb_id, *, workroom_id=None)
  • query_vectors(vectordb_id, *, collection_name, vectors, limit=10, workroom_id=None)
  • query_vectors_global(*, vectordb_id, collection_name, vectors, limit=10) — read the shared catalog
  • insert_vectors(vectordb_id, *, collection_name, vectors, metadata, workroom_id=None)
  • insert_vectors_global(...) — connector-runtime catalog writes only (see note above)
# db_id, embedding, and my_workroom_id are values you supply.

# Read from the shared Global catalog (allowed)
hits = client.context.query_vectors_global(
vectordb_id=db_id,
collection_name="shared-docs",
vectors=[embedding],
limit=5,
)

# Write to a workroom you own (allowed) — NOT the Global Workroom
client.context.insert_vectors(
db_id,
collection_name="my-docs",
vectors=[embedding],
metadata=[{"source": "doc1"}],
workroom_id=my_workroom_id,
)

Ontology (Knowledge Graph)

Available Methods

  • list_ontologies(*, workroom_id=None) / get_ontology(...)
  • create_ontology(...) / delete_ontology(...)
  • add_knowledge(...) / add_entity(...) / delete_group(...)
  • search_knowledge(...) / get_memory(...) / get_episodes(...)
  • ontology_health(...)

Reads (list_*, get_*, search_knowledge, get_memory, get_episodes, ontology_health) work against any workroom including Global. Writes (create_ontology, delete_ontology, add_knowledge, add_entity, delete_group) are rejected on the Global Workroom.

Collections, Pipelines, and Retrieval

Available Methods

  • list_collections(...) / create_collection(...) / get_collection(...) / delete_collection(...)
  • create_pipeline_job(...) / list_pipeline_jobs(...) / get_pipeline_job(...)
  • get_supported_file_types()
  • search(...) / retrieve(...) / upload_file(...)

Pipeline cancel vs. delete

The SDK exposes two distinct teardown verbs for a pipeline job:

  • cancel_pipeline_job(...)graceful cancel (POST /context/pipelines/{job_id}/cancel). Stops the job but preserves its recorded history; the job stays fetchable via get_pipeline_job(...).
  • delete_pipeline_job(...)destructive delete (DELETE /context/pipelines/{job_id}). Cancels a pending/running job and then removes the job and its history.

Breaking change: cancel_pipeline_job(...) previously mapped to the destructive DELETE route. It now maps to the graceful cancel route, and the destructive behavior moved to the new delete_pipeline_job(...). Update any caller that relied on the old cancel_pipeline_job to hard-delete a job.

Provider-neutral source import and replay

For Kaizen / import-shell automation, the SDK wraps the provider-neutral source-import and replay surface:

  • get_import_options(...) / evaluate_import_options(...) — aggregate and validate import options for selected source descriptors.
  • create_source_import_job(...) — start a provider-neutral source-import job.
  • list_import_items(...) — workroom-wide source-import inventory/history.
  • rerun_import_items(...) — rerun selected inventory items by recorded source descriptor.
  • list_pipeline_job_items(...) — per-item statuses for one job.
  • retry_pipeline_job(...) — retry failed/incomplete items from a replayable import job.
  • rerun_pipeline_job(...) — rerun all recorded source descriptors from a prior import job.

Collection/pipeline/file writes follow the same rule: allowed in a normal workroom, 403 on the Global Workroom.

Raw-file Object Storage

The SDK wraps the workroom-scoped raw-file object-storage CRUD surface (/context/storage/raw). These methods are keyword-only and take an explicit workroom_id (sent as the X-Workroom-ID header); they return raw dict records rather than typed models.

Available Methods

  • store_raw_file(*, workroom_id, filename, content, ...) — store a raw file directly into workroom object storage (POST /context/storage/raw). content accepts bytes or a str (UTF-8 encoded) and is base64-encoded on the wire for you. Optional content_type, source_urn, source_kind, source_ref, and metadata are forwarded only when set.
  • list_raw_files(*, workroom_id, ...) — list stored raw files (GET /context/storage/raw), returning the {"items": [...], "count": N} shape. Supports source_urn / job_id / connector_id filters, limit / offset paging, and include_markings=True to attach aggregated security markings.
  • get_raw_file(file_id, *, workroom_id, ...) — fetch one raw-file record (GET /context/storage/raw/{file_id}). Set include_download_url=True for a temporary presigned download URL (when S3 metadata exists); expires_seconds (30–3600) overrides its TTL.
  • update_raw_file(file_id, *, workroom_id, content, if_match=None) — replace the plain-text body of an editable raw file (PUT /context/storage/raw/{file_id}). Pass the file's updated_at token from a prior response as if_match for optimistic concurrency; a stale token returns 409 with the current token in the error detail.
# my_workroom_id is a workroom you own.
stored = client.context.store_raw_file(
workroom_id=my_workroom_id,
filename="notes.txt",
content="hello raw storage",
content_type="text/plain",
)
file_id = stored["id"]

current = client.context.get_raw_file(file_id, workroom_id=my_workroom_id)
client.context.update_raw_file(
file_id,
workroom_id=my_workroom_id,
content="edited body",
if_match=current["updated_at"], # optimistic concurrency
)

OmniParse Instances

The SDK wraps the workroom-scoped OmniParse instance lifecycle CRUD surface (/context/omniparses). OmniParse instances are the document-parsing runtimes that ingest pipelines depend on; wrapping them lets callers provision and manage OmniParse from automation rather than relying only on implicit lazy provisioning. These methods are keyword-only, take an explicit workroom_id (sent as the X-Workroom-ID header), and return raw dict / list[dict] records rather than typed models.

Available Methods

  • list_omniparses(*, workroom_id) — list OmniParse instances for a workroom (GET /context/omniparses), returning a list of instance records.
  • get_omniparse(omniparse_id, *, workroom_id) — fetch one instance by id (GET /context/omniparses/{omniparse_id}).
  • create_omniparse(*, name, workroom_id, template_name="tool-omniparse", config=None) — provision an OmniParse runtime instance (POST /context/omniparses). template_name selects the App Garden tool template; config carries optional OmniParse environment configuration and is forwarded only when set.
  • update_omniparse(omniparse_id, *, workroom_id, config=None) — update an instance's environment configuration (PUT /context/omniparses/{omniparse_id}).
  • delete_omniparse(omniparse_id, *, workroom_id) — delete an instance (DELETE /context/omniparses/{omniparse_id}).
# my_workroom_id is a workroom you own.
instance = client.context.create_omniparse(
name="docs-parser",
workroom_id=my_workroom_id,
config={"replicas": 1},
)
instance_id = instance["id"]

client.context.update_omniparse(
instance_id,
workroom_id=my_workroom_id,
config={"replicas": 2},
)
client.context.delete_omniparse(instance_id, workroom_id=my_workroom_id)

Global Settings, Document Download, and Audio Readiness

These cover platform-wide Context configuration, presigned download of an original document, and an audio-ingest preflight probe.

Available Methods

  • get_global_settings() — read platform-wide Context global settings (GET /context/global-settings). Platform-scoped (ContextAdmin), not workroom-scoped — no X-Workroom-ID header is sent.
  • update_global_settings(*, omniparse=None, reason=None) — patch the global settings (PATCH /context/global-settings). omniparse is a partial settings dict (e.g. {"force_insecure_model_ssl": True}); reason is an optional audit annotation. Only the provided fields change. Also ContextAdmin-scoped.
  • get_document_download_url(source_urn, *, workroom_id) — get a presigned S3 download URL for an original document by source URN (GET /context/documents/{source_urn}). Returns download_url plus filename / content_hash / source_urn. Requires S3 document storage to be enabled server-side.
  • get_audio_readiness(*, workroom_id, mime_type=None, filename=None) — probe whether a workroom is ready to ingest audio (GET /context/audio-readiness). Optional mime_type (e.g. audio/aiff) and filename refine the check. Returns the readiness verdict (ready / code / message / remediation / details). This GET never side-effect-provisions an OmniParse instance.
# Platform-scoped admin config (no workroom).
settings = client.context.get_global_settings()
client.context.update_global_settings(
omniparse={"force_insecure_model_ssl": False},
reason="rotate certs",
)

# Workroom-scoped: preflight audio ingest, then resolve a stored document.
readiness = client.context.get_audio_readiness(
workroom_id=my_workroom_id,
mime_type="audio/aiff",
)
if readiness["ready"]:
download = client.context.get_document_download_url(
"urn:source:abc123",
workroom_id=my_workroom_id,
)
url = download["download_url"]

Error Handling

from kamiwaza_sdk.exceptions import KamiwazaError

# my_workroom_id is a workroom you own. The Global Workroom id is available as
# client.context.DEFAULT_WORKROOM_ID.
try:
client.context.create_ontology(
name="my-graph",
backend="graphiti",
workroom_id=client.context.DEFAULT_WORKROOM_ID, # Global → will 403
)
except KamiwazaError as exc:
if exc.status_code == 403 and "read-only" in str(exc):
# Expected: the Global Workroom is a shared, read-only catalog.
# Retry the write against a workroom you own instead.
client.context.create_ontology(
name="my-graph",
backend="graphiti",
workroom_id=my_workroom_id,
)
else:
raise

Best Practices

  1. Treat the Global Workroom as read-only: query/search it, but write your own resources into a workroom you own.
  2. Pass an explicit workroom_id on writes so a resource never accidentally resolves to the Global Workroom (an omitted workroom can resolve to Global on some paths and will be rejected).
  3. Branch on status_code == 403 + "read-only" to distinguish the shared-catalog policy from a genuine permission error.
  4. Use query_vectors_global() / read-only ontology queries to consume shared knowledge; never rely on writing to Global from tenant code.