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:
| Field | Description |
|---|---|
name | Machine-readable identifier (e.g. is_headquartered_in) |
description | Human-readable explanation |
domain_kind | Expected subject type (e.g. company, person) |
range_kind | Expected object type (e.g. location, page_ref) |
transitive | Whether the relationship chains (A→B, B→C implies A→C — e.g. a transitive reports_to infers Alice→Carol from Alice→Bob→Carol) |
inverse_of | The reverse predicate, if one exists (e.g. manages ↔ reports_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.
| Method | Path | Description |
|---|---|---|
| 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.
| Method | Path | Description |
|---|---|---|
| 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.
| Method | Path | Description |
|---|---|---|
| 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.
| Method | Path | Description |
|---|---|---|
| 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.
| Method | Path | Description |
|---|---|---|
| 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").
| Method | Path | Description |
|---|---|---|
| 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.
| Method | Path | Description |
|---|---|---|
| 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.
| Method | Path | Description |
|---|---|---|
| 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.
| Method | Path | Description |
|---|---|---|
| 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.
| Method | Path | Description |
|---|---|---|
| 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.
| Method | Path | Description |
|---|---|---|
| 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.
| Method | Path | Description |
|---|---|---|
| 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
- Use specific predicates — prefer
is_headquartered_inover a genericrelated_to. - Include confidence scores — not all claims are equally certain.
- Link evidence — attach source URLs so claims can be verified.
- Use perspectives — separate human-asserted claims from automated ones.
- Retract, don't delete — retraction preserves the audit trail.