Context Service | Kamiwaza Docs

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 category Against a normal workroom Against 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

# 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

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

Pipeline cancel vs. delete

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

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:

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

# 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

# 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

# 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.