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.
- experience_graph-0.1.0/.github/workflows/ci.yml +41 -0
- experience_graph-0.1.0/.gitignore +22 -0
- experience_graph-0.1.0/.pre-commit-config.yaml +13 -0
- experience_graph-0.1.0/CLAUDE.md +110 -0
- experience_graph-0.1.0/LICENSE +21 -0
- experience_graph-0.1.0/Makefile +29 -0
- experience_graph-0.1.0/PKG-INFO +361 -0
- experience_graph-0.1.0/README.md +305 -0
- experience_graph-0.1.0/TODO.md +42 -0
- experience_graph-0.1.0/docs/agent-guide/README.md +21 -0
- experience_graph-0.1.0/docs/agent-guide/operations.md +858 -0
- experience_graph-0.1.0/docs/agent-guide/playbooks.md +586 -0
- experience_graph-0.1.0/docs/agent-guide/schemas.md +660 -0
- experience_graph-0.1.0/docs/agent-guide/trace-format.md +303 -0
- experience_graph-0.1.0/docs/design/architecture-design.md +92 -0
- experience_graph-0.1.0/docs/design/context-economy-strategy.md +71 -0
- experience_graph-0.1.0/docs/design/plan-context-economy.md +220 -0
- experience_graph-0.1.0/docs/design/plan-pluggable-architecture.md +303 -0
- experience_graph-0.1.0/integrations/__init__.py +1 -0
- experience_graph-0.1.0/integrations/langgraph/README.md +111 -0
- experience_graph-0.1.0/integrations/langgraph/__init__.py +1 -0
- experience_graph-0.1.0/integrations/langgraph/tools.py +180 -0
- experience_graph-0.1.0/integrations/obsidian/__init__.py +12 -0
- experience_graph-0.1.0/integrations/obsidian/indexer.py +179 -0
- experience_graph-0.1.0/integrations/obsidian/vault.py +215 -0
- experience_graph-0.1.0/integrations/openclaw/README.md +99 -0
- experience_graph-0.1.0/integrations/openclaw/SKILL.md +87 -0
- experience_graph-0.1.0/integrations/openclaw/openclaw.example.json +8 -0
- experience_graph-0.1.0/pyproject.toml +143 -0
- experience_graph-0.1.0/src/xpgraph/__init__.py +1 -0
- experience_graph-0.1.0/src/xpgraph/core/__init__.py +0 -0
- experience_graph-0.1.0/src/xpgraph/core/base.py +52 -0
- experience_graph-0.1.0/src/xpgraph/core/ids.py +23 -0
- experience_graph-0.1.0/src/xpgraph/errors.py +73 -0
- experience_graph-0.1.0/src/xpgraph/mcp/__init__.py +1 -0
- experience_graph-0.1.0/src/xpgraph/mcp/server.py +470 -0
- experience_graph-0.1.0/src/xpgraph/mcp_server.py +695 -0
- experience_graph-0.1.0/src/xpgraph/mutate/__init__.py +25 -0
- experience_graph-0.1.0/src/xpgraph/mutate/commands.py +155 -0
- experience_graph-0.1.0/src/xpgraph/mutate/executor.py +212 -0
- experience_graph-0.1.0/src/xpgraph/mutate/policy_gate.py +137 -0
- experience_graph-0.1.0/src/xpgraph/py.typed +0 -0
- experience_graph-0.1.0/src/xpgraph/retrieve/__init__.py +17 -0
- experience_graph-0.1.0/src/xpgraph/retrieve/effectiveness.py +150 -0
- experience_graph-0.1.0/src/xpgraph/retrieve/formatters.py +341 -0
- experience_graph-0.1.0/src/xpgraph/retrieve/pack_builder.py +158 -0
- experience_graph-0.1.0/src/xpgraph/retrieve/strategies.py +169 -0
- experience_graph-0.1.0/src/xpgraph/retrieve/token_tracker.py +59 -0
- experience_graph-0.1.0/src/xpgraph/retrieve/token_usage.py +145 -0
- experience_graph-0.1.0/src/xpgraph/schemas/__init__.py +56 -0
- experience_graph-0.1.0/src/xpgraph/schemas/entity.py +28 -0
- experience_graph-0.1.0/src/xpgraph/schemas/enums.py +72 -0
- experience_graph-0.1.0/src/xpgraph/schemas/evidence.py +39 -0
- experience_graph-0.1.0/src/xpgraph/schemas/graph.py +21 -0
- experience_graph-0.1.0/src/xpgraph/schemas/pack.py +53 -0
- experience_graph-0.1.0/src/xpgraph/schemas/policy.py +38 -0
- experience_graph-0.1.0/src/xpgraph/schemas/precedent.py +27 -0
- experience_graph-0.1.0/src/xpgraph/schemas/trace.py +83 -0
- experience_graph-0.1.0/src/xpgraph/stores/__init__.py +35 -0
- experience_graph-0.1.0/src/xpgraph/stores/base/__init__.py +19 -0
- experience_graph-0.1.0/src/xpgraph/stores/base/blob.py +41 -0
- experience_graph-0.1.0/src/xpgraph/stores/base/document.py +76 -0
- experience_graph-0.1.0/src/xpgraph/stores/base/event_log.py +130 -0
- experience_graph-0.1.0/src/xpgraph/stores/base/graph.py +170 -0
- experience_graph-0.1.0/src/xpgraph/stores/base/trace.py +44 -0
- experience_graph-0.1.0/src/xpgraph/stores/base/vector.py +56 -0
- experience_graph-0.1.0/src/xpgraph/stores/document.py +6 -0
- experience_graph-0.1.0/src/xpgraph/stores/event_log.py +6 -0
- experience_graph-0.1.0/src/xpgraph/stores/graph.py +6 -0
- experience_graph-0.1.0/src/xpgraph/stores/lancedb/__init__.py +5 -0
- experience_graph-0.1.0/src/xpgraph/stores/lancedb/store.py +236 -0
- experience_graph-0.1.0/src/xpgraph/stores/local/__init__.py +5 -0
- experience_graph-0.1.0/src/xpgraph/stores/local/blob.py +71 -0
- experience_graph-0.1.0/src/xpgraph/stores/pgvector/__init__.py +5 -0
- experience_graph-0.1.0/src/xpgraph/stores/pgvector/store.py +196 -0
- experience_graph-0.1.0/src/xpgraph/stores/postgres/__init__.py +13 -0
- experience_graph-0.1.0/src/xpgraph/stores/postgres/document.py +260 -0
- experience_graph-0.1.0/src/xpgraph/stores/postgres/event_log.py +208 -0
- experience_graph-0.1.0/src/xpgraph/stores/postgres/graph.py +650 -0
- experience_graph-0.1.0/src/xpgraph/stores/postgres/trace.py +203 -0
- experience_graph-0.1.0/src/xpgraph/stores/registry.py +249 -0
- experience_graph-0.1.0/src/xpgraph/stores/s3/__init__.py +5 -0
- experience_graph-0.1.0/src/xpgraph/stores/s3/blob.py +143 -0
- experience_graph-0.1.0/src/xpgraph/stores/sqlite/__init__.py +15 -0
- experience_graph-0.1.0/src/xpgraph/stores/sqlite/document.py +289 -0
- experience_graph-0.1.0/src/xpgraph/stores/sqlite/event_log.py +177 -0
- experience_graph-0.1.0/src/xpgraph/stores/sqlite/graph.py +700 -0
- experience_graph-0.1.0/src/xpgraph/stores/sqlite/trace.py +187 -0
- experience_graph-0.1.0/src/xpgraph/stores/sqlite/vector.py +174 -0
- experience_graph-0.1.0/src/xpgraph/stores/trace.py +6 -0
- experience_graph-0.1.0/src/xpgraph/stores/vector.py +6 -0
- experience_graph-0.1.0/src/xpgraph_api/__init__.py +1 -0
- experience_graph-0.1.0/src/xpgraph_api/app.py +65 -0
- experience_graph-0.1.0/src/xpgraph_api/deps.py +36 -0
- experience_graph-0.1.0/src/xpgraph_api/models.py +137 -0
- experience_graph-0.1.0/src/xpgraph_api/routes/__init__.py +1 -0
- experience_graph-0.1.0/src/xpgraph_api/routes/admin.py +46 -0
- experience_graph-0.1.0/src/xpgraph_api/routes/curate.py +143 -0
- experience_graph-0.1.0/src/xpgraph_api/routes/ingest.py +52 -0
- experience_graph-0.1.0/src/xpgraph_api/routes/retrieve.py +141 -0
- experience_graph-0.1.0/src/xpgraph_cli/__init__.py +1 -0
- experience_graph-0.1.0/src/xpgraph_cli/admin.py +179 -0
- experience_graph-0.1.0/src/xpgraph_cli/analyze.py +174 -0
- experience_graph-0.1.0/src/xpgraph_cli/config.py +47 -0
- experience_graph-0.1.0/src/xpgraph_cli/curate.py +206 -0
- experience_graph-0.1.0/src/xpgraph_cli/ingest.py +193 -0
- experience_graph-0.1.0/src/xpgraph_cli/main.py +32 -0
- experience_graph-0.1.0/src/xpgraph_cli/output.py +96 -0
- experience_graph-0.1.0/src/xpgraph_cli/retrieve.py +406 -0
- experience_graph-0.1.0/src/xpgraph_cli/stores.py +49 -0
- experience_graph-0.1.0/src/xpgraph_sdk/__init__.py +5 -0
- experience_graph-0.1.0/src/xpgraph_sdk/client.py +283 -0
- experience_graph-0.1.0/src/xpgraph_sdk/skills.py +153 -0
- experience_graph-0.1.0/src/xpgraph_workers/__init__.py +1 -0
- experience_graph-0.1.0/src/xpgraph_workers/engine/__init__.py +1 -0
- experience_graph-0.1.0/src/xpgraph_workers/engine/thinking.py +300 -0
- experience_graph-0.1.0/src/xpgraph_workers/enrichment/__init__.py +15 -0
- experience_graph-0.1.0/src/xpgraph_workers/enrichment/service.py +271 -0
- experience_graph-0.1.0/src/xpgraph_workers/ingestion/__init__.py +1 -0
- experience_graph-0.1.0/src/xpgraph_workers/ingestion/base.py +92 -0
- experience_graph-0.1.0/src/xpgraph_workers/ingestion/dbt.py +140 -0
- experience_graph-0.1.0/src/xpgraph_workers/ingestion/openlineage.py +152 -0
- experience_graph-0.1.0/src/xpgraph_workers/learning/__init__.py +1 -0
- experience_graph-0.1.0/src/xpgraph_workers/learning/miner.py +247 -0
- experience_graph-0.1.0/src/xpgraph_workers/maintenance/__init__.py +1 -0
- experience_graph-0.1.0/src/xpgraph_workers/maintenance/retention.py +184 -0
- experience_graph-0.1.0/tests/__init__.py +0 -0
- experience_graph-0.1.0/tests/integration/__init__.py +1 -0
- experience_graph-0.1.0/tests/integration/obsidian/__init__.py +1 -0
- experience_graph-0.1.0/tests/integration/obsidian/test_indexer.py +217 -0
- experience_graph-0.1.0/tests/integration/obsidian/test_vault.py +232 -0
- experience_graph-0.1.0/tests/unit/__init__.py +0 -0
- experience_graph-0.1.0/tests/unit/api/__init__.py +0 -0
- experience_graph-0.1.0/tests/unit/api/test_routes.py +167 -0
- experience_graph-0.1.0/tests/unit/cli/__init__.py +1 -0
- experience_graph-0.1.0/tests/unit/cli/conftest.py +20 -0
- experience_graph-0.1.0/tests/unit/cli/test_admin.py +94 -0
- experience_graph-0.1.0/tests/unit/cli/test_curate.py +118 -0
- experience_graph-0.1.0/tests/unit/cli/test_ingest.py +112 -0
- experience_graph-0.1.0/tests/unit/cli/test_retrieve.py +99 -0
- experience_graph-0.1.0/tests/unit/core/__init__.py +0 -0
- experience_graph-0.1.0/tests/unit/core/test_base.py +43 -0
- experience_graph-0.1.0/tests/unit/core/test_ids.py +36 -0
- experience_graph-0.1.0/tests/unit/mutate/__init__.py +0 -0
- experience_graph-0.1.0/tests/unit/mutate/test_commands.py +155 -0
- experience_graph-0.1.0/tests/unit/mutate/test_executor.py +202 -0
- experience_graph-0.1.0/tests/unit/mutate/test_policy_gate.py +177 -0
- experience_graph-0.1.0/tests/unit/retrieve/__init__.py +0 -0
- experience_graph-0.1.0/tests/unit/retrieve/test_effectiveness.py +150 -0
- experience_graph-0.1.0/tests/unit/retrieve/test_formatters.py +132 -0
- experience_graph-0.1.0/tests/unit/retrieve/test_pack_builder.py +133 -0
- experience_graph-0.1.0/tests/unit/retrieve/test_strategies.py +183 -0
- experience_graph-0.1.0/tests/unit/retrieve/test_token_tracker.py +257 -0
- experience_graph-0.1.0/tests/unit/schemas/__init__.py +0 -0
- experience_graph-0.1.0/tests/unit/schemas/test_entity.py +79 -0
- experience_graph-0.1.0/tests/unit/schemas/test_evidence.py +56 -0
- experience_graph-0.1.0/tests/unit/schemas/test_pack.py +55 -0
- experience_graph-0.1.0/tests/unit/schemas/test_policy.py +37 -0
- experience_graph-0.1.0/tests/unit/schemas/test_precedent.py +39 -0
- experience_graph-0.1.0/tests/unit/schemas/test_trace.py +151 -0
- experience_graph-0.1.0/tests/unit/sdk/__init__.py +0 -0
- experience_graph-0.1.0/tests/unit/sdk/test_client.py +92 -0
- experience_graph-0.1.0/tests/unit/sdk/test_skills.py +70 -0
- experience_graph-0.1.0/tests/unit/stores/__init__.py +0 -0
- experience_graph-0.1.0/tests/unit/stores/test_document_store.py +132 -0
- experience_graph-0.1.0/tests/unit/stores/test_event_log.py +104 -0
- experience_graph-0.1.0/tests/unit/stores/test_graph_store.py +133 -0
- experience_graph-0.1.0/tests/unit/stores/test_lancedb_store.py +122 -0
- experience_graph-0.1.0/tests/unit/stores/test_pgvector.py +112 -0
- experience_graph-0.1.0/tests/unit/stores/test_postgres_stores.py +354 -0
- experience_graph-0.1.0/tests/unit/stores/test_s3_blob.py +205 -0
- experience_graph-0.1.0/tests/unit/stores/test_temporal_graph.py +361 -0
- experience_graph-0.1.0/tests/unit/stores/test_trace_store.py +129 -0
- experience_graph-0.1.0/tests/unit/stores/test_vector_store.py +81 -0
- experience_graph-0.1.0/tests/unit/test_errors.py +44 -0
- experience_graph-0.1.0/tests/unit/workers/__init__.py +0 -0
- experience_graph-0.1.0/tests/unit/workers/engine/__init__.py +0 -0
- experience_graph-0.1.0/tests/unit/workers/engine/test_thinking.py +349 -0
- experience_graph-0.1.0/tests/unit/workers/enrichment/__init__.py +0 -0
- experience_graph-0.1.0/tests/unit/workers/enrichment/test_service.py +246 -0
- experience_graph-0.1.0/tests/unit/workers/learning/__init__.py +0 -0
- experience_graph-0.1.0/tests/unit/workers/learning/test_miner.py +390 -0
- experience_graph-0.1.0/tests/unit/workers/maintenance/__init__.py +0 -0
- experience_graph-0.1.0/tests/unit/workers/maintenance/test_retention.py +282 -0
- 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,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).
|