kaygee
Flat, SQLite-native knowledge graph for agent memory.
What it is
A knowledge graph stored in SQLite. Nodes have YAML frontmatter, link to each other with [[wikilinks]], and self-organize into typed tables. No schema upfront — it emerges from the data you write.
from kaygee import KnowledgeGraph
kg = KnowledgeGraph("brain.db")
kg.write("spreading-activation", """---
type: concept
description: How activation propagates through a network
tags: [cognition, search]
---
Follows [[agent-traversal]] paths and uses [[semantic-similarity]].""")
kg.write("turing", """---
type: person
role: researcher
born: 1912
---
Pioneered computation and [[agent-traversal]].""")
That's it. Types are tracked, links are resolved, backlinks work automatically.
Internally, all node data lives in a single _data table. A _type_fields table tracks which columns belong to which type. The nodes table is a thin index of name + type.
# Raw SQL is available when you need it
kg.query("SELECT name, description FROM _data WHERE name = ?", ("spreading-activation",))
Core operations
# Write and read
kg.write("name", "---\ntype: concept\n---\nBody text with [[links]].")
kg.cat("name") # full content (frontmatter + body)
kg.body("name") # body only
kg.frontmatter("name") # metadata dict
kg.read("name", depth=1) # this node + content of linked nodes
# Organize
kg.touch("name") # create if not exists
kg.rm("name") # delete
kg.mv("old", "new") # rename
kg.cp("src", "dst") # copy
# Search
kg.ls("concept") # nodes of type
kg.find(name="activ.*") # regex on names
kg.grep("pattern", content=True) # regex across content
kg.tags() # {tag: [node, ...]} mapping
# Graph
kg.wikilinks("name") # outgoing link targets
kg.backlinks("name") # who links here
kg.graph() # full adjacency dict
kg.schema() # {type: [fields]} across all types
# Raw SQL
kg.query("SELECT name FROM nodes WHERE type = ?", ("concept",))
Changelog
Every mutation is recorded in an append-only changelog (enabled by default). This drives delta sync and audit trails.
kg = KnowledgeGraph("brain.db") # changelog=True by default
kg.write("sa", "---\ntype: concept\n---\nSpreading activation.")
kg.rm("sa")
entries = kg.changelog(since_seq=0, limit=100)
# [(1, '2026-...', 'node.write', 'sa', '{"type": "concept", ...}'),
# (2, '2026-...', 'node.rm', 'sa', '{"type": "concept"}')]
kg.changelog_truncate(before_seq=2) # prune old entries
Operations logged: node.write, node.rm, node.mv, node.cp, node.type_change, type.add, type.rm.
Disable with KnowledgeGraph("brain.db", changelog=False) if you don't need it.
Sync
Push local changes to a remote MySQL database, scoped by team/user/project. Pull to replicate back.
from kaygee import sync_push, sync_pull
# Push changelog deltas to MySQL (only changed rows sent)
last_seq = sync_push(kg, mysql_conn, scope={"team_id": "eng"}, since_seq=0)
# Persist last_seq for next call
# Pull all rows matching scope from MySQL into local SQLite
count = sync_pull(kg, mysql_conn, scope={"team_id": "eng"})
- Push replays changelog entries — upserts and deletes flow through, including type changes and renames.
- Pull is a full pull filtered by scope. Writes bypass the changelog to avoid push-back loops.
- Falls back to full-table-scan push when changelog is disabled (deletes not propagated in this mode).
Constraints
Free-form by default. Add structure when you want it.
from kaygee import Validator, freeze_schema, requires_field, requires_link, no_orphans
v = Validator()
v.add(freeze_schema("concept", ["description", "tags"]))
v.add(requires_field("concept", "description"))
v.add(requires_link("paper", target_type="person"))
v.add(no_orphans())
v.check(kg) # raises ValidationError with all violations
kg.set_validator(v) # gatekeeper: blocks invalid writes before they persist
Shell
from kaygee import GraphShell
sh = GraphShell(kg)
sh.run("touch", ["neuron", "---\ntype: concept\n---\nA unit of [[computation]]."])
sh.run("ls", ["concept"])
sh.run("links", ["neuron"])
sh.execute("cat neuron | grep computation")
Visualization
from kaygee import visualize
visualize(kg, path="graph.html") # self-contained interactive HTML
Install
pip install kaygee
License
MIT
Metadata
Release files for kaygee 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| kaygee-0.1.1.tar.gz | 114.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| kaygee-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 148.8 kB
Release files / kaygee-0.1.1.tar.gz
| Download URL | kaygee-0.1.1.tar.gz |
|---|---|
| Size | 114.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1b88e3eff881eb6a5cfcfbfca95e6693677e37aad31148ab63bc5f768db1f727
|
|
BLAKE2b-256 checksum How to use checksums |
aa36d104a6ae3177fd85d176014db8f973477192b4646d88b65225cc93840ce1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.11
|
Release files / kaygee-0.1.1-py3-none-any.whl
| Download URL | kaygee-0.1.1-py3-none-any.whl |
|---|---|
| Size | 34.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5e0255eb73b4d72d54e6294be5d22c199b7cff2b2e3f6ba293eca977cf7980db
|
|
BLAKE2b-256 checksum How to use checksums |
19a570b11fbf13fcad2d0d91335537504ac611fc84ec5e0e94c3a15ffd205f98
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.11
|