Catalog PyPI
Back to packageRELEASE DETAILS

2.0.0

PyPI

agentflow-runtime

Real-time data platform serving context to AI agents

Published6 Jul 2026
Direct dependencies47
Transitive dependenciesNot calculated

README

Version 2.0.0 documentation

AgentFlow

Event-native metrics layer: business metrics that move when events happen — measured 1.1 s p50 event-to-metric freshness on production defaults. Live entity lookups, typed contracts, dual-language SDKs, and release-gated delivery for people, dashboards, services, and AI agents alike.

Release gate codecov Python License

Why this exists

BI on a replica answers yesterday's questions. Support, ops, and merch workflows need current orders, metrics, and health signals at the moment of decision — not a stale warehouse snapshot, not a pile of one-off service adapters, and not a cache that quietly serves 30-second-old numbers.

AgentFlow's axis is event → live metric: every metric declares which events move it (a contract-tested lineage graph), and the serving layer keeps reads fresh by invalidating its cache when events arrive — a measured behavior, not a slogan (docs/freshness-benchmark.md). One serving boundary on top of that axis:

  • streaming ingestion for operational events (validated, enriched, journaled)
  • a semantic layer that exposes entities, metrics, lineage, and query endpoints
  • typed, versioned contracts — each metric ships with its source events and a staleness budget
  • Python and TypeScript clients that speak the same API surface

Consumers are whoever needs the number now: humans, dashboards, downstream services, and AI agents — agents are one consumer, not the product.

Highlights

  • Measured event-to-metric freshness — an event entering the pipeline is reflected in GET /v1/metrics/* in 1.06 s p50 / 1.99 s p95 on production defaults (event-driven cache invalidation, no webhook registration), tunable to 238 ms p50; a plain TTL cache on the same pipeline sits at ~15 s. Reproducible via python scripts/benchmark_freshness.py → freshness benchmark
  • Lineage as a contract — all six metrics declare their source events, serving table, and a 2.5 s p95 staleness budget in versioned contracts, exposed through /v1/catalog and /v1/contracts and pinned by tests against the actual write path
  • Published release line through v1.6.0 on PyPI (agentflow-runtime, agentflow-client) and npm (@yuliaedomskikh/agentflow-client) via OIDC Trusted Publishers with SLSA provenance on every artifact
  • Tested and gated — 1,500+ unit tests plus a broad Windows no-Docker suite; CI enforces 13 required status checks (lint, schema, unit, integration, helm, perf, terraform, bandit, safety, npm-audit, trivy, contract, build-smoke) through branch protection
  • Dual SDK parity across Python and TypeScript — retries, circuit breakers, batching, pagination, contract pinning, idempotency keys, as_of historical reads — over sub-second entity lookups (p50 38–55 ms, p99 167 ms on local hardware)
  • Security in the hot path — tenant isolation on every read surface, parameterized queries, sqlglot AST validation for NL-to-SQL, fail-closed auth, secret scrubbing, and a Bandit gate for new findings
  • Production-shaped extras — two CDC paths (hardened Debezium/Kafka Connect + a ClickHouse per-branch fan-out), on-call runbooks, and a narrated demo of the DV2 multi-branch warehouse

Quick start

Upgrading from v1.0.x? See the v1.1 migration guide before installing.

Prerequisites:

  • Python 3.11+
  • make
  • Docker Compose (make demo starts Redis and the ClickHouse serving store)

PowerShell 7+:

git clone https://github.com/brownjuly2003-code/agentflow.git
cd agentflow
. .\scripts\setup.ps1
make demo

macOS / Linux:

git clone https://github.com/brownjuly2003-code/agentflow.git
cd agentflow
source ./scripts/setup.sh
make demo

make demo starts Redis and ClickHouse, seeds demo data through the full pipeline (validated events land in the ClickHouse serving store), and serves the API on http://localhost:8000. Swagger UI is available at http://localhost:8000/docs.

Try it:

curl http://localhost:8000/v1/entity/order/ORD-20260404-1001

curl -X POST http://localhost:8000/v1/query \
  -H "Content-Type: application/json" \
  -d '{"question":"Show me top 3 products"}'

Local demo runs without API-key enforcement unless you explicitly configure AGENTFLOW_API_KEYS_FILE.

Architecture

Event sources -> Kafka -> Flink -> Iceberg --------\
                                                    -> Semantic layer -> FastAPI -> Agent / SDK
Local demo   -> local_pipeline -> ClickHouse ------/
                       (DuckDB stays the local lake / test store)

Stack:

  • Ingestion: Kafka producers, Debezium/Kafka Connect CDC, and a local synthetic pipeline
  • Processing: Flink plus validation and enrichment stages
  • Storage: Iceberg for production-shaped tables; ClickHouse is the serving store (ADR 0006 — ReplacingMergeTree upserts, final=1 reads), DuckDB the local-dev / test store
  • Serving: FastAPI, contract registry, lineage, search, and operational endpoints
  • Orchestration: Dagster
  • IaC: Terraform, Helm, Docker Compose, and a Fly.io demo config

See docs/architecture.md for the detailed design, trade-offs, and deployment topologies.

CDC source capture is standardized on Debezium/Kafka Connect; downstream consumers use the canonical AgentFlow CDC contract defined in ADR 0005.

What's inside

AreaFiles
API coresrc/serving/api/
Semantic layersrc/serving/semantic_layer/
Python SDKsdk/agentflow/
TypeScript SDKsdk-ts/src/
Agent integrationsintegrations/agentflow_integrations/ (LangChain, LlamaIndex, CrewAI, MCP)
Flink jobssrc/processing/flink_jobs/
Test suitestests/
Design decisionsdocs/decisions/ (ADRs)
Public sitesite/
IaCinfrastructure/terraform/, infrastructure/dv2/, helm/, k8s/
DV2.0 warehousewarehouse/agentflow/dv2/ (hubs / links / satellites + real-dataset loader)

Documentation

Core

Deep dives

Development

# verified release slice
python -m pytest tests/unit tests/integration tests/sdk -q

# benchmark and regression gate
python scripts/run_benchmark.py
python scripts/check_performance.py --baseline docs/benchmark-baseline.json --current .artifacts/load/results.json --max-regress 20

# benchmark trend: [.github/perf-history.json](.github/perf-history.json) is appended on every main push;
# render the history locally with `make perf-plot` (writes docs/perf/history.html).

# contracts and security
python scripts/generate_contracts.py --check
bandit -r src sdk --ini .bandit --severity-level medium -f json -o .tmp/bandit-current.json
python scripts/bandit_diff.py .bandit-baseline.json .tmp/bandit-current.json

Status

v1.6.0 is the current release line — PyPI agentflow-runtime / agentflow-client and npm @yuliaedomskikh/agentflow-client, all published via OIDC Trusted Publishers with SLSA provenance attestations. CI on main is green across all 13 required checks.

The v1.1.0 → v1.6.0 arc landed in six increments on top of a security audit-closure sprint:

  • v1.1.0 — audit closure: tenant isolation across every read surface, SQL guard centralized on sqlglot, entity allowlist enforcement, fail-closed auth, secret rotation, Helm hardening, OpenAPI drift gate, and the required status checks.
  • v1.2.0 — DV2 multi-branch warehouse: 38 Data Vault 2.0 tables (8 hubs / 8 links / 22+ satellites), an Argo Workflows dv2-refresh template, a dbt project (3 mart models + 12 tests), and per-branch CDC fan-out via ClickHouse MaterializedPostgreSQL.
  • v1.3.0 — helm/kafka-connect hardening matched to helm/agentflow (NetworkPolicy + PDB + securityContext), live Helm validation across both charts, and the narrated DV2 demo (terminal + web-UI + dbt docs).
  • v1.4.0 — maintenance: on-call runbooks, SECURITY.md, issue/PR templates, contract/DORA CI hardening, repo hygiene, and a dependency wave (mypy, Terraform AWS provider, TypeScript, GitHub Actions, Vitest). No runtime API changes from v1.3.0.
  • v1.5.0 — security & correctness hardening: argon2id key hashing with an O(1) peppered lookup index (M-C4), an NL→SQL guard bypass fix (typed read_csv / read_parquet scan functions now denied in projection position), sqlglot control-byte and mutation-target repairs, and a strict-mypy expansion across the orchestration and freshness slices. No public API changes.
  • v1.6.0 — the architecture-fixing release: ClickHouse becomes the shipped serving engine (pipeline sink, ReplacingMergeTree row versions, backend-routed event scan, a dedicated CI E2E lane against a real ClickHouse), PII protection moves from the removed app-level string-parse gate to engine-enforced vault governance (fail-closed column grants, per-jurisdiction officer roles, row policies, SQL SECURITY DEFINER views — every live adversarial probe green), plus the vendored NL→SQL generation engine (LangGraph, routed through GraceKelly), the DV2 raw vault on PostgreSQL with LISTEN/NOTIFY freshness, the MinIO-backed PyIceberg catalog, and the OpenSSF Scorecard channel (5.8 → 7.0).

The tagged line and main are in sync as of v1.6.0. See the changelog for full detail.

Scope

This is a reference data-engineering project. The streaming, warehouse, and deployment artifacts (Flink, Iceberg, Helm, Terraform, k8s) are exercised against a local pipeline and a kind cluster in CI rather than a managed cloud. Wiring it to a live production source needs inputs that live outside the repo — CDC source onboarding (runbook ready in docs/operations/cdc-production-onboarding.md), a public benchmark on production-grade hardware, and an external pen-test attestation.

Screenshots

Admin UIAPI docs
AgentFlow admin UIAgentFlow API docs
Landing pageBenchmark run
AgentFlow landing pageAgentFlow benchmark terminal

Capture notes and publish-time checks are listed in docs/publication-checklist.md.

License

MIT. See LICENSE.

Credits

Built as a data-engineering reference project. Initial release cycle 2026-04-10 → 2026-04-20, with post-audit hardening and the DV2 extension landing through v1.4.0. Architecture decisions are recorded as ADRs in docs/decisions/.

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Declared dependencies 47

Native requirements
47 direct targetsNot calculated transitive count
Package / targetRequirementRelationship
argon2-cffi
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
argon2-cffi<26,>=23runtime
bcrypt
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
bcrypt<6,>=5runtime
confluent-kafka
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
confluent-kafka<3,>=2.5runtime
dagster
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
dagster<2,>=1.13.1runtime
duckdb
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
duckdb<2,>=1.1runtime
fastapi
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
fastapi<1,>=0.111runtime
httpx
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
httpx<1,>=0.27runtime
opentelemetry-exporter-otlp-proto-grpc
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
opentelemetry-exporter-otlp-proto-grpc<2,>=1.41runtime
opentelemetry-instrumentation-fastapi
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
opentelemetry-instrumentation-fastapi<1,>=0.62b0runtime
opentelemetry-instrumentation-httpx
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
opentelemetry-instrumentation-httpx<1,>=0.62b0runtime
opentelemetry-sdk
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
opentelemetry-sdk<2,>=1.41runtime
pandera
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
pandera<1,>=0.20runtime
prometheus-client
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
prometheus-client<1,>=0.21runtime
pyarrow
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
pyarrow<25,>=17runtime
pydantic-settings
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
pydantic-settings<3,>=2.5runtime
pydantic
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
pydantic<3,>=2.9runtime
pyyaml
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
pyyaml<7,>=6runtime
sqlglot
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
sqlglot<31,>=30runtime
structlog
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
structlog<27,>=24.4runtime
uvicorn
Environment
{
  "extras": "standard",
  "marker": null,
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
uvicorn[standard]<1,>=0.30runtime
boto3
Environment
{
  "extras": "",
  "marker": "extra == \"cloud\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
boto3<2,>=1.35; extra == "cloud"runtime
pyiceberg
Environment
{
  "extras": "pyiceberg-core",
  "marker": "extra == \"cloud\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
pyiceberg[pyiceberg-core]<1,>=0.7; extra == "cloud"runtime
schemathesis
Environment
{
  "extras": "",
  "marker": "extra == \"contract\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
schemathesis==4.21.10; extra == "contract"runtime
bandit
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
bandit<2,>=1.9; extra == "dev"runtime
build
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
build<2,>=1.2; extra == "dev"runtime
hatchling
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
hatchling<2,>=1.25; extra == "dev"runtime
hypothesis
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
hypothesis<7,>=6; extra == "dev"runtime
jsonschema
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
jsonschema<5,>=4; extra == "dev"runtime
mypy
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
mypy<3,>=1.11; extra == "dev"runtime
pandas
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
pandas<4,>=2.2; extra == "dev"runtime
pytest-asyncio
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
pytest-asyncio<2,>=0.24; extra == "dev"runtime
pytest-cov
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
pytest-cov<8,>=5; extra == "dev"runtime
pytest
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
pytest<10,>=8.3; extra == "dev"runtime
ruff
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
ruff<1,>=0.6; extra == "dev"runtime
testcontainers
Environment
{
  "extras": "kafka",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
testcontainers[kafka]<5,>=4.9; extra == "dev"runtime
types-pyyaml
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
types-pyyaml<7,>=6; extra == "dev"runtime
types-redis
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
types-redis<6,>=4.6; extra == "dev"runtime
apache-flink
Environment
{
  "extras": "",
  "marker": "extra == \"flink\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
apache-flink==2.3.0; extra == "flink"runtime
langchain-core
Environment
{
  "extras": "",
  "marker": "extra == \"integrations\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
langchain-core<2,>=1.2.22; extra == "integrations"runtime
langchain-text-splitters
Environment
{
  "extras": "",
  "marker": "extra == \"integrations\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
langchain-text-splitters<2,>=1.1.2; extra == "integrations"runtime
langchain
Environment
{
  "extras": "",
  "marker": "extra == \"integrations\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
langchain<2,>=0.3.30; extra == "integrations"runtime
langgraph
Environment
{
  "extras": "",
  "marker": "extra == \"integrations\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
langgraph<2,>=1; extra == "integrations"runtime
langsmith
Environment
{
  "extras": "",
  "marker": "extra == \"integrations\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
langsmith<1,>=0.7.31; extra == "integrations"runtime
llama-index-core
Environment
{
  "extras": "",
  "marker": "extra == \"integrations\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
llama-index-core<1,>=0.12; extra == "integrations"runtime
fakeredis
Environment
{
  "extras": "",
  "marker": "extra == \"load\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
fakeredis<3,>=2.21; extra == "load"runtime
locust
Environment
{
  "extras": "",
  "marker": "extra == \"load\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
locust<3,>=2.29; extra == "load"runtime
psycopg
Environment
{
  "extras": "binary",
  "marker": "extra == \"postgres\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
psycopg[binary]<4,>=3.2; extra == "postgres"runtime

Distribution files

2 collected
agentflow_runtime-2.0.0-py3-none-any.whl

bdist_wheel · 268.69 KB · Python py3

Source file
agentflow_runtime-2.0.0.tar.gz

sdist · 256.56 KB · Python source

Source file

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 21:55 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package_version:e789ef628d15136a6da45e3509b4cf84c0a07f021d781ce03a5b3004e916ea67

Other collected versions

View all collected versions →