Use cases
Worked scenarios, end to end
Five concrete builds, each showing the whole loop: the scenario, the ingestion setup, the scoping setup, and the agent interaction. Every command matches a real Verity route or tool. Assume a running server (verity-cli dev), $VERITY, $TENANT, and $VERITY_ADMIN_TOKEN in the environment.
1 · A support agent that answers from live CRM + docs without leaking other customers
Scenario. A support agent for Acme should answer from Acme's live CRM state and the shared docs Acme is allowed to see — and must never surface another customer's data or Acme's restricted pricing.
Ingestion setup
# live CRM via CDC (mirrored) — one field update, queryable in ~31ms
curl -s -X POST "$VERITY/v1/ingest/debezium?tenant_id=$TENANT" \
-H "authorization: Bearer $VERITY_ADMIN_TOKEN" -H 'content-type: application/json' \
-d '{"payload":{"after":{"id":"opp-1","amount":84000,"stage":"negotiation"},
"source":{"connector":"postgresql","db":"crm","table":"opportunities","ts_ms":1752000000000},"op":"u"}}'
# a shared runbook, visible to the support group (token 12), tagged to Acme
HANDLE=$(curl -s -X POST "$VERITY/v1/scopes" \
-d '{"tenant_id":"'"$TENANT"'","principals":[12],"entity_scope":["account:acme"]}' | jq -r .scope_handle)
curl -s -X POST "$VERITY/v1/files" -F "scope_handle=$HANDLE" \
-F "entities=account:acme" -F "file=@acme-runbook.md"Scoping setup
The agent's session clamps pricing out with a purpose pack and binds to Acme only:
SUPPORT=$(curl -s -X POST "$VERITY/v1/scopes" -d '{
"tenant_id":"'"$TENANT"'","principals":[12],"entity_scope":["account:acme"],
"purpose":"support_conversation","actor_azp":"agent:support-bot"}' | jq -r .scope_handle)Agent interaction
# answers from live CRM + the runbook
curl -s -X POST "$VERITY/v1/recall" -d "{\"scope_handle\":\"$SUPPORT\",\"text\":\"what stage is the Acme deal in?\"}"
# restricted pricing is filtered out by the purpose clamp
curl -s -X POST "$VERITY/v1/recall" -d "{\"scope_handle\":\"$SUPPORT\",\"text\":\"exact renewal quote amount\"}" | jq length
# → 0
# another customer's data is simply not in scope — 0 results, never a refusal message
curl -s -X POST "$VERITY/v1/recall" -d "{\"scope_handle\":\"$SUPPORT\",\"text\":\"globex account details\"}" | jq length
# → 0support_conversation purpose lowers the confidentiality ceiling below restricted so pricing is filtered too. The model never receives the excluded data, so no prompt can coax it out.2 · Two agents sharing one account's memory with cross-agent activity awareness
Scenario. A sales-bot and a prep-bot both work Acme. They should share semantic memory and see each other's actions so neither repeats work — but the sharing must stay inside Acme.
Scoping setup
mint() { curl -s -X POST "$VERITY/v1/scopes" -d "$1" | jq -r .scope_handle; }
SALES=$(mint '{"tenant_id":"'"$TENANT"'","principals":[7,11],"entity_scope":["account:acme"],"actor_azp":"agent:sales-bot"}')
PREP=$(mint '{"tenant_id":"'"$TENANT"'","principals":[7,11],"entity_scope":["account:acme"],"actor_azp":"agent:prep-bot"}')Agent interaction
# sales-bot records an action AND a shared note
curl -s -X POST "$VERITY/v1/actions" -d "{\"scope_handle\":\"$SALES\",\"action_id\":\"q1\",
\"action_type\":\"quote.issued\",\"summary\":\"Issued renewal quote at \$84,000.\",
\"outcome\":\"succeeded\",\"occurred_at\":\"2026-07-10T17:41:02Z\"}"
curl -s -X POST "$VERITY/v1/episodes" -d "{\"scope_handle\":\"$SALES\",
\"observation\":\"Acme's renewal decision moves to their Q4 board meeting.\",\"entities\":[\"account:acme\"]}"
# prep-bot checks activity BEFORE acting (so it won't re-issue the quote)…
curl -s "$VERITY/v1/activity?scope_handle=$PREP&entity=account:acme&action_types=quote.*" \
| jq '.[] | {who:.actor_azp, what:.action_type}'
# → { "who":"agent:sales-bot", "what":"quote.issued" }
# …and recalls sales-bot's shared note
curl -s -X POST "$VERITY/v1/recall" -d "{\"scope_handle\":\"$PREP\",\"text\":\"when is Acme deciding on renewal?\",\"k\":1}" \
| jq -r '.[0].content'
# → "Acme's renewal decision moves to their Q4 board meeting."An MCP agent would use memory_activity before acting, memory_record_action after, and memory_poll_changes between turns to notice the other agent's writes with a cursor.
3 · A HubSpot + Google Drive knowledge base with ACL inheritance
Scenario. Connect a CRM and a document store so agents answer from both — with Drive's real file permissions inherited so a caller only sees the files they'd see in Drive.
Ingestion setup (BYOT, two connectors)
# Google Drive — service account (tier A, mirrored ACLs). ACL-before-content.
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
python -m verity_ingest.connectors.gdrive --once
# HubSpot — private-app token (tier C, no per-record ACL API → admin-assigned visibility)
export HUBSPOT_PRIVATE_APP_TOKEN=pat-na1-...
python -m verity_ingest.connectors.hubspot --once --visibility 12 # the "support" group tokenDrive documents arrive with mirrored provenance: each file's permissions.list is mapped to canonical principals (user:*, group:*), and nested groups are resolved through SpiceDB via the Admin SDK directory sync. HubSpot, having no ACL API, arrives with admin-assigned visibility from the --visibility policy.
Scoping setup & interaction
# resolve a real user to their principals (user + group closure) via ReBAC
ALICE=$(curl -s -X POST "$VERITY/v1/scopes" -d '{
"tenant_id":"'"$TENANT"'","subject":"user:alice@corp.example"}' | jq -r .scope_handle)
# alice sees exactly the Drive files her Drive permissions allow, plus HubSpot content
# her support-group token can read — a single recall spanning both sources
curl -s -X POST "$VERITY/v1/recall" -d "{\"scope_handle\":\"$ALICE\",\"text\":\"acme onboarding plan\"}" \
| jq '.[] | {source:.source, provenance:.acl_provenance}'
# → mixed hits: {"source":"gdrive","provenance":"mirrored"} … {"source":"hubspot","provenance":"admin-assigned"}4 · Org-wide learning via the knowledge layer without cross-customer leakage
Scenario. Sales agents keep hitting the same DPA objection with healthcare customers. You want that lesson available org-wide — without any single customer's specifics crossing scopes.
Agents propose (as hypotheses)
# each scoped agent proposes from its own single-customer view (n=1, unpublishable alone)
curl -s -X POST "$VERITY/v1/knowledge" -d "{\"scope_handle\":\"$ACME_SCOPE\",
\"statement\":\"Healthcare-segment customers require DPA redlines before security review; budget ~2 extra weeks.\",
\"categories\":[\"industry:healthcare\",\"objection:dpa\"],\"evidence\":[\"$EPISODE_ID\"]}"
# a similar proposal from a DIFFERENT customer's agent accrues support onto the same candidateThe de-identification gate screens each statement against the entity lexicon, quoted spans, and identifying values; anything naming a customer is rejected back to scoped memory. The consolidation worker clusters similar proposals across entities.
A human publishes past k-support
# review the queue (admin) — support must span ≥3 distinct entities and ≥2 writers
curl -s "$VERITY/v1/knowledge?tenant_id=$TENANT&status=candidate" \
-H "authorization: Bearer $VERITY_ADMIN_TOKEN" | jq '.items[] | {statement, support_tier, distinct_entities}'
# publish with broad visibility; k_min is clamped to ≥3 server-side
curl -s -X POST "$VERITY/v1/knowledge/$ID/publish" -H "authorization: Bearer $VERITY_ADMIN_TOKEN" \
-d '{"tenant_id":"'"$TENANT"'","visibility":[1],"k_min":3}'Any scoped agent now benefits — the §7g carve-out
# an agent scoped to a NEW healthcare customer retrieves the published lesson
# (entity-free, kind:knowledge) alongside its own account's tagged content — and nothing else
curl -s -X POST "$VERITY/v1/recall" -d "{\"scope_handle\":\"$NEWCO_SCOPE\",\"text\":\"what slows down healthcare security review?\"}"Between propose and publish, the item passes through an eligible status once support crosses k across distinct entities and writers — nothing an agent reads ever triggers a publish, and auto-publish is off by default. Agents that recall the published item see a bucketed support tier (emerging / established / extensive), never an exact customer count.
status: published. Erase a supporting episode and a recount runs; if support drops below k, the item auto-invalidates. Full treatment — the three roles, the four gates, the merge cascade with measured precision/recall, and the acceptability controls — on the knowledge layer page; the carve-out itself in Permissions.5 · A webhook from an internal system as a memory source in 60 seconds
Scenario. An internal deployment system should drop a note into shared memory whenever it ships — no connector, no OAuth.
Mint → POST → recall
# 1. mint a scoped URL (admin) — token shown once
URL=$(curl -s -X POST "$VERITY/v1/webhooks" -H "authorization: Bearer $VERITY_ADMIN_TOKEN" \
-d '{"tenant_id":"'"$TENANT"'","name":"deploys","visibility":[1]}' | jq -r .url)
# 2. the internal system POSTs its native note (from CI, a cron, anywhere)
curl -s -X POST "$VERITY$URL" -H 'content-type: application/json' \
-d '{"content":"Deployed api v2.4.1 to prod at 14:02 UTC; migration 0042 applied."}'
# → 200 { "episode_id":"...", "chunks_indexed":1, "facts_written":0 }
# 3. an agent recalls it seconds later
curl -s -X POST "$VERITY/v1/recall" -d "{\"scope_handle\":\"$ANY_ORG_HANDLE\",\"text\":\"latest prod deploy\",\"k\":1}" \
| jq -r '.[0].content'
# → "Deployed api v2.4.1 to prod at 14:02 UTC; migration 0042 applied."If the internal system sends a vendor-specific shape Verity doesn't recognize, the delivery returns 202 {"quarantined":true} and the raw payload waits in verity-cli tail for review — you then either adjust the sender to the native shape or bind a source manifest to map it. Either way, nothing ambiguous is ever indexed permissively.