docs / agent-knowledge / concepts

Concepts

The mental model behind agent-knowledge, in the order you'll meet it.

Claims — the unit of knowledge

A claim is a signed statement with pedigree. Its body is immutable — revision means a new claim that supersedes the old one. The claim id is content-addressed:

claim_id = sha256( signing_input("claim", body) )   # hex

Derived, never chosen. Two identical bodies are one claim, which makes duplicate proposals idempotent. Topics are lowercased, sorted, and deduped at construction. The author address is derived from the signing key, so a claim can never carry an author its signer doesn't control.

Claim kinds: semantic (what is true) · procedural (how to do things) · relational (how things relate).

Provenance and pedigree

Every claim carries:

Episode and supersedes references may not cross the space boundary (ScopeError).

Confidence ⊥ Staleness

Trust has two independent axes, both derived at read time from the endorsement record — never persisted as authoritative.

Confidence ∈ [0, 1] — "was this ever true." Reference formula:

confidence = (1 + c) / (2 + c + k·d)

where c = distinct corroborating identities, d = distinct contradicting identities, k = contradiction weight (default 2 — one contradiction outweighs one corroboration). No endorsements → prior of 0.5. Implementations may substitute the formula; the fields are the standard.

Staleness — whole seconds since the last corroborating encounter (asserted_at counts as the first). Corroboration resets it. Contradictions never touch staleness — they're about truth, not freshness.

Standing positions supersede, not accumulate: an identity's most recent endorsement is its position, and self-corroboration never stacks.

Ranking applies freshness damping: horizon / (horizon + staleness) — 1.0 when fresh, 0.5 at the horizon (default 7 days).

Provenance-linked invalidation ("the signature move")

kb.invalidate(scope, artifact_uri="file://pricing-model.md", changed_at=now)

records that an artifact changed. Any claim whose refs include that artifact — with a change newer than its last corroboration — becomes suspect. The flag flips the moment the artifact changes and clears on the next corroboration. Knowledge about things that changed announces itself instead of quietly rotting.

Contradiction attaches, never edits

A contradiction is a signed endorsement on the claim. It lowers confidence and stays visible in every briefing. Silent last-write-wins is forbidden by construction. When distinct contradictors reach the threshold (2), a ConflictEvent is surfaced for humans — the library never auto-resolves disputes.

Proposal-governed promotion

Knowledge enters a scope only by proposal, decided under the scope's Policy:

Mode Behavior
auto (default) Accepts immediately — unless a claim topic is in protected_topics, which queues it pending
review Pending until required_approvals distinct approving identities; any reject → rejected

Rules enforced in code, not convention:

All governance records are append-only and queryable: the audit trail is the data structure.

Retirement — the only exit

retire() is the only way a claim leaves briefings, and it is author-only. The record itself is never deleted. Cross-author disagreement must use contradiction (which keeps the claim visible) — unrestricted retirement would be a hidden-censorship primitive. Supersession is likewise author-only.

Assembled briefings

brief() is deterministic and model-free:

rank = relevance (refs-overlap boosted) × confidence × freshness damping

The retriever supplies relevance (reference implementation: Okapi BM25 over Porter-stemmed, stopword-filtered tokens); the core owns trust and assembly. verify_first fires on items that made the briefing while suspect or staler than the scope's horizon. An empty query ("list everything") ranks by trust alone. Default limit: 12 items.

The three seams

Everything above is the fixed normative core. Three things are deliberately pluggable:

  1. Store — persistence. Ships SQLiteStore (WAL) and InMemoryStore, tested for parity.
  2. Retriever — relevance. Ships KeywordRetriever (BM25); bring your own embeddings.
  3. SourceWeight — trust. A Callable[[address], float] mapping authors to weights. Absent it, every distinct identity is one equal vote. This is the injection point for reputation or stake-weighted Sybil resistance, which a wire standard cannot itself provide.

Fine print worth knowing

Signing domain

Records sign under the domain fg-agent-knowledge/v1 with per-record contexts (claim, endorsement, verdict, retirement):

signing_input = uint16be(len(tag)) || tag || canonical_json(body)

Same construction as agent-id but a distinct domain — a knowledge signature can never be replayed as an identity artifact. Canonical JSON forbids floats anywhere. Timestamps are RFC 3339 UTC with 3 fractional digits. Future timestamps beyond a 300s skew window (MAX_CLOCK_SKEW_SECONDS) are rejected on propose(asserted_at) and endorse(issued_at); the spec requires this for every signed record, and the reference implementation does not yet enforce it on observe/review/retire paths. Signed text fields are bounded at 65,536 bytes.