Getting started
Install
pip install fg-agent-knowledge
The only runtime dependency is fg-agent-id; storage uses stdlib sqlite3.
Requires Python ≥ 3.11. The package is fully typed (py.typed ships in the wheel),
and everything runs locally — no network, no LLM, no async. The installed version is
exported as fg_agent_knowledge.__version__.
First knowledge base in five minutes
Two agents share a workspace: a scout proposes knowledge, an analyst reviews it.
The natural pattern is one KnowledgeBase handle per acting agent — default_author
is the identity that handle signs as, so the verbs need no keys argument at all:
from fg_agent_id import KeyPair
from fg_agent_knowledge import KnowledgeBase, Policy, Scope, SQLiteStore
# 1. One SQLite file, one handle per acting agent
store = SQLiteStore("team.db")
scout = KnowledgeBase(store, default_author=KeyPair.generate())
analyst = KnowledgeBase(store, default_author=KeyPair.generate())
# 2. A scope (a shared space), governed: claims need one approval
# from someone other than the proposer
scope = Scope(space="workspace-42")
scout.set_policy(scope, Policy(mode="review", required_approvals=1))
# 3. Capture an observation (cheap, unsigned, append-only)
ep = scout.observe(scope, kind="observation", content="deploy failed twice on cold cache")
# 4. Propose a claim distilled from it — the episode id is its pedigree
promo = scout.propose(
scope, kind="procedural",
statement="warm the cache before deploying the pricing service",
topics=("deploy", "pricing"), episodes=(ep.id,),
)
# 5. A different identity approves; the claim enters the scope
promo = analyst.review(promo.id, verdict="approve", basis="matches incident log")
assert promo.status == "accepted"
# 6. Ask for a briefing — ranked, attributed, model-free
briefing = analyst.brief(scope, task="deploy pricing service")
top = briefing.items[0]
print(top.claim.body.statement, top.confidence, top.verify_first)
Every verb also takes explicit keys as its second argument
(kb.propose(scope, keys, "procedural", ...)) — an explicit author always wins over the
handle's default_author, and governance guards (self-review, author-only retire) compare
identities at call time either way. So a single shared KnowledgeBase with explicit keys
per call works exactly as before 0.2.1.
What just happened
observerecorded raw experience. Episodes are fuel for later distillation — they are never returned by briefings directly.proposecreated a signed, content-addressed claim and opened a promotion under the scope's policy. Inreviewmode it waits for approvals.reviewwas performed by a different identity — the proposer can never approve their own promotion.briefassembled a ranked answer from accepted claims: relevance × confidence × freshness.verify_firstflags items that are stale or suspect.
Keys across sessions
Every verb signs as an identity, so an agent needs the same keypair from one session to
the next — KeyPair.generate() on every run creates a brand-new author each time.
fg-agent-id ships this as a one-liner: the keyfile is created on first run and loaded
back ever after, passphrase-sealed (scrypt + ChaCha20-Poly1305) when a passphrase is given:
from fg_agent_id import load_or_create_keys
scout_keys = load_or_create_keys("scout.key", passphrase="…from your secret manager…")
scout = KnowledgeBase(store, default_author=scout_keys)
# scout now signs as the same author in every session
Treat the keyfile like any private key: keep it out of version control and source the passphrase from your environment or a secret manager.