kntgraph
A pure, event-sourced agent framework over Redis Streams.
Quality gates
The badges below mirror the nine gates in
scripts/ci.py — the single source of
truth for the project's quality bar. Each badge is a
Shields.io static image; the
values are pinned in docs/quality.md
(auto-generated by scripts/quality_report.py).
The current value of each badge is generated locally by
scripts/quality_report.py; the script reads each gate's output and updatesdocs/quality.mdon every CI run. Keep the snapshot in sync with this block when you remove badges or change the gate count.
A full breakdown of the current technical debt is in
DEBT.md. All pyright errors are resolved
(0 errors / 1043 warnings; the warning budget is
tracked separately under §4.2 and is out of scope for
the strict error budget).
kntgraph is the renamed and unified successor of
two internal packages (formerly fmh_backend and
fmh_agents). It provides the core abstractions
needed to build autonomous, replayable agents:
- Pure ECS —
Worldis a deterministic function of events. - Event Sourcing — Redis Streams is the single source of truth.
- Idempotency — replay produces the same
World;
idempotency_keyonToolmakes at-least-once delivery into at-most-once side effects. - Dual lifecycle — operational (framework) and
domain (application) lifecycles are orthogonal;
the same
Worldcarries both views. - Resilience — circuit breaker, retry, bulkhead, timeout, fallback, and a Dead Letter Queue for failed events.
- Durable checkpoints — the
ReactiveDispatchercommits a Redis checkpoint after the batch's emitted events are durably appended to the EventLog, so a crash between append and save replays the same events on restart (idempotency window). - Solution tier (ADR-010) — tool-call
re-use: when a tool call succeeds for a given
(problem, params)pair across multiple agents, the framework promotes the call into a reusable Solution node in FalkorDB, with per-tenant allow-list and man-in-the-loop review. - Semantic routing (ADR-013) — opt-in GLiNER2
intent classification and argument extraction
in the
agentssub-module.
Install
Install from PyPI:
uv add kntgraph
The version is the git tag (v0.11.0 → 0.11.0),
discoverable on PyPI:
pip show kntgraph
# Version: 0.11.0
# License: Apache-2.0
Optional extras (install only what you need):
uv add "kntgraph[cli]" # CLI Boilerplate Generator (ADR-038)
uv add "kntgraph[falkordb]" # graph projection + Cypher
uv add "kntgraph[ollama]" # local LLM / embeddings
uv add "kntgraph[gliner]" # NER-based PII redaction
uv add "kntgraph[api]" # HTTP gateway (FastAPI)
uv add "kntgraph[crypto]" # Ed25519 event signing
uv add "kntgraph[llm]" # LiteLLM adapter
uv add "kntgraph[all-runtime]" # everything above
To install the unreleased
main(between tagged releases), pin to the GitHub repo:uv add "kntgraph @ git+https://github.com/kinetgraph/kinetgraph.git". The tagged releases on PyPI are the canonical, supported install path.
Hello world
import asyncio
from kntgraph.core.event import Event
from kntgraph.core.world import World
async def main() -> None:
e1 = Event.create(
event_type="agent.spawned",
agent_id="a-1",
event_class="lifecycle",
)
e2 = Event.create(
event_type="document.received",
agent_id="a-1",
event_class="domain",
data={"doc_id": "NF-001"},
)
world = World.fold([e1, e2], tick=2)
print(world.agents["a-1"].operational_phase) # "spawned"
print(world.agents["a-1"].domain_phase) # "document.received"
asyncio.run(main())
The agents sub-module ships concrete LLM, cache,
and PII adapters on top of the framework:
from kntgraph.agents.tools import LiteLLMToolWorker
worker = LiteLLMToolWorker()
result = await worker.invoke(
system="You are a helpful assistant.",
user="What is the capital of France?",
idempotency_key="k1",
)
# ``result`` is a ``Result[dict, ToolError]``; the dict
# envelope carries ``text`` / ``model`` / ``usage`` /
# ``finish_reason`` / ``cost_usd`` / ``latency_ms``.
Run the tests
# Unit (fast, no Redis required)
uv run --package kntgraph pytest kntgraph/tests/unit/
# Integration (requires Redis on localhost:6379)
uv run --package kntgraph pytest kntgraph/tests/integration/
CLI Boilerplate Generator
Kinetgraph provides a first-party CLI (knt) to scaffold complete, ADR-compliant Modular Monoliths and Contexts.
Install the framework with the [cli] extra and initialize a new project:
# 1. Install Kinetgraph with the CLI extra globally or in your venv
uv add "kntgraph[cli]"
# 2. Scaffold a new application with the HTTP Gateway included
knt init project my_platform --use-intent-http
# or generate an intent-routing scaffold with an explicit mode
knt init project my_platform --routing-mode external
# supported values: external, autonomous, collaborate
# external: routes intents from outside the agent boundary
# autonomous: lets the agent resolve intents internally
# collaborate: coordinates multiple agents or roles for a shared intent
# 3. Enter the project and scaffold domain contexts
cd my_platform
knt new context weather
knt new system weather.WeatherRouter
knt new tool weather.OpenMeteoApi
For a comprehensive walkthrough on building an application from scratch using the CLI, refer to the CLI Guide.
Architecture
kntgraph/
├── src/kntgraph/
│ ├── core/ # Pure: ECS, Event, World, System
│ ├── stream/ # Redis Streams (EventLog, fold)
│ ├── runner/ # Side effects (Runner, ReactiveDispatcher)
│ ├── events/ # Dead Letter Queue
│ ├── resilience/ # Circuit breaker, retry, bulkhead, etc.
│ ├── infra/ # Config, Redis pool, hashing
│ ├── tools/ # Tool Protocol, registry, worker
│ ├── api/ # Optional HTTP gateway
│ ├── security/ # Ed25519 signing, principal, ACL
│ └── agents/ # LLM/cache/PII adapters, role_systems
│ ├── role_systems/ # ChatRoleSystem, PlannerRoleSystem, etc.
│ ├── tools/ # LiteLLMToolWorker, PiiRedactionTool
│ └── memory/ # Solution extractor/promoter
├── tests/
│ ├── unit/ # No external dependencies
│ ├── integration/ # Real Redis required
│ └── agents/ # agents sub-module tests
├── ADRs/ # Architecture Decision Records
├── docs/ # Public documentation
└── examples/ # Runnable end-to-end examples
Configuration
All settings live under the KNT_ env-var prefix
and are loaded via Pydantic v2 BaseSettings. The
canonical schema is Settings in
kntgraph.infra.config. Highlights:
| Env var | Default |
|---|---|
KNT_REDIS_URL |
redis://localhost:6379 |
KNT_FALKORDB_HOST |
localhost |
KNT_FALKORDB_PORT |
16379 |
KNT_STREAM_MAXLEN |
100_000 |
KNT_TICK_INTERVAL |
1.0 (seconds) |
KNT_ENV |
dev (set to prod in deploy) |
Documentation
- Getting Started — mental model and your first agent.
- Quick Start — 5-minute install and "hello world".
- Architecture — the three pillars (ECS, event sourcing, resilience) and how the pieces fit together.
- Zero Token Architecture — software handlers before LLM, read-side cache, hybrid dispatcher stack (ADR-049).
- API Reference — the public API map, env-var table, and common patterns.
- CLI Guide — walkthrough on scaffolding projects, contexts, systems, tools, and agents with the CLI.
- docs/ — full index of the docs.
- ADRs — Architecture Decision Records.
ADRs Accepted in v0.8.0 / v0.9.0 (closed in this cycle)
| ADR | Título | Status |
|---|---|---|
| ADR-042 | Memory Model Exposure in ECS Pattern (Systems vs. Tools) and CLI Support | Accepted (Implemented; CLI follow-up outstanding) |
| ADR-043 | LiteLLM worker migration + ToolInvoker deprecation | Accepted (Implemented; surpassed removal target) |
| ADR-044 | Tool-call Overlay Accumulation (slot persistence across ticks) | Accepted (Implemented) |
| ADR-046 | CLI Scaffold for Intent Routing Modes | Accepted (Implemented) |
| ADR-047 | Standardizing Tool Construction via Adapters | Draft (sync ToolWorker stable; §6 follow-ups open) |
ADRs Accepted in v0.10.0 / v0.11.0 (closed in this cycle)
| ADR | Título | Status |
|---|---|---|
| ADR-050 | CLI command consistency (sub-Typer, Typer Enum, template helper) | Accepted (v0.10.0) |
| ADR-051 | Release versioning via git tags + setuptools_scm |
Accepted (v0.10.0) |
| ADR-052 | PyPI publishing via Trusted Publishing (PEP 740) | Accepted (v0.11.0; first PyPI release cut via the two-workflow flow: release.yml then publish.yml) |
| ADR-053 | CLI Boilerplate Generation v2 (in-template rendering, knt upgrade workflow) |
Accepted (v0.11.0; 23-test render suite enforces the framework's symbol contracts; the knt upgrade check mode is the CI-quality drift detector) |
ADRs Proposed in discussion
| ADR | Título | Status |
|---|---|---|
| ADR-035 | Sharding and Dispatcher Coordination for Horizontal Scaling | Proposed (Under Review) |
| ADR-040 | Messaging Adapter for Intent Ingestion | Proposed (Under Discussion) |
| ADR-048 | Observability Dashboard and Control Panel API | Proposed |
| ADR-049 | Zero Token Architecture support (RuleBasedChatSystem + SolutionLookupSystem) | Proposed (items 3 + 4 shipped in v0.10.0; Redis adapter shipped; FalkorDB adapter §6 still pending) |
Design evaluations (decisions not to migrate). ADR-054 records the evaluation of executor and transport alternatives for the
WorkerManagerand confirms the current design:ProcessPoolExecutoras the function executor, Redis Streams as the per-tool queue. The realistic local alternatives (ThreadPoolExecutor, pureasyncio, external subprocess JSON-lines workers) are listed in ADR-054 §3.2 with the criteria that would justify a future revisit (ADR-054 §3.3).
Project status
0.11.0— first PyPI release. Shippingpip install kntgraphas the canonical install path (ADR-052). The release process is now two workflows:release.ymlcuts the git tag- opens the GitHub Release;
publish.ymlbuilds the wheel from the tag and uploads to PyPI via Trusted Publishing (PEP 740). ThepypiGitHub Environment is the human-in- the-loop gate. The publish workflow also enforces agit ls-remotepre-check (the tag must exist on the remote before the checkout can foolsetuptools_scminto a misleading0.0.0derivation) and agit configstep inrelease.ymlresolves theempty ident namefailure from the GitHub Actions runner.pyproject.tomlnow declares PEP 639license = "Apache-2.0"(theLicense :: OSI Approved :: Apache Software Licenseclassifier is rejected by setuptools ≥ 77 when thelicense =field is set) plus 11 canonical PyPI classifiers;[build-system] ::requiresis bumped tosetuptools>=77to make the PEP 639 floor explicit. 16 contract tests intests/scripts/test_workflow_split.pyenforce the split. The PyPI project page is live at https://pypi.org/project/kntgraph/ (licenseApache-2.0, version0.11.0). Operator runbook atdocs/pypi_publishing_runbook.md.
- opens the GitHub Release;
0.10.0— breaking: removes the_legacy_principalfallback in the API key verifier (ADR-017 §7.3). Plain-string bindings (pre-ADR-017) are now rejected asAuthError(kind="malformed", ...). Operators with legacy bindings MUST runscripts/migrate_principals.py --applybefore upgrading (the script is idempotent and safe to dry-run). The KNT_AUTH_MODE flag that ADR-017 §2.4 promised was never implemented; the wire-format detection inRedisAPIKeyVerifieris the only path that distinguished JSON from legacy, and that path is now closed. Adds Zero Token Architecture support (ADR-049):RuleBasedChatSystemshort-circuitsuser.intentevents with deterministic replies andSolutionLookupSystemsynthesises cachedtool.<name>.completedevents. The lookup system ships with twoSolutionStoreLikeadapters:InMemorySolutionStore(tests /09bexample) andRedisSolutionStore(production; one Hash per tool with the canonicalknt:solution:<tool_name>layout). Also fixes the dispatcher's drain contract so a synthetic completion queued byrun_pending_lookupsactually lands in the EventLog on the next tick. Seedocs/zta.md,examples/09b_solution_lookup_zta.py(in-memory) andexamples/09c_solution_lookup_zta_redis.py(Redis). Also adds release versioning via git tags (ADR-051): the project version is now derived from the git tag bysetuptools_scm(no morepyproject.toml::version); the new CI gatescheck_versionandbump_dry_runcatch drift before a release ships; theCONTRIBUTING.md::Release checklistis the 6-step ritual for cutting a release. Retroactive tags forv0.7.0,v0.8.0,v0.10.0are pushed sogit log v0.8.0..v0.10.0anduv syncwork today. PyPI publishing is deferred to ADR-052.0.9.0— predecessor release. Drops the legacyLiteLLMTool/ToolInvoker/kntgraph.agents.rolespaths (the canonical path isLiteLLMToolWorker+ theWorkerManager, and therole_systemsECS-shaped counterparts). Adds theHttpClientLikeProtocol and theHttpxHttpClientAdapterfor HTTP-boundToolWorkers(ADR-047). CLI tests ship aconftest.pyfor the optional[cli]extra (DEBT §2.25). CC refactor of 10 functions over the CC=10 ceiling (DEBT §2.26); thegate_complexityinscripts/ci.pynow flags new CC offenders that bypass the previous baseline-only check. Pyright errors down from 68 → 51 (17-error delta).0.7.0— public release under thekntgraphpackage name. Backwards-incompatible with the oldfmh_backend/fmh_agentsimports; the source is structurally the same (same modules, same tests).0.6.x— internal releases under thefmh_*package names (no longer distributed).
License
Apache License 2.0. See LICENSE.
Contributing
See CONTRIBUTING.md for development setup, the gate that runs in CI, and the pull request workflow. Bug reports and security disclosures follow SECURITY.md.
Project metrics
| Source modules | Test modules | ADRs | Docs |
|---|---|---|---|
| 248 (40,277 LOC) | 208 (47,990 LOC, 2,192 tests collected) | 54 | 25 pages |
Release files for kntgraph 0.13.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| kntgraph-0.13.0-py3-none-any.whl | Python 3 | none | any | Details |
Release files / kntgraph-0.13.0-py3-none-any.whl
| Download URL | kntgraph-0.13.0-py3-none-any.whl |
|---|---|
| Size | 549.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d5025808183fa9a698f8444ad09ae1e10b66fedb85c180a32d28656926453411
|
|
BLAKE2b-256 checksum How to use checksums |
b137294129a67136399bcddcebca2dd086e7cd95e156a5be6555b5f3726a7c01
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 21, 2026.
Transparency log