Local-first graph analytics for AI agent traces and event data
Project description
JourneyGraph
Local-first graph analytics for recurring paths, loops, failures, and outcomes across AI-agent traces and event data.
JourneyGraph does not collect traces. It analyzes the traces and event exports you already have. Core analysis runs locally, needs no account or API key, and sends no telemetry.
Tracing tools help inspect one execution. JourneyGraph answers population-level questions: Which paths recur across many executions? Where do agents retry, loop, fail, hand off, or drop off? Which exact paths are associated with outcomes, and how do latency, token use, or cost differ globally or across retained cohorts?
JourneyGraph 0.1 is an early alpha with a deliberately narrow, tested contract. It turns canonical JSONL, CSV, optional Parquet, or one supported OTLP/JSON request shape into a deterministic aggregate graph, machine-readable analysis, normalized events, static HTML, and standalone SVG.
Five-minute quickstart
Python 3.11 or later is required. From a fresh checkout, this single setup-and-demo command installs the standard-library runtime core and generates a complete synthetic report:
git clone https://github.com/GermanGerken/journeygraph.git
cd journeygraph
python3 -m venv .venv && . .venv/bin/activate && python -m pip install . && journeygraph demo --output-dir journeygraph-demo
Open journeygraph-demo/report.html in a browser. The command also writes:
journeygraph-demo/
├── analysis.json
├── demo-traces.jsonl
├── graph.svg
├── normalized.jsonl
└── report.html
The packaged demo is deterministic and entirely synthetic. Its current output contains 45 events across 9 traces, 13 aggregate nodes, 19 unique transitions, 2 retry categories, and 3 exact return-loop sequences. Outcomes are 5 successes, 2 failures, 1 handoff, and 1 drop-off.
Analyze your own export
Canonical JSON Lines contains one operation per line:
{"schema_version":"1.0","trace_id":"trace-1","step_id":"request","timestamp":"2026-07-21T08:00:00Z","operation_type":"request","component":"user_request","duration_ms":4,"status":"ok"}
{"schema_version":"1.0","trace_id":"trace-1","step_id":"answer","parent_step_id":"request","timestamp":"2026-07-21T08:00:00.125Z","operation_type":"outcome","component":"completed","duration_ms":1,"status":"ok","outcome":"success"}
Validate first, then produce all four analysis artifacts:
journeygraph validate traces.jsonl
journeygraph analyze traces.jsonl --output-dir journeygraph-report
A compact part of analysis.json looks like this for the packaged demo:
{
"schema_version": "1.0",
"totals": {
"events": 45,
"nodes": 13,
"traces": 9,
"transitions": 36,
"unique_transitions": 19
},
"outcomes": {
"counts": {
"dropoff": 1,
"failure": 2,
"handoff": 1,
"success": 5,
"unknown": 0
}
}
}
Use --cohort-key environment to compare retained operational cohorts. Use repeatable
--allow-metadata-key KEY options only for additional non-sensitive operational fields.
Sensitive-key rules remain permanent even when a key is requested explicitly.
What it computes
- Aggregate nodes for exact
(operation_type, component)categories and weighted directed transitions between adjacent steps. - Complete exact paths with stable SHA-256 identities and frequency/outcome summaries.
- Adjacent exact-category retries and non-adjacent return loops, reported separately.
- Reconciled success, failure, handoff, drop-off, and unknown outcomes.
- Failure points, drop-off points, entries, terminals, and successful versus non-successful path comparisons.
- Event-level duration, token, and supplied-cost summaries with explicit missing counts.
- Optional cohort summaries based on retained metadata.
- Structured data-quality and privacy warnings without echoing rejected values.
All ordering, IDs, aggregates, JSON, normalized JSONL, HTML, and SVG are deterministic for the
same accepted input and configuration. Parent links are diagnostics; normalized chronological
order is authoritative, with step_id as the equal-timestamp tie-breaker.
Supported inputs
| Input | Maturity | Boundary |
|---|---|---|
| JSON Lines | Stable canonical v1 | One journeygraph.event/v1 object per line. |
| CSV | Stable canonical v1 | Same scalar fields; metadata uses metadata.<key> columns. |
| Parquet | Optional canonical v1 | Same logical columns through journeygraph[parquet] and PyArrow. |
| OTLP/JSON | Experimental | Explicit --format otlp-json; one uncompressed OTLP/HTTP ExportTraceServiceRequest JSON body. |
The experimental importer verifies an official OTLP request shape and maps a documented subset of OpenTelemetry and OpenInference attributes. It is not a collector, live receiver, gRPC or protobuf-binary decoder, generic JSON importer, or claim of Langfuse/Phoenix/provider compatibility. Validate a representative sanitized export before relying on it. See the exact data schema and mappings.
Where it fits
For AI systems, a journey might be:
request -> router -> retrieval -> model -> tool -> validation -> outcome
The same canonical model also supports non-AI operational journeys such as service workflows, batch pipelines, product events, support escalation, approval processes, or test-run steps. JourneyGraph describes observed associations; it does not infer causes or judge quality.
The implementation keeps provider-specific decoding at the ingestion boundary:
local export -> reader -> validation/privacy normalization -> aggregate graph
-> deterministic analytics -> JSON + normalized JSONL + HTML + SVG
The analytical core uses only the Python standard library. Optional PyArrow is isolated to Parquet ingestion. See Architecture for dependency boundaries and stable identity rules.
Privacy and security boundary
JourneyGraph denies metadata by default except for a small operational allowlist. Keys matching the documented sensitive fragments—including prompt, message, document, credential, token, email, and common identifier names—are permanently excluded. Reports escape untrusted markup; HTML has no executable JavaScript or remote dependency, and SVG has no scripts or remote resources.
This is key-based filtering, not content inspection, anonymization, or a DLP system. An
arbitrary custom key or value can still identify someone even when its name does not match the
denylist. Retained IDs, timestamps, labels, allowed values, rare paths, and normalized.jsonl
may still be sensitive. Inspect artifacts before sharing them. Read the full Privacy and
Threat Model.
Quality and reproducibility
The repository has three test layers: pure unit tests, real-file integration tests, and black-box installed-CLI functional tests. The acceptance suite covers deterministic ordering, branches, retries, loops, outcomes, malformed data, duplicates, privacy leakage, hostile markup, Unicode, output safety, canonical formats, representative OTLP/JSON, and a real Parquet file when the optional dependency is installed.
The canonical local gate enforces Ruff formatting/linting, strict mypy, combined statement and branch coverage of at least 90%, an isolated wheel smoke test, documentation contracts, dependency auditing, Bandit, and secret scanning:
make setup
make verify
Mutation testing and the deterministic 2,000-trace benchmark are explicit additional checks:
make mutation
make benchmark
CI runs the same Make targets on Linux with Python 3.11, 3.12, 3.13, and 3.14. A separate native Windows job on Python 3.12 builds the distributions, installs the exact wheel in an isolated environment, and exercises CLI help, CRLF/Unicode validation, deterministic analysis, and the packaged demo. No remote CI result is claimed until that workflow actually runs. See Testing and Quality.
Current limitations and non-goals
- Batch, local, in-memory analysis only; no collection, streaming, server, hosted service, or graph database.
- Exact category and path grouping only; no fuzzy clustering, causal inference, prediction, anomaly truth, or LLM-as-a-judge.
- OTLP/JSON support is intentionally narrower than the complete protocol and semantic convention surface.
- Supplied token and cost values are summarized as-is; provider pricing is not recalculated.
- Whole multi-file publication is not transactional, although each artifact uses guarded sibling replacement.
- The installed package and CLI are tested natively on Windows with Python 3.12. Repository development commands still use the documented POSIX Makefile harness or WSL.
Roadmap
Near-term work should be driven by sanitized real-export evidence: harden canonical and OTLP adapters, improve large-input behavior, add explainable comparisons and filtering, and expand visual navigation without weakening static/local guarantees. Leakage-safe prefix prediction is a possible later experiment only after temporal evaluation and privacy safeguards exist; it is not part of 0.1.
Documentation
- CLI and Python API
- Data and Analysis Schemas
- Architecture
- Privacy and Threat Model
- Privacy-safe real-trace discovery
- Testing and Quality
- Product brief
- MVP execution plan
- Real-trace discovery execution plan
- PyPI Trusted Publishing preparation
- Release process
The experimental standards boundary is anchored to the OTLP specification, pinned OpenTelemetry protobuf v1.10.0, and OpenInference semantic conventions.
Contributing
Issues and small, evidence-backed changes are welcome. Significant changes to schema meaning, privacy, stable identities, format compatibility, or architecture need an approved ExecPlan. Please read CONTRIBUTING.md, the Code of Conduct, and the Security Policy before submitting material.
License
JourneyGraph is available under the Apache License 2.0.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file journeygraph-0.1.1.tar.gz.
File metadata
- Download URL: journeygraph-0.1.1.tar.gz
- Upload date:
- Size: 53.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
25729f54e87b1fd862cf362e20d0b8c693b30620367792f1bca99f7e37f8b899
|
|
| MD5 |
85819012e70fd7a9ab5077b825e0b29c
|
|
| BLAKE2b-256 |
f0760f276163b81caa0168083526376dc5674899aea5c6d31f4f5f423ad6ab78
|
Provenance
The following attestation bundles were made for journeygraph-0.1.1.tar.gz:
Publisher:
release.yml on GermanGerken/journeygraph
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
journeygraph-0.1.1.tar.gz -
Subject digest:
25729f54e87b1fd862cf362e20d0b8c693b30620367792f1bca99f7e37f8b899 - Sigstore transparency entry: 2218393559
- Sigstore integration time:
-
Permalink:
GermanGerken/journeygraph@948eccab276eac42ecb0cd1f3ce0600354eb4d02 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/GermanGerken
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@948eccab276eac42ecb0cd1f3ce0600354eb4d02 -
Trigger Event:
release
-
Statement type:
File details
Details for the file journeygraph-0.1.1-py3-none-any.whl.
File metadata
- Download URL: journeygraph-0.1.1-py3-none-any.whl
- Upload date:
- Size: 58.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
79835cb57084aeb785baff8c0e061239fcc4a984e385433d1e529c5df765df00
|
|
| MD5 |
2af6ea2e8cd86b1ee8c63056d27bfea3
|
|
| BLAKE2b-256 |
acf3390c8b94736b82cc266773521a18be875b213699b8a7fb3c7b21f355cc11
|
Provenance
The following attestation bundles were made for journeygraph-0.1.1-py3-none-any.whl:
Publisher:
release.yml on GermanGerken/journeygraph
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
journeygraph-0.1.1-py3-none-any.whl -
Subject digest:
79835cb57084aeb785baff8c0e061239fcc4a984e385433d1e529c5df765df00 - Sigstore transparency entry: 2218393588
- Sigstore integration time:
-
Permalink:
GermanGerken/journeygraph@948eccab276eac42ecb0cd1f3ce0600354eb4d02 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/GermanGerken
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@948eccab276eac42ecb0cd1f3ce0600354eb4d02 -
Trigger Event:
release
-
Statement type: