Knowledge API

A knowledge graph service for claims, predicates, perspectives, entity resolution, provenance tracking, and invariant monitoring. Build structured knowledge bases with multi-perspective conflict detection.

Concepts

A claim is a single typed assertion — subject predicate object: Acme Corp is_headquartered_in San Francisco; Widget API depends_on Auth Service. Claims carry metadata — who asserted them, when, a confidence score, and optional evidence links — and are retracted rather than deleted, preserving the audit trail. A predicate defines the kind of relationship a claim can express:

FieldDescription
nameMachine-readable identifier (e.g. is_headquartered_in)
descriptionHuman-readable explanation
domain_kindExpected subject type (e.g. company, person)
range_kindExpected object type (e.g. location, page_ref)
transitiveWhether the relationship chains (A→B, B→C implies A→C — e.g. a transitive reports_to infers Alice→Carol from Alice→Bob→Carol)
inverse_ofThe reverse predicate, if one exists (e.g. managesreports_to)

A perspective is a named viewpoint that groups related claims, so different members or automated systems can assert under their own perspective and disagreements become comparable instead of silent overwrites. Kapable ships seed predicates covering common relationships — person (affiliated_with, assigned_to, reports_to), organisation (is_headquartered_in, subsidiary_of, partner_of), technical (depends_on, deployed_to, implements), and content (authored_by, references, supersedes) — and you extend the ontology with custom predicates for your domain. Browse the full predicate ontology in the console's Knowledge page: a searchable table with domain-kind and seed-vs-custom filters.

Sources

Sources represent the origin of knowledge -- documents, APIs, human input, or agent observations. Every claim traces back to a source for provenance.

MethodPathDescription
GET /v1/knowledge/sources List sources (optional namespace filter)
POST /v1/knowledge/sources Create a source
DELETE /v1/knowledge/sources/{id} Soft-delete a source

SDK Examples

// Create a source
const source = await client.knowledge.createSource({
  namespace: 'product-docs',
  name: 'API Reference v2',
  kind: 'document',
  url: 'https://docs.example.com/api/v2',
});

// List sources by namespace
const sources = await client.knowledge.listSources('product-docs');
// Rust SDK
use kapable_sdk::knowledge::types::*;

let source = client.knowledge().create_source(CreateSourceRequest {
    namespace: Some("product-docs".into()),
    name: "API Reference v2".into(),
    kind: Some("document".into()),
    url: Some("https://docs.example.com/api/v2".into()),
    ..Default::default()
}).await?;

let sources = client.knowledge().list_sources(ListSourcesQuery {
    namespace: Some("product-docs".into()),
    ..Default::default()
}).await?;

Pages

Pages are named entities within a source. They provide the structure for organizing claims and edges in the knowledge graph.

MethodPathDescription
GET /v1/knowledge/pages List pages (canonical only)
POST /v1/knowledge/pages Create a page
POST /v1/knowledge/pages/merge Merge two pages (dedup)

SDK Examples

// Create a page
const page = await client.knowledge.createPage({
  source_id: source.id,
  title: 'Authentication',
  namespace: 'product-docs',
});

// Merge duplicate pages
await client.knowledge.mergePages({
  keep_id: canonicalPageId,
  merge_id: duplicatePageId,
});
// Rust SDK
let page = client.knowledge().create_page(CreatePageRequest {
    source_id: source.id,
    title: "Authentication".into(),
    namespace: Some("product-docs".into()),
    ..Default::default()
}).await?;

client.knowledge().merge_pages(MergePagesRequest {
    keep_id: canonical_page_id,
    merge_id: duplicate_page_id,
}).await?;

Claims

Claims are the core knowledge unit -- subject-predicate-object triples with confidence scores, perspectives, and provenance. Claims can be retracted, searched, and compared across perspectives.

MethodPathDescription
GET /v1/knowledge/claims List claims with optional filters
POST /v1/knowledge/claims Create a claim (supports dry_run query param)
GET /v1/knowledge/claims/{id} Get a single claim
POST /v1/knowledge/claims/{id}/retract Retract a claim
GET /v1/knowledge/claims/similar Search claims (lexical, vector, or hybrid)
GET /v1/knowledge/claims-by-perspective Compare claims by perspective for a (subject, predicate)

SDK Examples

// Create a claim
const claim = await client.knowledge.createClaim({
  subject: 'kapable-auth',
  predicate: 'supports',
  object: 'OAuth 2.0',
  confidence: 0.95,
  source_id: source.id,
  perspective_id: perspectiveId,
});

// Dry-run: check what would happen without persisting
const outcome = await client.knowledge.createClaim(
  { subject: 'kapable-auth', predicate: 'supports', object: 'SAML' },
  { dryRun: true },
);

// Search claims
const similar = await client.knowledge.searchClaims({
  query: 'authentication protocol',
  mode: 'hybrid',
  limit: 10,
});

// Compare perspectives
const views = await client.knowledge.listClaimsByPerspective({
  subject: 'kapable-auth',
  predicate: 'supports',
});

// Retract a claim
await client.knowledge.retractClaim(claim.id, {
  reason: 'Superseded by newer information',
});
// Rust SDK
let claim = client.knowledge().create_claim(
    CreateClaimRequest {
        subject: "kapable-auth".into(),
        predicate: "supports".into(),
        object: "OAuth 2.0".into(),
        confidence: Some(0.95),
        source_id: Some(source.id),
        perspective_id: Some(perspective_id),
        ..Default::default()
    },
    CreateClaimQuery { dry_run: None },
).await?;

let similar = client.knowledge().search_claims(SearchClaimsQuery {
    query: Some("authentication protocol".into()),
    mode: Some("hybrid".into()),
    limit: Some(10),
    ..Default::default()
}).await?;

let views = client.knowledge().list_claims_by_perspective(CompareByPerspectiveQuery {
    subject: "kapable-auth".into(),
    predicate: "supports".into(),
}).await?;

client.knowledge().retract_claim(claim_id, RetractClaimRequest {
    reason: "Superseded by newer information".into(),
}).await?;

Claim Confidence Evidence

Attach evidence records that justify a claim's confidence score. Each evidence record documents why the confidence was set to a particular value.

MethodPathDescription
GET /v1/knowledge/claims/{id}/confidence-evidence List confidence evidence for a claim
POST /v1/knowledge/claims/{id}/confidence-evidence Create confidence evidence for a claim
GET /v1/knowledge/claim_confidence_evidence List all confidence evidence (global)

Claim Meta and Derivations

Claim meta (reification) attaches metadata to claims. Derivations link claims that were derived from other claims.

MethodPathDescription
GET /v1/knowledge/claim_meta List claim meta records
POST /v1/knowledge/claim_meta Create claim meta
GET /v1/knowledge/claim_derivations List claim derivations
POST /v1/knowledge/claim_derivations Create claim derivation links

Edges

Edges connect pages in the knowledge graph (e.g. "references", "depends_on").

MethodPathDescription
GET /v1/knowledge/edges List edges with optional filters
POST /v1/knowledge/edges Create an edge between pages

SDK Examples

// Create an edge between pages
const edge = await client.knowledge.createEdge({
  source_page_id: authPageId,
  target_page_id: oauthPageId,
  predicate: 'depends_on',
});
// Rust SDK
let edge = client.knowledge().create_edge(CreateEdgeRequest {
    source_page_id: auth_page_id,
    target_page_id: oauth_page_id,
    predicate: "depends_on".into(),
    ..Default::default()
}).await?;

Predicates

Predicates define the vocabulary for claims and edges. The predicate ontology supports parent/child relationships and inverse predicates.

MethodPathDescription
GET /v1/knowledge/predicates List all predicates
GET /v1/knowledge/predicates/{name}/ontology Get predicate ontology (parents, children, inverse)

SDK Examples

// List all predicates
const predicates = await client.knowledge.listPredicates();

// Get ontology for a predicate
const ontology = await client.knowledge.predicateOntology('supports');
// { name: 'supports', inverse: 'supported_by', parents: [...], children: [...] }
// Rust SDK
let predicates = client.knowledge().list_predicates().await?;

let ontology = client.knowledge().predicate_ontology("supports").await?;
// ontology.name, ontology.inverse, ontology.parents, ontology.children

Canonical Entities

Entity resolution merges duplicate references into canonical entities. Auto-merge candidates are surfaced for review and decision.

MethodPathDescription
GET /v1/knowledge/canonical_entities List canonical entities
POST /v1/knowledge/canonical_entities/resolve Resolve (or create) a canonical entity
GET /v1/knowledge/canonical_entities/merge_candidates List merge candidates
POST /v1/knowledge/canonical_entities/merge_candidates/{id}/decide Decide a merge candidate
POST /v1/knowledge/canonical_entities/merge_candidates/{id}/unmerge Unmerge a previously merged candidate

SDK Examples

// Resolve an entity (find or create canonical)
const result = await client.knowledge.resolveCanonicalEntity({
  name: 'Kapable Auth Service',
  namespace: 'services',
});

// List merge candidates
const candidates = await client.knowledge.listMergeCandidates({
  status: 'pending',
});

// Accept a merge
await client.knowledge.decideMergeCandidate(candidateId, {
  decision: 'merged',
});

// Undo a merge
await client.knowledge.unmergeMergeCandidate(candidateId, {
  reason: 'False positive -- different services',
});
// Rust SDK
let result = client.knowledge().resolve_canonical_entity(ResolveCanonicalEntityRequest {
    name: "Kapable Auth Service".into(),
    namespace: Some("services".into()),
    ..Default::default()
}).await?;

let candidates = client.knowledge().list_merge_candidates(ListMergeCandidatesQuery {
    status: Some("pending".into()),
    ..Default::default()
}).await?;

client.knowledge().decide_merge_candidate(candidate_id, DecideMergeCandidateRequest {
    decision: "merged".into(),
    ..Default::default()
}).await?;

client.knowledge().unmerge_merge_candidate(candidate_id, UnmergeRequest {
    reason: Some("False positive -- different services".into()),
}).await?;

Perspectives

Perspectives represent viewpoints from which claims are made. Different agents, teams, or documents may hold different perspectives on the same subject-predicate pair.

MethodPathDescription
GET /v1/knowledge/perspectives List all perspectives
GET /v1/knowledge/perspectives/{id} Get a perspective by ID

Provenance

Track the provenance chain for sources -- where knowledge came from and how it was transformed.

MethodPathDescription
GET /v1/knowledge/source_provenance List source provenance records
GET /v1/knowledge/sources/{id}/provenance-graph BFS provenance graph for a source

SDK Examples

// Get the provenance graph for a source
const graph = await client.knowledge.sourceProvenanceGraph(sourceId, {
  depth: 3,
});
// graph.nodes, graph.edges -- ready for visualization
// Rust SDK
let graph = client.knowledge().source_provenance_graph(source_id, Some(3)).await?;
// graph.nodes, graph.edges

Invariants and Assay

The Knowledge service runs periodic invariant checks (assay runs) to detect data quality issues, contradictions, and anomalies.

MethodPathDescription
GET /v1/knowledge/invariants List invariant definitions
GET /v1/knowledge/assay_runs List assay run results

Tensions

Detect contradictions (tensions) between claims. Useful for surfacing conflicting information from different perspectives.

MethodPathDescription
GET /v1/knowledge/tensions Detect tensions (contradictions) between claims

SDK Examples

// Detect tensions
const tensions = await client.knowledge.detectTensions({
  namespace: 'product-docs',
});
for (const t of tensions.items) {
  console.log(`Tension: ${t.claim_a.subject} vs ${t.claim_b.subject}`);
  console.log(`  Predicate: ${t.predicate}`);
}
// Rust SDK
let tensions = client.knowledge().detect_tensions(TensionsQuery {
    namespace: Some("product-docs".into()),
    ..Default::default()
}).await?;
for t in &tensions.items {
    println!("Tension: {} vs {}", t.claim_a.subject, t.claim_b.subject);
}

Best practices