experience-graph 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. experience_graph-0.1.0/.github/workflows/ci.yml +41 -0
  2. experience_graph-0.1.0/.gitignore +22 -0
  3. experience_graph-0.1.0/.pre-commit-config.yaml +13 -0
  4. experience_graph-0.1.0/CLAUDE.md +110 -0
  5. experience_graph-0.1.0/LICENSE +21 -0
  6. experience_graph-0.1.0/Makefile +29 -0
  7. experience_graph-0.1.0/PKG-INFO +361 -0
  8. experience_graph-0.1.0/README.md +305 -0
  9. experience_graph-0.1.0/TODO.md +42 -0
  10. experience_graph-0.1.0/docs/agent-guide/README.md +21 -0
  11. experience_graph-0.1.0/docs/agent-guide/operations.md +858 -0
  12. experience_graph-0.1.0/docs/agent-guide/playbooks.md +586 -0
  13. experience_graph-0.1.0/docs/agent-guide/schemas.md +660 -0
  14. experience_graph-0.1.0/docs/agent-guide/trace-format.md +303 -0
  15. experience_graph-0.1.0/docs/design/architecture-design.md +92 -0
  16. experience_graph-0.1.0/docs/design/context-economy-strategy.md +71 -0
  17. experience_graph-0.1.0/docs/design/plan-context-economy.md +220 -0
  18. experience_graph-0.1.0/docs/design/plan-pluggable-architecture.md +303 -0
  19. experience_graph-0.1.0/integrations/__init__.py +1 -0
  20. experience_graph-0.1.0/integrations/langgraph/README.md +111 -0
  21. experience_graph-0.1.0/integrations/langgraph/__init__.py +1 -0
  22. experience_graph-0.1.0/integrations/langgraph/tools.py +180 -0
  23. experience_graph-0.1.0/integrations/obsidian/__init__.py +12 -0
  24. experience_graph-0.1.0/integrations/obsidian/indexer.py +179 -0
  25. experience_graph-0.1.0/integrations/obsidian/vault.py +215 -0
  26. experience_graph-0.1.0/integrations/openclaw/README.md +99 -0
  27. experience_graph-0.1.0/integrations/openclaw/SKILL.md +87 -0
  28. experience_graph-0.1.0/integrations/openclaw/openclaw.example.json +8 -0
  29. experience_graph-0.1.0/pyproject.toml +143 -0
  30. experience_graph-0.1.0/src/xpgraph/__init__.py +1 -0
  31. experience_graph-0.1.0/src/xpgraph/core/__init__.py +0 -0
  32. experience_graph-0.1.0/src/xpgraph/core/base.py +52 -0
  33. experience_graph-0.1.0/src/xpgraph/core/ids.py +23 -0
  34. experience_graph-0.1.0/src/xpgraph/errors.py +73 -0
  35. experience_graph-0.1.0/src/xpgraph/mcp/__init__.py +1 -0
  36. experience_graph-0.1.0/src/xpgraph/mcp/server.py +470 -0
  37. experience_graph-0.1.0/src/xpgraph/mcp_server.py +695 -0
  38. experience_graph-0.1.0/src/xpgraph/mutate/__init__.py +25 -0
  39. experience_graph-0.1.0/src/xpgraph/mutate/commands.py +155 -0
  40. experience_graph-0.1.0/src/xpgraph/mutate/executor.py +212 -0
  41. experience_graph-0.1.0/src/xpgraph/mutate/policy_gate.py +137 -0
  42. experience_graph-0.1.0/src/xpgraph/py.typed +0 -0
  43. experience_graph-0.1.0/src/xpgraph/retrieve/__init__.py +17 -0
  44. experience_graph-0.1.0/src/xpgraph/retrieve/effectiveness.py +150 -0
  45. experience_graph-0.1.0/src/xpgraph/retrieve/formatters.py +341 -0
  46. experience_graph-0.1.0/src/xpgraph/retrieve/pack_builder.py +158 -0
  47. experience_graph-0.1.0/src/xpgraph/retrieve/strategies.py +169 -0
  48. experience_graph-0.1.0/src/xpgraph/retrieve/token_tracker.py +59 -0
  49. experience_graph-0.1.0/src/xpgraph/retrieve/token_usage.py +145 -0
  50. experience_graph-0.1.0/src/xpgraph/schemas/__init__.py +56 -0
  51. experience_graph-0.1.0/src/xpgraph/schemas/entity.py +28 -0
  52. experience_graph-0.1.0/src/xpgraph/schemas/enums.py +72 -0
  53. experience_graph-0.1.0/src/xpgraph/schemas/evidence.py +39 -0
  54. experience_graph-0.1.0/src/xpgraph/schemas/graph.py +21 -0
  55. experience_graph-0.1.0/src/xpgraph/schemas/pack.py +53 -0
  56. experience_graph-0.1.0/src/xpgraph/schemas/policy.py +38 -0
  57. experience_graph-0.1.0/src/xpgraph/schemas/precedent.py +27 -0
  58. experience_graph-0.1.0/src/xpgraph/schemas/trace.py +83 -0
  59. experience_graph-0.1.0/src/xpgraph/stores/__init__.py +35 -0
  60. experience_graph-0.1.0/src/xpgraph/stores/base/__init__.py +19 -0
  61. experience_graph-0.1.0/src/xpgraph/stores/base/blob.py +41 -0
  62. experience_graph-0.1.0/src/xpgraph/stores/base/document.py +76 -0
  63. experience_graph-0.1.0/src/xpgraph/stores/base/event_log.py +130 -0
  64. experience_graph-0.1.0/src/xpgraph/stores/base/graph.py +170 -0
  65. experience_graph-0.1.0/src/xpgraph/stores/base/trace.py +44 -0
  66. experience_graph-0.1.0/src/xpgraph/stores/base/vector.py +56 -0
  67. experience_graph-0.1.0/src/xpgraph/stores/document.py +6 -0
  68. experience_graph-0.1.0/src/xpgraph/stores/event_log.py +6 -0
  69. experience_graph-0.1.0/src/xpgraph/stores/graph.py +6 -0
  70. experience_graph-0.1.0/src/xpgraph/stores/lancedb/__init__.py +5 -0
  71. experience_graph-0.1.0/src/xpgraph/stores/lancedb/store.py +236 -0
  72. experience_graph-0.1.0/src/xpgraph/stores/local/__init__.py +5 -0
  73. experience_graph-0.1.0/src/xpgraph/stores/local/blob.py +71 -0
  74. experience_graph-0.1.0/src/xpgraph/stores/pgvector/__init__.py +5 -0
  75. experience_graph-0.1.0/src/xpgraph/stores/pgvector/store.py +196 -0
  76. experience_graph-0.1.0/src/xpgraph/stores/postgres/__init__.py +13 -0
  77. experience_graph-0.1.0/src/xpgraph/stores/postgres/document.py +260 -0
  78. experience_graph-0.1.0/src/xpgraph/stores/postgres/event_log.py +208 -0
  79. experience_graph-0.1.0/src/xpgraph/stores/postgres/graph.py +650 -0
  80. experience_graph-0.1.0/src/xpgraph/stores/postgres/trace.py +203 -0
  81. experience_graph-0.1.0/src/xpgraph/stores/registry.py +249 -0
  82. experience_graph-0.1.0/src/xpgraph/stores/s3/__init__.py +5 -0
  83. experience_graph-0.1.0/src/xpgraph/stores/s3/blob.py +143 -0
  84. experience_graph-0.1.0/src/xpgraph/stores/sqlite/__init__.py +15 -0
  85. experience_graph-0.1.0/src/xpgraph/stores/sqlite/document.py +289 -0
  86. experience_graph-0.1.0/src/xpgraph/stores/sqlite/event_log.py +177 -0
  87. experience_graph-0.1.0/src/xpgraph/stores/sqlite/graph.py +700 -0
  88. experience_graph-0.1.0/src/xpgraph/stores/sqlite/trace.py +187 -0
  89. experience_graph-0.1.0/src/xpgraph/stores/sqlite/vector.py +174 -0
  90. experience_graph-0.1.0/src/xpgraph/stores/trace.py +6 -0
  91. experience_graph-0.1.0/src/xpgraph/stores/vector.py +6 -0
  92. experience_graph-0.1.0/src/xpgraph_api/__init__.py +1 -0
  93. experience_graph-0.1.0/src/xpgraph_api/app.py +65 -0
  94. experience_graph-0.1.0/src/xpgraph_api/deps.py +36 -0
  95. experience_graph-0.1.0/src/xpgraph_api/models.py +137 -0
  96. experience_graph-0.1.0/src/xpgraph_api/routes/__init__.py +1 -0
  97. experience_graph-0.1.0/src/xpgraph_api/routes/admin.py +46 -0
  98. experience_graph-0.1.0/src/xpgraph_api/routes/curate.py +143 -0
  99. experience_graph-0.1.0/src/xpgraph_api/routes/ingest.py +52 -0
  100. experience_graph-0.1.0/src/xpgraph_api/routes/retrieve.py +141 -0
  101. experience_graph-0.1.0/src/xpgraph_cli/__init__.py +1 -0
  102. experience_graph-0.1.0/src/xpgraph_cli/admin.py +179 -0
  103. experience_graph-0.1.0/src/xpgraph_cli/analyze.py +174 -0
  104. experience_graph-0.1.0/src/xpgraph_cli/config.py +47 -0
  105. experience_graph-0.1.0/src/xpgraph_cli/curate.py +206 -0
  106. experience_graph-0.1.0/src/xpgraph_cli/ingest.py +193 -0
  107. experience_graph-0.1.0/src/xpgraph_cli/main.py +32 -0
  108. experience_graph-0.1.0/src/xpgraph_cli/output.py +96 -0
  109. experience_graph-0.1.0/src/xpgraph_cli/retrieve.py +406 -0
  110. experience_graph-0.1.0/src/xpgraph_cli/stores.py +49 -0
  111. experience_graph-0.1.0/src/xpgraph_sdk/__init__.py +5 -0
  112. experience_graph-0.1.0/src/xpgraph_sdk/client.py +283 -0
  113. experience_graph-0.1.0/src/xpgraph_sdk/skills.py +153 -0
  114. experience_graph-0.1.0/src/xpgraph_workers/__init__.py +1 -0
  115. experience_graph-0.1.0/src/xpgraph_workers/engine/__init__.py +1 -0
  116. experience_graph-0.1.0/src/xpgraph_workers/engine/thinking.py +300 -0
  117. experience_graph-0.1.0/src/xpgraph_workers/enrichment/__init__.py +15 -0
  118. experience_graph-0.1.0/src/xpgraph_workers/enrichment/service.py +271 -0
  119. experience_graph-0.1.0/src/xpgraph_workers/ingestion/__init__.py +1 -0
  120. experience_graph-0.1.0/src/xpgraph_workers/ingestion/base.py +92 -0
  121. experience_graph-0.1.0/src/xpgraph_workers/ingestion/dbt.py +140 -0
  122. experience_graph-0.1.0/src/xpgraph_workers/ingestion/openlineage.py +152 -0
  123. experience_graph-0.1.0/src/xpgraph_workers/learning/__init__.py +1 -0
  124. experience_graph-0.1.0/src/xpgraph_workers/learning/miner.py +247 -0
  125. experience_graph-0.1.0/src/xpgraph_workers/maintenance/__init__.py +1 -0
  126. experience_graph-0.1.0/src/xpgraph_workers/maintenance/retention.py +184 -0
  127. experience_graph-0.1.0/tests/__init__.py +0 -0
  128. experience_graph-0.1.0/tests/integration/__init__.py +1 -0
  129. experience_graph-0.1.0/tests/integration/obsidian/__init__.py +1 -0
  130. experience_graph-0.1.0/tests/integration/obsidian/test_indexer.py +217 -0
  131. experience_graph-0.1.0/tests/integration/obsidian/test_vault.py +232 -0
  132. experience_graph-0.1.0/tests/unit/__init__.py +0 -0
  133. experience_graph-0.1.0/tests/unit/api/__init__.py +0 -0
  134. experience_graph-0.1.0/tests/unit/api/test_routes.py +167 -0
  135. experience_graph-0.1.0/tests/unit/cli/__init__.py +1 -0
  136. experience_graph-0.1.0/tests/unit/cli/conftest.py +20 -0
  137. experience_graph-0.1.0/tests/unit/cli/test_admin.py +94 -0
  138. experience_graph-0.1.0/tests/unit/cli/test_curate.py +118 -0
  139. experience_graph-0.1.0/tests/unit/cli/test_ingest.py +112 -0
  140. experience_graph-0.1.0/tests/unit/cli/test_retrieve.py +99 -0
  141. experience_graph-0.1.0/tests/unit/core/__init__.py +0 -0
  142. experience_graph-0.1.0/tests/unit/core/test_base.py +43 -0
  143. experience_graph-0.1.0/tests/unit/core/test_ids.py +36 -0
  144. experience_graph-0.1.0/tests/unit/mutate/__init__.py +0 -0
  145. experience_graph-0.1.0/tests/unit/mutate/test_commands.py +155 -0
  146. experience_graph-0.1.0/tests/unit/mutate/test_executor.py +202 -0
  147. experience_graph-0.1.0/tests/unit/mutate/test_policy_gate.py +177 -0
  148. experience_graph-0.1.0/tests/unit/retrieve/__init__.py +0 -0
  149. experience_graph-0.1.0/tests/unit/retrieve/test_effectiveness.py +150 -0
  150. experience_graph-0.1.0/tests/unit/retrieve/test_formatters.py +132 -0
  151. experience_graph-0.1.0/tests/unit/retrieve/test_pack_builder.py +133 -0
  152. experience_graph-0.1.0/tests/unit/retrieve/test_strategies.py +183 -0
  153. experience_graph-0.1.0/tests/unit/retrieve/test_token_tracker.py +257 -0
  154. experience_graph-0.1.0/tests/unit/schemas/__init__.py +0 -0
  155. experience_graph-0.1.0/tests/unit/schemas/test_entity.py +79 -0
  156. experience_graph-0.1.0/tests/unit/schemas/test_evidence.py +56 -0
  157. experience_graph-0.1.0/tests/unit/schemas/test_pack.py +55 -0
  158. experience_graph-0.1.0/tests/unit/schemas/test_policy.py +37 -0
  159. experience_graph-0.1.0/tests/unit/schemas/test_precedent.py +39 -0
  160. experience_graph-0.1.0/tests/unit/schemas/test_trace.py +151 -0
  161. experience_graph-0.1.0/tests/unit/sdk/__init__.py +0 -0
  162. experience_graph-0.1.0/tests/unit/sdk/test_client.py +92 -0
  163. experience_graph-0.1.0/tests/unit/sdk/test_skills.py +70 -0
  164. experience_graph-0.1.0/tests/unit/stores/__init__.py +0 -0
  165. experience_graph-0.1.0/tests/unit/stores/test_document_store.py +132 -0
  166. experience_graph-0.1.0/tests/unit/stores/test_event_log.py +104 -0
  167. experience_graph-0.1.0/tests/unit/stores/test_graph_store.py +133 -0
  168. experience_graph-0.1.0/tests/unit/stores/test_lancedb_store.py +122 -0
  169. experience_graph-0.1.0/tests/unit/stores/test_pgvector.py +112 -0
  170. experience_graph-0.1.0/tests/unit/stores/test_postgres_stores.py +354 -0
  171. experience_graph-0.1.0/tests/unit/stores/test_s3_blob.py +205 -0
  172. experience_graph-0.1.0/tests/unit/stores/test_temporal_graph.py +361 -0
  173. experience_graph-0.1.0/tests/unit/stores/test_trace_store.py +129 -0
  174. experience_graph-0.1.0/tests/unit/stores/test_vector_store.py +81 -0
  175. experience_graph-0.1.0/tests/unit/test_errors.py +44 -0
  176. experience_graph-0.1.0/tests/unit/workers/__init__.py +0 -0
  177. experience_graph-0.1.0/tests/unit/workers/engine/__init__.py +0 -0
  178. experience_graph-0.1.0/tests/unit/workers/engine/test_thinking.py +349 -0
  179. experience_graph-0.1.0/tests/unit/workers/enrichment/__init__.py +0 -0
  180. experience_graph-0.1.0/tests/unit/workers/enrichment/test_service.py +246 -0
  181. experience_graph-0.1.0/tests/unit/workers/learning/__init__.py +0 -0
  182. experience_graph-0.1.0/tests/unit/workers/learning/test_miner.py +390 -0
  183. experience_graph-0.1.0/tests/unit/workers/maintenance/__init__.py +0 -0
  184. experience_graph-0.1.0/tests/unit/workers/maintenance/test_retention.py +282 -0
  185. experience_graph-0.1.0/tests/unit/workers/test_ingestion.py +363 -0
@@ -0,0 +1,41 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ lint:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ - uses: actions/setup-python@v5
15
+ with:
16
+ python-version: "3.11"
17
+ - run: pip install ruff>=0.8
18
+ - run: ruff check src/ tests/
19
+
20
+ typecheck:
21
+ runs-on: ubuntu-latest
22
+ steps:
23
+ - uses: actions/checkout@v4
24
+ - uses: actions/setup-python@v5
25
+ with:
26
+ python-version: "3.11"
27
+ - run: pip install -e ".[dev]"
28
+ - run: mypy src/
29
+
30
+ test:
31
+ runs-on: ubuntu-latest
32
+ strategy:
33
+ matrix:
34
+ python-version: ["3.11", "3.12", "3.13"]
35
+ steps:
36
+ - uses: actions/checkout@v4
37
+ - uses: actions/setup-python@v5
38
+ with:
39
+ python-version: ${{ matrix.python-version }}
40
+ - run: pip install -e ".[dev]"
41
+ - run: pytest tests/ -v
@@ -0,0 +1,22 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ dist/
6
+ build/
7
+
8
+ # Virtual environments
9
+ .venv/
10
+ venv/
11
+
12
+ # Tools
13
+ .mypy_cache/
14
+ .ruff_cache/
15
+ .pytest_cache/
16
+
17
+ # Data
18
+ data/
19
+ *.db
20
+
21
+ # Environment
22
+ .env
@@ -0,0 +1,13 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.8.6
4
+ hooks:
5
+ - id: ruff-format
6
+ - id: ruff
7
+ args: [--fix]
8
+
9
+ - repo: https://github.com/pre-commit/pre-commit-hooks
10
+ rev: v5.0.0
11
+ hooks:
12
+ - id: trailing-whitespace
13
+ - id: check-yaml
@@ -0,0 +1,110 @@
1
+ # Experience Graph
2
+
3
+ A structured experience store for AI agents. Agents record traces of their work, build a shared knowledge graph of entities and evidence, and retrieve context packs before starting new tasks. The system provides governed mutations, immutable audit logging, and policy-based access control.
4
+
5
+ ## Agent Guide
6
+
7
+ Operational reference for interacting with the experience graph lives in `docs/agent-guide/`:
8
+
9
+ | Document | What It Covers |
10
+ |----------|----------------|
11
+ | [trace-format.md](docs/agent-guide/trace-format.md) | Constructing and ingesting valid trace JSON |
12
+ | [schemas.md](docs/agent-guide/schemas.md) | All Pydantic schemas with fields, types, and examples |
13
+ | [operations.md](docs/agent-guide/operations.md) | Full CLI, REST API, MCP, and Python mutation API reference |
14
+ | [playbooks.md](docs/agent-guide/playbooks.md) | Step-by-step procedures for common tasks |
15
+
16
+ ## Hard Rules
17
+
18
+ - **Traces are immutable.** Once ingested, a trace cannot be modified or deleted through normal operations.
19
+ - **All mutations go through the governed pipeline.** Validate, policy check, idempotency check, execute, emit event. No direct store writes.
20
+ - **Use `--format json` for machine output.** All CLI commands support it. Parse JSON output, not human-readable text.
21
+ - **Extra fields are forbidden.** All schemas use `extra="forbid"`. Unrecognized fields cause validation errors.
22
+ - **Use `structlog` for logging.** Never use `print()` in library code.
23
+ - **Type hints on all public APIs.**
24
+
25
+ ## Development Commands
26
+
27
+ ```bash
28
+ # Setup
29
+ uv pip install -e ".[dev]"
30
+ xpg admin init
31
+
32
+ # Quality
33
+ make lint # ruff check src/ tests/
34
+ make format # ruff format + fix
35
+ make typecheck # mypy src/
36
+ make test # pytest tests/ -v
37
+
38
+ # CLI
39
+ xpg admin health
40
+ xpg admin stats
41
+ xpg admin serve --port 8420
42
+ xpg ingest trace <file>
43
+ xpg ingest dbt-manifest <manifest>
44
+ xpg ingest openlineage <events>
45
+ xpg retrieve search "<query>"
46
+ xpg curate promote <trace_id> --title "..." --description "..."
47
+ xpg analyze context-effectiveness
48
+ xpg analyze token-usage
49
+ ```
50
+
51
+ ## Key Files
52
+
53
+ | Path | Purpose |
54
+ |------|---------|
55
+ | `src/xpgraph/schemas/` | All Pydantic data models |
56
+ | `src/xpgraph/mutate/commands.py` | Operation enum, Command/CommandResult schemas |
57
+ | `src/xpgraph/mutate/executor.py` | Governed mutation pipeline |
58
+ | `src/xpgraph/retrieve/pack_builder.py` | Context pack assembly with telemetry |
59
+ | `src/xpgraph/retrieve/strategies.py` | Search strategies (keyword, semantic, graph) |
60
+ | `src/xpgraph/retrieve/formatters.py` | Token-budgeted markdown formatters |
61
+ | `src/xpgraph/retrieve/effectiveness.py` | Context effectiveness analysis |
62
+ | `src/xpgraph/retrieve/token_tracker.py` | Token usage tracking |
63
+ | `src/xpgraph/retrieve/token_usage.py` | Token usage analysis and reporting |
64
+ | `src/xpgraph/stores/base/` | Store ABCs (TraceStore, DocumentStore, GraphStore, VectorStore, EventLog, BlobStore) |
65
+ | `src/xpgraph/stores/registry.py` | StoreRegistry — DI container with config-driven backend selection |
66
+ | `src/xpgraph/stores/sqlite/` | SQLite store implementations (default) |
67
+ | `src/xpgraph/stores/postgres/` | Postgres store implementations (cloud) |
68
+ | `src/xpgraph/stores/lancedb/` | LanceDB vector store (serverless ANN) |
69
+ | `src/xpgraph/stores/pgvector/` | pgvector store (cloud vectors) |
70
+ | `src/xpgraph/stores/s3/` | S3 blob store (cloud files) |
71
+ | `src/xpgraph/stores/local/` | Local filesystem blob store |
72
+ | `src/xpgraph/mcp/server.py` | MCP Macro Tools server (8 tools, markdown responses) |
73
+ | `src/xpgraph_cli/` | CLI commands (ingest, curate, retrieve, analyze, admin) |
74
+ | `src/xpgraph_api/` | REST API (FastAPI routes, models) |
75
+ | `src/xpgraph_sdk/` | Python SDK (XPGClient, skill functions) |
76
+ | `src/xpgraph_workers/` | Workers (enrichment, learning, ingestion, maintenance) |
77
+ | `integrations/obsidian/` | Obsidian vault indexer |
78
+
79
+ ## Packages
80
+
81
+ | Package | Purpose |
82
+ |---------|---------|
83
+ | `xpgraph` | Core library — schemas, pluggable stores, mutation executor, retrieval, formatters |
84
+ | `xpgraph_cli` | CLI (`xpg`) — ingest, curate, retrieve, analyze, admin |
85
+ | `xpgraph_api` | REST API (`xpg-api`) — FastAPI with OpenAPI auto-generation |
86
+ | `xpgraph_sdk` | Python SDK — XPGClient (local/remote), skill functions |
87
+ | `xpgraph_workers` | Workers — enrichment, learning, ingestion (dbt, OpenLineage), maintenance |
88
+
89
+ ## Store Backends
90
+
91
+ Backends are configured via `~/.xpg/config.yaml` or environment variables:
92
+
93
+ | Store | Default | Local ANN | Cloud | Env Var |
94
+ |-------|---------|-----------|-------|---------|
95
+ | Trace | `sqlite` | | `postgres` | `XPG_PG_DSN` |
96
+ | Document | `sqlite` | | `postgres` | `XPG_PG_DSN` |
97
+ | Graph | `sqlite` | | `postgres` | `XPG_PG_DSN` |
98
+ | Vector | `sqlite` | `lancedb` | `pgvector` | `XPG_PG_DSN` |
99
+ | Event Log | `sqlite` | | `postgres` | `XPG_PG_DSN` |
100
+ | Blob | `local` | | `s3` | `XPG_S3_BUCKET` |
101
+
102
+ Graph stores support temporal versioning (SCD Type 2) with `as_of` parameter for time-travel queries.
103
+
104
+ ## Entry Points
105
+
106
+ | Command | Target |
107
+ |---------|--------|
108
+ | `xpg` | `xpgraph_cli.main:app` |
109
+ | `xpg-mcp` | `xpgraph.mcp.server:main` |
110
+ | `xpg-api` | `xpgraph_api.app:main` |
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nathan Ronsse
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,29 @@
1
+ .DEFAULT_GOAL := help
2
+
3
+ .PHONY: help install install-dev lint format typecheck test clean
4
+
5
+ help: ## Show this help message
6
+ @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-15s\033[0m %s\n", $$1, $$2}'
7
+
8
+ install: ## Install package
9
+ uv pip install -e .
10
+
11
+ install-dev: ## Install package with dev dependencies
12
+ uv pip install -e ".[dev]"
13
+
14
+ lint: ## Run linting
15
+ ruff check src/ tests/
16
+
17
+ format: ## Format code
18
+ ruff format src/ tests/
19
+ ruff check --fix src/ tests/
20
+
21
+ typecheck: ## Run type checking
22
+ mypy src/
23
+
24
+ test: ## Run tests
25
+ pytest tests/ -v
26
+
27
+ clean: ## Clean build artifacts
28
+ rm -rf dist/ build/ *.egg-info .mypy_cache .ruff_cache .pytest_cache
29
+ find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
@@ -0,0 +1,361 @@
1
+ Metadata-Version: 2.4
2
+ Name: experience-graph
3
+ Version: 0.1.0
4
+ Summary: Experience Graph — structured memory and learning for AI agents
5
+ Project-URL: Homepage, https://github.com/experience-graph/experience-graph
6
+ Project-URL: Documentation, https://github.com/experience-graph/experience-graph/tree/main/docs
7
+ Project-URL: Repository, https://github.com/experience-graph/experience-graph
8
+ Project-URL: Issues, https://github.com/experience-graph/experience-graph/issues
9
+ Author: Nathan
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: agents,ai,knowledge-graph,llm,mcp,memory,traces
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Requires-Python: >=3.11
22
+ Requires-Dist: fastapi>=0.115
23
+ Requires-Dist: fastmcp>=2.0
24
+ Requires-Dist: httpx>=0.27
25
+ Requires-Dist: pydantic-settings>=2.0
26
+ Requires-Dist: pydantic>=2.0
27
+ Requires-Dist: python-dateutil>=2.8
28
+ Requires-Dist: pyyaml>=6.0
29
+ Requires-Dist: rich>=13.0
30
+ Requires-Dist: structlog>=23.0
31
+ Requires-Dist: typer>=0.9
32
+ Requires-Dist: ulid-py>=1.1
33
+ Requires-Dist: uvicorn>=0.30
34
+ Provides-Extra: cloud
35
+ Requires-Dist: boto3>=1.34; extra == 'cloud'
36
+ Requires-Dist: pgvector>=0.3; extra == 'cloud'
37
+ Requires-Dist: psycopg-pool>=3.1; extra == 'cloud'
38
+ Requires-Dist: psycopg[binary]>=3.1; extra == 'cloud'
39
+ Provides-Extra: dev
40
+ Requires-Dist: mypy>=1.13; extra == 'dev'
41
+ Requires-Dist: pre-commit>=4.0; extra == 'dev'
42
+ Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
43
+ Requires-Dist: pytest-cov>=4.0; extra == 'dev'
44
+ Requires-Dist: pytest>=8.0; extra == 'dev'
45
+ Requires-Dist: ruff>=0.8; extra == 'dev'
46
+ Requires-Dist: types-pyyaml>=6.0; extra == 'dev'
47
+ Provides-Extra: langgraph
48
+ Requires-Dist: langchain-core>=0.3; extra == 'langgraph'
49
+ Requires-Dist: langgraph>=0.2; extra == 'langgraph'
50
+ Provides-Extra: vectors
51
+ Requires-Dist: lancedb>=0.6; extra == 'vectors'
52
+ Requires-Dist: numpy; extra == 'vectors'
53
+ Requires-Dist: pandas; extra == 'vectors'
54
+ Requires-Dist: pyarrow; extra == 'vectors'
55
+ Description-Content-Type: text/markdown
56
+
57
+ # Experience Graph
58
+
59
+ A structured context graph and experience store for AI agents. Agents read from and write to a shared knowledge layer — traces, entities, evidence, precedents, and policies — so teams build institutional memory instead of starting from scratch.
60
+
61
+ ## What's In the Graph
62
+
63
+ ```
64
+ ┌─────────────────────────────────────────────────────────────────────┐
65
+ │ THE EXPERIENCE GRAPH │
66
+ │ │
67
+ │ ┌───────────┐ depends_on ┌───────────┐ part_of ┌─────────┐ │
68
+ │ │ service: │──────────────▶│ service: │─────────▶│ team: │ │
69
+ │ │ auth-api │ │ user-db │ │ platform │ │
70
+ │ └─────┬─────┘ └───────────┘ └─────────┘ │
71
+ │ │ touched_entity │
72
+ │ ┌─────▼──────────────────────────────────────┐ │
73
+ │ │ trace: "Added rate limiting to auth-api" │ │
74
+ │ │ ├─ step: researched existing patterns │ │
75
+ │ │ ├─ step: tool_call edit_file gateway.py │ │
76
+ │ │ ├─ step: tool_call run_tests (42 passed) │ │
77
+ │ │ └─ outcome: success │ │
78
+ │ └─────┬──────────────────────┬───────────────┘ │
79
+ │ │ used_evidence │ promoted_to_precedent │
80
+ │ ┌─────▼─────────┐ ┌──────▼──────────────────────────┐ │
81
+ │ │ evidence: │ │ precedent: "Rate limiting │ │
82
+ │ │ "RFC: API │ │ pattern for API gateways" │ │
83
+ │ │ guidelines" │ │ confidence: 0.85 │ │
84
+ │ │ uri: s3://… │ │ applies_to: [auth, payments] │ │
85
+ │ └───────────────┘ └─────────────────────────────────┘ │
86
+ │ │
87
+ │ Every node has temporal versions (valid_from / valid_to) │
88
+ │ — query any past state with as_of │
89
+ └─────────────────────────────────────────────────────────────────────┘
90
+ ```
91
+
92
+ The graph captures **what agents did** (traces with steps, tool calls, reasoning, outcomes), **what they knew** (evidence — documents, snippets, file pointers with URIs to local files or S3), **what they learned** (precedents — distilled patterns extracted from successful and failed traces), and **how things relate** (13 edge types: dependencies, provenance, applicability). All nodes carry temporal versions so you can query the state of knowledge at any point in time.
93
+
94
+ ## How It Works
95
+
96
+ ```
97
+ AGENTS & HUMANS BACKGROUND WORKERS
98
+ read & write analyze & curate
99
+ │ │
100
+ │ ┌───────────────────────┐ │
101
+ ├──│ CLI (xpg) │ │
102
+ ├──│ MCP (8 macro tools) │ Tools │ ┌─────────────────────┐
103
+ ├──│ API (REST/FastAPI) │──Layer──┐ ├──│ Enrichment: auto- │
104
+ ├──│ SDK (XPGClient) │ │ │ │ tag, classify, │
105
+ ├──│ OpenClaw (MCP skill) │ │ │ │ score importance │
106
+ │ └───────────────────────┘ │ │ ├─────────────────────┤
107
+ │ │ ├──│ Learning: mine │
108
+ │ ┌───────────────────────┐ │ │ │ failure patterns │
109
+ │ │ Context Pack Builder │◀───────┘ │ │ into precedents │
110
+ │ │ ┌─────┐ ┌─────┐ │ │ ├─────────────────────┤
111
+ │ │ │docs │ │graph│ │ Retrieval├──│ Ingestion: import │
112
+ │ │ │FTS │ │ BFS │ │ │ │ dbt, OpenLineage │
113
+ │ │ └─────┘ └─────┘ │ │ ├─────────────────────┤
114
+ │ │ ┌─────┐ ┌─────┐ │ ├──│ Maintenance: prune │
115
+ │ │ │trace│ │vector│ │ │ │ stale data, audit │
116
+ │ │ │ │ │ │ │ │ ├─────────────────────┤
117
+ │ │ │hist.│ │sim. │ │ └──│ Thinking Engine: │
118
+ │ │ └─────┘ └─────┘ │ │ cognition tiering │
119
+ │ │ │ │ (fast→deep) │
120
+ │ │ → deduplicate │ └─────────────────────┘
121
+ │ │ → rank by relevance │
122
+ │ │ → enforce token │
123
+ │ │ budget │
124
+ │ │ → emit telemetry │
125
+ │ └──────────┬───────────┘
126
+ │ │ assembled pack
127
+ │ ▼
128
+ │ ┌──────────────────────────┐
129
+ │ │ Markdown context for │
130
+ │ │ agent's next task │
131
+ │ │ (token-budgeted, │
132
+ │ │ relevance-ranked) │
133
+ │ └──────────────────────────┘
134
+
135
+ │ ┌──────────────────────────────────────┐
136
+ └─▶│ Governed Write Pipeline │
137
+ │ validate → policy check │
138
+ │ → idempotency → execute │
139
+ │ → emit event (immutable audit log) │
140
+ └──────────────────────┬────────────────┘
141
+
142
+ ┌──────────────────────▼────────────────┐
143
+ │ Pluggable Storage │
144
+ │ SQLite (local) │ Postgres (cloud) │
145
+ │ pgvector │ S3 (blobs/files) │
146
+ └────────────────────────────────────────┘
147
+ ```
148
+
149
+ **The feedback loop:** agents retrieve context packs before tasks, execute work, ingest traces of what happened, and record whether the task succeeded. Background workers analyze these outcomes to promote successful patterns into precedents and flag noisy context items — so the graph gets smarter over time.
150
+
151
+ ## Install
152
+
153
+ Requires Python 3.11+.
154
+
155
+ ```bash
156
+ # Core (SQLite backends)
157
+ pip install -e ".[dev]"
158
+
159
+ # With cloud backends (Postgres, pgvector, S3)
160
+ pip install -e ".[dev,cloud]"
161
+
162
+ # With vector support (LanceDB, numpy, pyarrow)
163
+ pip install -e ".[dev,vectors]"
164
+ ```
165
+
166
+ ## Quick Start
167
+
168
+ ```bash
169
+ xpg admin init # Initialize stores
170
+ xpg admin health # Check store health
171
+ ```
172
+
173
+ ## CLI
174
+
175
+ ```bash
176
+ # Ingest
177
+ xpg ingest trace trace.json # Ingest a trace
178
+ xpg ingest evidence evidence.json # Ingest evidence
179
+ xpg ingest dbt-manifest manifest.json # Import dbt lineage graph
180
+ xpg ingest openlineage events.json # Import OpenLineage events
181
+
182
+ # Curate
183
+ xpg curate promote TRACE_ID --title "..." --description "..."
184
+ xpg curate link SOURCE_ID TARGET_ID
185
+ xpg curate label ENTITY_ID important
186
+ xpg curate feedback TRACE_ID 0.9
187
+
188
+ # Retrieve
189
+ xpg retrieve trace TRACE_ID # Fetch a trace
190
+ xpg retrieve search "query" # Search documents
191
+ xpg retrieve entity ENTITY_ID # Fetch an entity
192
+ xpg retrieve precedents # List precedents
193
+ xpg retrieve pack --intent "..." # Assemble a retrieval pack
194
+
195
+ # Analyze
196
+ xpg analyze context-effectiveness # Which context items correlate with success
197
+ xpg analyze token-usage # Token budget tracking across layers
198
+
199
+ # Admin
200
+ xpg admin stats # Store counts
201
+ xpg admin serve --port 8420 # Start REST API server
202
+ ```
203
+
204
+ All commands support `--format json` for machine-readable output. List commands also support `--format jsonl`, `--format tsv`, `--fields`, `--truncate`, and `--quiet`.
205
+
206
+ ## REST API
207
+
208
+ Start the API server:
209
+
210
+ ```bash
211
+ xpg admin serve --port 8420
212
+ # or
213
+ xpg-api
214
+ ```
215
+
216
+ Key endpoints:
217
+
218
+ | Method | Endpoint | Description |
219
+ |--------|----------|-------------|
220
+ | POST | `/api/v1/traces` | Ingest a trace |
221
+ | GET | `/api/v1/search?q=...` | Full-text search |
222
+ | POST | `/api/v1/packs` | Assemble context pack |
223
+ | GET | `/api/v1/entities/{id}` | Get entity with neighborhood |
224
+ | POST | `/api/v1/precedents` | Promote trace to precedent |
225
+ | POST | `/api/v1/feedback` | Record feedback |
226
+ | GET | `/api/v1/health` | Health check |
227
+ | GET | `/api/v1/stats` | Store statistics |
228
+ | GET | `/api/v1/effectiveness` | Context effectiveness report |
229
+
230
+ Full OpenAPI spec available at `/docs` when the server is running.
231
+
232
+ ## OpenClaw Integration
233
+
234
+ Add structured institutional memory to OpenClaw agents in 3 steps:
235
+
236
+ ```bash
237
+ pip install experience-graph && xpg admin init
238
+ ```
239
+
240
+ Add to `openclaw.json`:
241
+
242
+ ```json
243
+ {
244
+ "mcpServers": {
245
+ "experience-graph": {
246
+ "command": "xpg-mcp",
247
+ "args": []
248
+ }
249
+ }
250
+ }
251
+ ```
252
+
253
+ Your agent gets 8 macro tools for traces, precedents, knowledge graph, and search. See [`integrations/openclaw/`](integrations/openclaw/) for full setup guide.
254
+
255
+ ## MCP Server
256
+
257
+ 8 high-level Macro Tools returning token-budgeted markdown (not raw JSON):
258
+
259
+ ```bash
260
+ xpg-mcp # Start the MCP server
261
+ ```
262
+
263
+ | Tool | Purpose |
264
+ |------|---------|
265
+ | `get_context` | Search docs + graph + traces, return summarized markdown pack |
266
+ | `save_experience` | Ingest a trace |
267
+ | `save_knowledge` | Create entity + optional relationship |
268
+ | `save_memory` | Store a document |
269
+ | `get_lessons` | List precedents as markdown |
270
+ | `get_graph` | Entity + neighborhood as markdown |
271
+ | `record_feedback` | Record task success/failure |
272
+ | `search` | Combined doc + graph search as markdown |
273
+
274
+ All tools accept `max_tokens` (default 2000) for context window budgeting.
275
+
276
+ ## Python SDK
277
+
278
+ ```python
279
+ from xpgraph_sdk import XPGClient
280
+
281
+ # Local mode (direct store access)
282
+ client = XPGClient()
283
+
284
+ # Remote mode (via REST API)
285
+ client = XPGClient(base_url="http://localhost:8420")
286
+
287
+ # Operations
288
+ results = client.search("database migration", limit=5)
289
+ trace_id = client.ingest_trace(trace_dict)
290
+ entity_id = client.create_entity("auth-service", entity_type="service")
291
+ pack = client.assemble_pack("deploy checklist for staging")
292
+ ```
293
+
294
+ Skill functions return pre-summarized markdown strings for direct LLM injection:
295
+
296
+ ```python
297
+ from xpgraph_sdk.skills import get_context_for_task, get_recent_activity
298
+
299
+ context = get_context_for_task(client, "implement retry logic", domain="backend")
300
+ activity = get_recent_activity(client, domain="backend", max_tokens=1500)
301
+ ```
302
+
303
+ ## Pluggable Storage
304
+
305
+ Store backends are selected via `~/.xpg/config.yaml`:
306
+
307
+ ```yaml
308
+ stores:
309
+ graph:
310
+ backend: postgres
311
+ dsn: postgresql://user:pass@host/db
312
+ vector:
313
+ backend: lancedb # serverless, no external DB needed
314
+ # uri: /custom/path # optional, defaults to data/stores/lancedb/
315
+ blob:
316
+ backend: s3
317
+ bucket: xpg-artifacts
318
+ region: us-east-1
319
+ # trace, document, event_log default to sqlite
320
+ ```
321
+
322
+ Available backends:
323
+
324
+ | Store | SQLite (default) | LanceDB | Postgres | Other |
325
+ |-------|:-:|:-:|:-:|:-:|
326
+ | Trace | `sqlite` | | `postgres` | |
327
+ | Document | `sqlite` | | `postgres` | |
328
+ | Graph | `sqlite` | | `postgres` | |
329
+ | Vector | `sqlite` | `lancedb` | `pgvector` | |
330
+ | Event Log | `sqlite` | | `postgres` | |
331
+ | Blob | `local` | | | `s3` |
332
+
333
+ **LanceDB** is the recommended vector backend for local/single-machine deployments — it's serverless (like SQLite for vectors), uses native ANN indexing with cosine similarity, and stores data as efficient Lance-format files on disk. No external database needed. Use **pgvector** for distributed/multi-server deployments.
334
+
335
+ Graph stores support SCD Type 2 temporal versioning — query historical state with `as_of` parameter.
336
+
337
+ ## Ingestion Workers
338
+
339
+ Auto-populate the knowledge graph from external data tools:
340
+
341
+ ```bash
342
+ # Import dbt lineage (models, sources, dependencies)
343
+ xpg ingest dbt-manifest target/manifest.json
344
+
345
+ # Import OpenLineage events (datasets, jobs, reads/writes)
346
+ xpg ingest openlineage lineage-events.json
347
+ ```
348
+
349
+ ## Development
350
+
351
+ ```bash
352
+ pytest # Run all tests (440+)
353
+ pytest tests/unit/ -v # Unit tests only
354
+ pytest -m postgres # Postgres integration tests
355
+ ruff check src/ tests/ # Lint
356
+ mypy src/ # Type check
357
+ ```
358
+
359
+ ## License
360
+
361
+ MIT — see [LICENSE](LICENSE).