Skip to content

kb: client for the external Knowledge Base API

gencli kb is a full CLI client for a separate service, the Knowledge Base ("kb"): a fact store where every fact records its evidence and the rule-engine decisions that admitted it.

As with example.ipynb, this notebook demonstrates gencli.kb_client's pure functions directly — no live network calls at doc-build time, since network I/O doesn't belong in a docs build. Each section notes the equivalent CLI command. A final, non-executed section walks through a real session against a local kb instance.

%load_ext autoreload
%autoreload 2

Building request payloads

Pure functions: given the same arguments, they always build the same JSON body — no network call, no side effect.

from gencli.kb_client import (
    build_evidence_create_payload,
    build_attribute_create_payload,
)

build_evidence_create_payload(
    "https://example.com/toy-dataset", "gs://kb-evidence/toy-seed.json"
)
build_attribute_create_payload("shoe_size", "number", cardinality="one")

Equivalent CLI commands:

gencli kb evidence create https://example.com/toy-dataset gs://kb-evidence/toy-seed.json
gencli kb attributes create shoe_size --value-type number --cardinality one

coerce_fact_value

The CLI always receives --value as a plain string; this pure function converts it into the JSON-native value the API's value_type expects.

from gencli.kb_client import coerce_fact_value

(
    coerce_fact_value("8", "number"),
    coerce_fact_value("true", "boolean"),
    coerce_fact_value('{"nested": 1}', "json"),
    coerce_fact_value("acme-corp", "entity"),
)

Equivalent CLI command:

gencli kb facts ingest alice shoe_size --value-type number --value 8 --evidence-id <id>

validate_evidence_selector

kb facts ingest accepts either an existing --evidence-id, or --evidence-url/--evidence-artifact-path to create evidence inline. This pure function enforces exactly one of those two forms — it raises ValueError for anything else, before any network call is made.

from gencli.kb_client import validate_evidence_selector

validate_evidence_selector("existing-evidence-id", None, None)  # ok
validate_evidence_selector(None, "https://x", "gs://y")  # ok

try:
    validate_evidence_selector("existing-evidence-id", "https://x", "gs://y")
except ValueError as exc:
    print("rejected:", exc)

try:
    validate_evidence_selector(None, None, None)
except ValueError as exc:
    print("rejected:", exc)

The two accepted CLI forms:

gencli kb facts ingest alice shoe_size --value-type number --value 8 \
    --evidence-id existing-evidence-id

gencli kb facts ingest alice shoe_size --value-type number --value 8 \
    --evidence-url https://x --evidence-artifact-path gs://y

Recognizing a blocked ingest

A POST /api/facts blocked by the validation rule engine returns 422 with a body shaped like {"detail": {"validation_tags": [...]}} — an object detail, unlike every other error ({"detail": "a string"}). is_validation_failure/extract_validation_tags recognize this exact shape.

from gencli.kb_client import is_validation_failure, extract_validation_tags

blocked_body = {
    "detail": {
        "validation_tags": [
            {
                "rule_name": "attribute_known",
                "severity": "blocking",
                "passed": False,
                "reason": 'attribute "not_a_real_attribute" is not registered',
            }
        ]
    }
}

print(is_validation_failure(422, blocked_body))
print(is_validation_failure(404, {"detail": "not found"}))
extract_validation_tags(blocked_body)

gencli kb facts ingest exits with code 2 (not the generic 1) on exactly this shape, with the failing tags printed as JSON on stderr:

gencli kb facts ingest alice not_a_real_attribute --value-type string \
    --value x --evidence-id <id>
echo $?  # 2

flatten_search_result

Search endpoints wrap each hit as {<resource>: {...}, "score": float}. This flattens one hit into a single row, for --table rendering.

from gencli.kb_client import flatten_search_result

hit = {"evidence": {"id": "e1", "url": "https://example.com"}, "score": 0.91}
flatten_search_result(hit, "evidence")

Equivalent CLI command:

gencli kb evidence search example.com --table

Talking to a real KB instance

Not executed here (this is a docs build, not a live environment) — a walkthrough against a local kb checkout with its dev auth disabled (make -C backend up migrate run, make -C backend seed):

# One-time config: point gencli at the local API, no auth needed locally.
gencli config set kb_base_url http://localhost:8000
gencli config set kb_auth_mode none

# Sanity check + read seeded demo data.
gencli kb me
gencli kb entities list
gencli kb facts for-entity alice --table

# Register a new attribute, then ingest a fact for it, creating evidence
# inline.
gencli kb attributes create shoe_size --value-type number
gencli kb facts ingest alice shoe_size --value-type number --value 8 \
    --evidence-url https://example.com/shoe-size-source \
    --evidence-artifact-path gs://kb-evidence/shoe-size.png

# Inspect the full validation/reconciliation audit trail for that fact.
gencli kb facts get <fact-id-from-the-ingest-response>

Against a deployed instance instead of localhost, set kb_auth_mode=service_account and kb_service_account_file (or kb_auth_mode=token with a token from gcloud auth print-identity-token --audiences=<api-base-url>) — see gencli/kb_client.py's build_headers_for_config and the project README.