Metadata-Version: 2.4
Name: kntgraph
Version: 0.11.0
Summary: Pure ECS agent framework: event-sourced via Redis Streams, semantic routing via GLiNER2, tool re-use via the Solution tier (ADR-010). Sub-package `agents` ships concrete LLM/cache/PII adapters over the framework.
License-Expression: Apache-2.0
Classifier: Operating System :: OS Independent
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Software Development
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Typing :: Typed
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: deal>=4.24
Requires-Dist: immutables>=0.21
Requires-Dist: pydantic>=2.13.4
Requires-Dist: pydantic-settings>=2.14.2
Requires-Dist: redis>=5.0
Requires-Dist: result>=0.17
Requires-Dist: structlog>=26.1.0
Requires-Dist: tenacity>=9.1.4
Provides-Extra: cli
Requires-Dist: typer>=0.26.8; extra == "cli"
Requires-Dist: rich>=15.0.0; extra == "cli"
Requires-Dist: jinja2>=3.1.6; extra == "cli"
Provides-Extra: falkordb
Requires-Dist: falkordb>=1.6.1; extra == "falkordb"
Provides-Extra: ollama
Requires-Dist: ollama>=0.6.2; extra == "ollama"
Provides-Extra: gliner
Requires-Dist: gliner2>=1.3.2; extra == "gliner"
Provides-Extra: api
Requires-Dist: fastapi>=0.139.0; extra == "api"
Requires-Dist: uvicorn[standard]>=0.51.0; extra == "api"
Provides-Extra: crypto
Requires-Dist: cryptography>=49.0.0; extra == "crypto"
Requires-Dist: canonicaljson>=2.0.0; extra == "crypto"
Provides-Extra: llm
Requires-Dist: litellm>=1.92.0; extra == "llm"
Provides-Extra: all-runtime
Requires-Dist: kntgraph[api,cli,crypto,falkordb,gliner,llm,ollama]; extra == "all-runtime"
Dynamic: license-file

<!--
SPDX-FileCopyrightText: 2026 kinetgraph

SPDX-License-Identifier: Apache-2.0
-->

# kntgraph

A pure, event-sourced agent framework over Redis Streams.

## Quality gates

The badges below mirror the nine gates in
[`scripts/ci.py`](scripts/ci.py) — the single source of
truth for the project's quality bar. Each badge is a
[Shields.io](https://shields.io/) static image; the
values are pinned in [`docs/quality.md`](docs/quality.md)
(auto-generated by `scripts/quality_report.py`).

<div align="center">

### Code quality

[![cc](https://img.shields.io/badge/CC-A%20%282.49%29-brightgreen?style=for-the-badge&logo=radar&logoColor=white)](https://radon.readthedocs.io/)
[![mi](https://img.shields.io/badge/MI-237_A_0_B_0_C-brightgreen?style=for-the-badge&logo=heartbeat&logoColor=white)](https://radon.readthedocs.io/)
[![pyright](https://img.shields.io/badge/pyright-0%20errors-brightgreen?style=for-the-badge&logo=microsoft&logoColor=white)](https://microsoft.github.io/pyright/)
![Version](https://img.shields.io/badge/version-0.10.1-blue)

### Tests

[![coverage](https://img.shields.io/badge/coverage-83.0%25-brightgreen?style=for-the-badge&logo=codecov&logoColor=white)](https://coverage.readthedocs.io/)
[![tests](https://img.shields.io/badge/tests-1902%20passed-brightgreen?style=for-the-badge&logo=pytest&logoColor=white)](https://docs.pytest.org/)

### Security

[![security](https://img.shields.io/badge/security-bandit-brightgreen?style=for-the-badge&logo=shield&logoColor=white)](https://bandit.readthedocs.io/)
[![audit](https://img.shields.io/badge/audit-pip--audit-blueviolet?style=for-the-badge&logo=dependabot&logoColor=white)](https://pypi.org/project/pip-audit/)

</div>

> The current value of each badge is generated locally by
> [`scripts/quality_report.py`](scripts/quality_report.py);
> the script reads each gate's output and updates
> [`docs/quality.md`](docs/quality.md) on 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`](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** — `World` is a deterministic
  function of events.
- **Event Sourcing** — Redis Streams is the single
  source of truth.
- **Idempotency** — replay produces the same
  World; `idempotency_key` on `Tool` makes
  at-least-once delivery into at-most-once
  side effects.
- **Dual lifecycle** — operational (framework) and
  domain (application) lifecycles are orthogonal;
  the same `World` carries both views.
- **Resilience** — circuit breaker, retry,
  bulkhead, timeout, fallback, and a Dead Letter
  Queue for failed events.
- **Durable checkpoints** — the
  `ReactiveDispatcher` commits 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 `agents` sub-module.

## Install

Currently, `kntgraph` is not published to PyPI. You can install it directly from GitHub:

```bash
uv add git+https://github.com/kinetgraph/kinetgraph.git
```

Optional extras (install only what you need):

```bash
uv add "kntgraph[cli]@git+https://github.com/kinetgraph/kinetgraph.git"      # CLI Boilerplate Generator (ADR-038)
uv add "kntgraph[falkordb]@git+https://github.com/kinetgraph/kinetgraph.git" # graph projection + Cypher
uv add "kntgraph[ollama]@git+https://github.com/kinetgraph/kinetgraph.git"   # local LLM / embeddings
uv add "kntgraph[gliner]@git+https://github.com/kinetgraph/kinetgraph.git"   # NER-based PII redaction
uv add "kntgraph[api]@git+https://github.com/kinetgraph/kinetgraph.git"      # HTTP gateway (FastAPI)
uv add "kntgraph[crypto]@git+https://github.com/kinetgraph/kinetgraph.git"   # Ed25519 event signing
uv add "kntgraph[llm]@git+https://github.com/kinetgraph/kinetgraph.git"      # LiteLLM adapter
uv add "kntgraph[all-runtime]@git+https://github.com/kinetgraph/kinetgraph.git" # everything above
```

## Hello world

```python
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:

```python
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

```bash
# 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:

```bash
# 1. Install Kinetgraph with the CLI extra globally or in your venv
uv pip install "kntgraph[cli]@git+https://github.com/kinetgraph/kinetgraph.git"

# 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](docs/cli_guide.md).

## 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 `FMH_` env-var prefix
and are loaded via Pydantic v2 `BaseSettings`. The
canonical schema is `Settings` in
`kntgraph.infra.config`. Highlights:

| Env var                       | Default                          |
| ----------------------------- | -------------------------------- |
| `FMH_REDIS_URL`               | `redis://localhost:6379`         |
| `FMH_FALKORDB_HOST`           | `localhost`                      |
| `FMH_FALKORDB_PORT`           | `16379`                          |
| `FMH_STREAM_MAXLEN`           | `100_000`                        |
| `FMH_TICK_INTERVAL`           | `1.0` (seconds)                  |
| `FMH_ENV`                     | `dev` (set to `prod` in deploy)  |

## Documentation

- [Getting Started](GETTING_STARTED.md) —
  mental model and your first agent.
- [Quick Start](docs/quickstart.md) — 5-minute
  install and "hello world".
- [Architecture](docs/architecture.md) — the
  three pillars (ECS, event sourcing,
  resilience) and how the pieces fit together.
- [Zero Token Architecture](docs/zta.md) —
  software handlers before LLM, read-side cache,
  hybrid dispatcher stack (ADR-049).
- [API Reference](REFERENCE.md) — the public
  API map, env-var table, and common patterns.
- [CLI Guide](docs/cli_guide.md) — walkthrough on scaffolding projects, contexts, systems, tools, and agents with the CLI.
- [docs/](docs/README.md) — full index of the
  docs.
- [ADRs](ADRs/) — Architecture Decision Records.

### ADRs Accepted in v0.8.0 / v0.9.0 (closed in this cycle)

| ADR | Título | Status |
| --- | ------ | ------ |
| [ADR-042](ADRs/ADR-042-Agents-Memory-Model-usage.md) | Memory Model Exposure in ECS Pattern (Systems vs. Tools) and CLI Support | Accepted (Implemented; CLI follow-up outstanding) |
| [ADR-043](ADRs/ADR-043-LiteLLM-Worker-Migration.md) | LiteLLM worker migration + ToolInvoker deprecation | Accepted (Implemented; surpassed removal target) |
| [ADR-044](ADRs/ADR-044-Tool-call-Overlay-Accumulation.md) | Tool-call Overlay Accumulation (slot persistence across ticks) | Accepted (Implemented) |
| [ADR-046](ADRs/ADR-046-CLI-Intent-Routing-Scaffold.md) | CLI Scaffold for Intent Routing Modes | Accepted (Implemented) |
| [ADR-047](ADRs/ADR-047-Tool-Adapter-Pattern.md) | Standardizing Tool Construction via Adapters | Draft (sync `ToolWorker` stable; §6 follow-ups open) |

### ADRs Proposed in discussion

| ADR | Título | Status |
| --- | ------ | ------ |
| [ADR-035](ADRs/ADR-035-sharding-and-dispatcher-coordination-for-horizontal-scaling.md) | Sharding and Dispatcher Coordination for Horizontal Scaling | Proposed (Under Review) |
| [ADR-040](ADRs/ADR-040-Messaging-Adapter-Intent-Ingestion.md) | Messaging Adapter for Intent Ingestion | Proposed (Under Discussion) |
| [ADR-048](ADRs/ADR-048-Visibility-Dashboard.md) | Observability Dashboard and Control Panel API | Proposed |
| [ADR-049](ADRs/ADR-049-Zero-Token-Architecture.md) | Zero Token Architecture support (RuleBasedChatSystem + SolutionLookupSystem) | Proposed (items 3 + 4 shipped in v0.10.0; Redis adapter shipped; FalkorDB adapter §6 still pending) |
| [ADR-050](ADRs/ADR-050-CLI-Command-Consistency.md) | CLI command consistency (sub-Typer, Typer Enum, template helper) | Accepted (v0.10.0) |
| [ADR-051](ADRs/ADR-051-Release-Versioning-via-Git-Tags.md) | Release versioning via git tags + `setuptools_scm` | Accepted (v0.10.0; PyPI publishing deferred to ADR-052) |
| [ADR-052](ADRs/ADR-052-PyPI-Publishing.md) | PyPI publishing via Trusted Publishing (PEP 740) | Proposed (workflow split: `release.yml` cuts the tag, `publish.yml` builds + uploads; 16 contract tests enforce the split) |

## Project status

- `0.10.0` — breaking: removes the `_legacy_principal`
  fallback in the API key verifier (ADR-017 §7.3).
  Plain-string bindings (pre-ADR-017) are now rejected
  as `AuthError(kind="malformed", ...)`. Operators with
  legacy bindings MUST run
  `scripts/migrate_principals.py --apply` before
  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 in `RedisAPIKeyVerifier` is the only path
  that distinguished JSON from legacy, and that path
  is now closed. Adds Zero Token Architecture support
  (ADR-049): `RuleBasedChatSystem` short-circuits
  `user.intent` events with deterministic replies and
  `SolutionLookupSystem` synthesises cached
  `tool.<name>.completed` events. The lookup system
  ships with two `SolutionStoreLike` adapters:
  `InMemorySolutionStore` (tests / `09b` example)
  and `RedisSolutionStore` (production; one Hash per
  tool with the canonical
  `knt:solution:<tool_name>` layout). Also fixes the
  dispatcher's drain contract so a synthetic
  completion queued by `run_pending_lookups`
  actually lands in the EventLog on the next tick.
  See [`docs/zta.md`](docs/zta.md),
  [`examples/09b_solution_lookup_zta.py`](examples/09b_solution_lookup_zta.py)
  (in-memory) and
   [`examples/09c_solution_lookup_zta_redis.py`](examples/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 by `setuptools_scm`
  (no more `pyproject.toml::version`); the new
  CI gates `check_version` and `bump_dry_run`
  catch drift before a release ships; the
  `CONTRIBUTING.md::Release checklist` is the
  6-step ritual for cutting a release. Retroactive
  tags for `v0.7.0`, `v0.8.0`, `v0.10.0` are
  pushed so `git log v0.8.0..v0.10.0` and
  `uv sync` work today. PyPI publishing is
  deferred to ADR-052.
- `0.9.0` — predecessor release. Drops the legacy
  `LiteLLMTool` / `ToolInvoker` / `kntgraph.agents.roles`
  paths (the canonical path is
  `LiteLLMToolWorker` + the `WorkerManager`, and the
  `role_systems` ECS-shaped counterparts). Adds the
  `HttpClientLike` Protocol and the `HttpxHttpClientAdapter`
  for HTTP-bound `ToolWorkers` (ADR-047). CLI tests
  ship a   `conftest.py` for the optional `[cli]` extra
  (DEBT §2.25). CC refactor of 10 functions over the
  CC=10 ceiling (DEBT §2.26); the `gate_complexity` in
  `scripts/ci.py` now 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 the
  `kntgraph` package name. Backwards-incompatible
  with the old `fmh_backend` / `fmh_agents`
  imports; the source is structurally the same
  (same modules, same tests).
- `0.6.x` — internal releases under the
  `fmh_*` package names (no longer distributed).

## License

Apache License 2.0. See [LICENSE](LICENSE).

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md) for
development setup, the gate that runs in CI, and
the pull request workflow. Bug reports and
security disclosures follow
[SECURITY.md](SECURITY.md).
















<!-- STATS START -->
<!-- This block is regenerated by scripts/readme_stats.py. Do not edit by hand. -->
## Project metrics

| Source modules | Test modules | ADRs | Docs |
| --- | --- | --- | --- |
| 243 (39,199 LOC) | 190 (42,076 LOC, 1,968 tests collected) | 51 | 24 pages |
<!-- STATS END -->
