relata-sdk 0.2.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.
- relata_sdk-0.2.0/.gitignore +259 -0
- relata_sdk-0.2.0/PKG-INFO +407 -0
- relata_sdk-0.2.0/README.md +375 -0
- relata_sdk-0.2.0/examples/analytics.py +231 -0
- relata_sdk-0.2.0/examples/audit.py +358 -0
- relata_sdk-0.2.0/examples/basic_query.py +126 -0
- relata_sdk-0.2.0/examples/face_search.py +225 -0
- relata_sdk-0.2.0/examples/graph_traversal.py +245 -0
- relata_sdk-0.2.0/examples/memory_quickstart.py +22 -0
- relata_sdk-0.2.0/pyproject.toml +64 -0
- relata_sdk-0.2.0/relata/__init__.py +127 -0
- relata_sdk-0.2.0/relata/_http.py +405 -0
- relata_sdk-0.2.0/relata/a2a.py +157 -0
- relata_sdk-0.2.0/relata/audit.py +237 -0
- relata_sdk-0.2.0/relata/backup.py +257 -0
- relata_sdk-0.2.0/relata/client.py +597 -0
- relata_sdk-0.2.0/relata/exceptions.py +203 -0
- relata_sdk-0.2.0/relata/governance.py +499 -0
- relata_sdk-0.2.0/relata/identity.py +267 -0
- relata_sdk-0.2.0/relata/ingest.py +209 -0
- relata_sdk-0.2.0/relata/log.py +162 -0
- relata_sdk-0.2.0/relata/mcp.py +383 -0
- relata_sdk-0.2.0/relata/memory.py +479 -0
- relata_sdk-0.2.0/relata/models.py +354 -0
- relata_sdk-0.2.0/relata/objects.py +228 -0
- relata_sdk-0.2.0/relata/query.py +601 -0
- relata_sdk-0.2.0/relata/s3.py +190 -0
- relata_sdk-0.2.0/relata/streaming.py +320 -0
- relata_sdk-0.2.0/relata/system.py +129 -0
- relata_sdk-0.2.0/relata/tenants.py +246 -0
- relata_sdk-0.2.0/relata/tokens.py +167 -0
- relata_sdk-0.2.0/relata/vectors.py +209 -0
- relata_sdk-0.2.0/relata_adapters/__init__.py +20 -0
- relata_sdk-0.2.0/relata_adapters/_base.py +87 -0
- relata_sdk-0.2.0/relata_adapters/ag2.py +85 -0
- relata_sdk-0.2.0/relata_adapters/autogen.py +50 -0
- relata_sdk-0.2.0/relata_adapters/crewai.py +56 -0
- relata_sdk-0.2.0/relata_adapters/langchain.py +64 -0
- relata_sdk-0.2.0/relata_adapters/llamaindex.py +60 -0
- relata_sdk-0.2.0/relata_adapters/pydantic_ai.py +88 -0
- relata_sdk-0.2.0/relata_adapters/registry.py +76 -0
- relata_sdk-0.2.0/relata_adapters/smolagents.py +88 -0
- relata_sdk-0.2.0/relata_langgraph/__init__.py +180 -0
- relata_sdk-0.2.0/tests/test_adapters.py +135 -0
- relata_sdk-0.2.0/tests/test_agent_verbs_coverage.py +190 -0
- relata_sdk-0.2.0/tests/test_async_memory.py +66 -0
- relata_sdk-0.2.0/tests/test_introspection_and_headers.py +199 -0
- relata_sdk-0.2.0/tests/test_langgraph_checkpointer.py +98 -0
- relata_sdk-0.2.0/tests/test_log_tokens_backup_stats.py +308 -0
- relata_sdk-0.2.0/tests/test_memory.py +189 -0
- relata_sdk-0.2.0/tests/test_memory_completion_and_query_cursor.py +204 -0
- relata_sdk-0.2.0/tests/test_sdk_modules_wave.py +404 -0
- relata_sdk-0.2.0/tests/test_streaming_tenants_safety.py +212 -0
- relata_sdk-0.2.0/tests/test_transport_and_adapters.py +243 -0
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
|
|
3
|
+
# Relata — .gitignore
|
|
4
|
+
# =============================================================================
|
|
5
|
+
# Layered by tool. Keep entries grouped and alphabetised within groups.
|
|
6
|
+
# Anything generated, machine-specific, or secret stays out of git.
|
|
7
|
+
# Spec corpus (SPECS.md, DECISIONS.md, etc.), source code, and CI config stay IN.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
|
|
10
|
+
# -----------------------------------------------------------------------------
|
|
11
|
+
# Rust / Cargo
|
|
12
|
+
# -----------------------------------------------------------------------------
|
|
13
|
+
/target/
|
|
14
|
+
**/target/
|
|
15
|
+
**/*.rs.bk
|
|
16
|
+
Cargo.lock.bak
|
|
17
|
+
|
|
18
|
+
# Cargo.lock IS committed for binaries (relata-cli) and applications, but the
|
|
19
|
+
# workspace publishes only binaries today. If a publishable library is added
|
|
20
|
+
# later, narrow this rule per ADR.
|
|
21
|
+
# (Cargo.lock is intentionally NOT ignored.)
|
|
22
|
+
|
|
23
|
+
# Cargo registry / git caches that some tools dump locally
|
|
24
|
+
.cargo/registry/
|
|
25
|
+
.cargo/git/
|
|
26
|
+
|
|
27
|
+
# Coverage and profiling output
|
|
28
|
+
*.profraw
|
|
29
|
+
*.profdata
|
|
30
|
+
coverage/
|
|
31
|
+
tarpaulin-report.html
|
|
32
|
+
cobertura.xml
|
|
33
|
+
lcov.info
|
|
34
|
+
flamegraph.svg
|
|
35
|
+
perf.data
|
|
36
|
+
perf.data.old
|
|
37
|
+
samply.json
|
|
38
|
+
*.cargo-ok
|
|
39
|
+
CLAUDE.md
|
|
40
|
+
# Criterion benchmark output (large; regenerate locally)
|
|
41
|
+
**/criterion/
|
|
42
|
+
|
|
43
|
+
# rust-analyzer / IDE incrementals
|
|
44
|
+
rust-analyzer-*.log
|
|
45
|
+
|
|
46
|
+
# -----------------------------------------------------------------------------
|
|
47
|
+
# Build artefacts (engine binaries, signed bundles, release outputs)
|
|
48
|
+
# -----------------------------------------------------------------------------
|
|
49
|
+
/dist/
|
|
50
|
+
/build/
|
|
51
|
+
/release/
|
|
52
|
+
*.dSYM/
|
|
53
|
+
*.pdb
|
|
54
|
+
|
|
55
|
+
# Air-gap install bundles (large; not source of truth)
|
|
56
|
+
/airgap-bundle/
|
|
57
|
+
*.airgap.tar
|
|
58
|
+
*.airgap.tar.zst
|
|
59
|
+
|
|
60
|
+
# -----------------------------------------------------------------------------
|
|
61
|
+
# Generated docs (mdbook, rustdoc) — sources are committed, output is not
|
|
62
|
+
# -----------------------------------------------------------------------------
|
|
63
|
+
/docs/book/
|
|
64
|
+
/target/doc/
|
|
65
|
+
|
|
66
|
+
# -----------------------------------------------------------------------------
|
|
67
|
+
# Conformance corpus (M0.5) and benchmark data
|
|
68
|
+
# -----------------------------------------------------------------------------
|
|
69
|
+
# Sample-data generators are committed under relata-conformance/<pack>/generators/
|
|
70
|
+
# Generated fixtures (Parquet, CSV, JSON) are large and reproducible — ignore them.
|
|
71
|
+
/relata-conformance/*/fixtures/generated/
|
|
72
|
+
/relata-conformance/*/snapshots/
|
|
73
|
+
**/conformance-results-*.json
|
|
74
|
+
**/BENCHMARKS-RESULTS.local.md
|
|
75
|
+
**/BENCHMARKS-CONFORMANCE.local.md
|
|
76
|
+
|
|
77
|
+
# Legacy roadmap state mirror (M0.1.E). GitHub Issues/Milestones are current.
|
|
78
|
+
/roadmap_state.json
|
|
79
|
+
|
|
80
|
+
# -----------------------------------------------------------------------------
|
|
81
|
+
# Secrets, credentials, KMS material — NEVER commit
|
|
82
|
+
# -----------------------------------------------------------------------------
|
|
83
|
+
.env
|
|
84
|
+
.env.*
|
|
85
|
+
!.env.example
|
|
86
|
+
*.pem
|
|
87
|
+
*.key
|
|
88
|
+
*.p12
|
|
89
|
+
*.pfx
|
|
90
|
+
*.crt
|
|
91
|
+
*.cer
|
|
92
|
+
*.csr
|
|
93
|
+
!relata-conformance/**/*.pem.example
|
|
94
|
+
!relata-conformance/**/*.key.example
|
|
95
|
+
secrets/
|
|
96
|
+
credentials.json
|
|
97
|
+
**/kms-cache/
|
|
98
|
+
**/hsm-session-*
|
|
99
|
+
|
|
100
|
+
# AWS / GCP / Azure / Cloudflare local credentials
|
|
101
|
+
.aws/credentials
|
|
102
|
+
.aws/config
|
|
103
|
+
gcloud/
|
|
104
|
+
.azure/
|
|
105
|
+
.cloudflare/
|
|
106
|
+
.config/rclone/
|
|
107
|
+
|
|
108
|
+
# TUF / Sigstore local material (ADR-058)
|
|
109
|
+
# Root metadata and Rekor pins are committed under docs/security/;
|
|
110
|
+
# session keys, cosign keys, and rekor signing material are NOT.
|
|
111
|
+
*.cosign.key
|
|
112
|
+
*.cosign.pub
|
|
113
|
+
!cosign.pub.example
|
|
114
|
+
# License files generated by the License Manager (test / demo artefacts)
|
|
115
|
+
*.lic
|
|
116
|
+
/tuf-staging/
|
|
117
|
+
/tuf-private/
|
|
118
|
+
|
|
119
|
+
# -----------------------------------------------------------------------------
|
|
120
|
+
# Object-store local emulators (MinIO, fake-s3) used in dev
|
|
121
|
+
# -----------------------------------------------------------------------------
|
|
122
|
+
/minio-data/
|
|
123
|
+
/.minio.sys/
|
|
124
|
+
/fake-s3/
|
|
125
|
+
/localstack/
|
|
126
|
+
|
|
127
|
+
# Kafka / Redpanda local data
|
|
128
|
+
/kafka-data/
|
|
129
|
+
/redpanda-data/
|
|
130
|
+
|
|
131
|
+
# etcd / FoundationDB local data (writer-lease fallback for M4.A.3)
|
|
132
|
+
/etcd-data/
|
|
133
|
+
/fdb-data/
|
|
134
|
+
/fdb.cluster
|
|
135
|
+
|
|
136
|
+
# -----------------------------------------------------------------------------
|
|
137
|
+
# Tracing / profiling artefacts
|
|
138
|
+
# -----------------------------------------------------------------------------
|
|
139
|
+
/traces/
|
|
140
|
+
*.svg.tmp
|
|
141
|
+
chrome-trace-*.json
|
|
142
|
+
otel-traces-*.json
|
|
143
|
+
*.heap-profile
|
|
144
|
+
|
|
145
|
+
# -----------------------------------------------------------------------------
|
|
146
|
+
# SDKs (sdks/python, sdks/typescript, sdks/go) — language-local artefacts
|
|
147
|
+
# -----------------------------------------------------------------------------
|
|
148
|
+
# Python (uv + pyo3)
|
|
149
|
+
__pycache__/
|
|
150
|
+
*.py[cod]
|
|
151
|
+
*$py.class
|
|
152
|
+
*.so
|
|
153
|
+
*.pyd
|
|
154
|
+
.venv/
|
|
155
|
+
venv/
|
|
156
|
+
.env-py/
|
|
157
|
+
.pytest_cache/
|
|
158
|
+
.mypy_cache/
|
|
159
|
+
.ruff_cache/
|
|
160
|
+
.pdm-build/
|
|
161
|
+
.pdm-python
|
|
162
|
+
dist-py/
|
|
163
|
+
build-py/
|
|
164
|
+
*.egg-info/
|
|
165
|
+
*.whl
|
|
166
|
+
uv.lock.bak
|
|
167
|
+
|
|
168
|
+
# Maturin / pyo3 build output
|
|
169
|
+
sdks/python/target/
|
|
170
|
+
sdks/python/*.so
|
|
171
|
+
sdks/python/*.dylib
|
|
172
|
+
|
|
173
|
+
# TypeScript / Node
|
|
174
|
+
node_modules/
|
|
175
|
+
dist-ts/
|
|
176
|
+
.npm/
|
|
177
|
+
.pnp.*
|
|
178
|
+
.yarn/
|
|
179
|
+
.parcel-cache/
|
|
180
|
+
*.tsbuildinfo
|
|
181
|
+
.next/
|
|
182
|
+
.turbo/
|
|
183
|
+
|
|
184
|
+
# Go
|
|
185
|
+
sdks/go/bin/
|
|
186
|
+
sdks/go/pkg/
|
|
187
|
+
sdks/go/vendor/
|
|
188
|
+
|
|
189
|
+
# -----------------------------------------------------------------------------
|
|
190
|
+
# Editor / IDE
|
|
191
|
+
# -----------------------------------------------------------------------------
|
|
192
|
+
.vscode/
|
|
193
|
+
!.vscode/extensions.json
|
|
194
|
+
!.vscode/settings.shared.json
|
|
195
|
+
.idea/
|
|
196
|
+
*.iml
|
|
197
|
+
*.swp
|
|
198
|
+
*.swo
|
|
199
|
+
*~
|
|
200
|
+
.*.swp
|
|
201
|
+
.*.swo
|
|
202
|
+
.zed/
|
|
203
|
+
.nvim/
|
|
204
|
+
.code-workspace
|
|
205
|
+
|
|
206
|
+
# -----------------------------------------------------------------------------
|
|
207
|
+
# OS noise
|
|
208
|
+
# -----------------------------------------------------------------------------
|
|
209
|
+
.DS_Store
|
|
210
|
+
.DS_Store?
|
|
211
|
+
._*
|
|
212
|
+
.Spotlight-V100
|
|
213
|
+
.Trashes
|
|
214
|
+
ehthumbs.db
|
|
215
|
+
Thumbs.db
|
|
216
|
+
Desktop.ini
|
|
217
|
+
$RECYCLE.BIN/
|
|
218
|
+
|
|
219
|
+
# -----------------------------------------------------------------------------
|
|
220
|
+
# CI / test scratch
|
|
221
|
+
# -----------------------------------------------------------------------------
|
|
222
|
+
/tmp/
|
|
223
|
+
/.tmp/
|
|
224
|
+
/scratch/
|
|
225
|
+
/.scratch/
|
|
226
|
+
*.log
|
|
227
|
+
!CHANGELOG*.md
|
|
228
|
+
test-output/
|
|
229
|
+
junit*.xml
|
|
230
|
+
|
|
231
|
+
# -----------------------------------------------------------------------------
|
|
232
|
+
# Simulation output — all generated; not part of the shipped artefact
|
|
233
|
+
# -----------------------------------------------------------------------------
|
|
234
|
+
simulation-output/
|
|
235
|
+
landing/simulation-output/
|
|
236
|
+
|
|
237
|
+
# -----------------------------------------------------------------------------
|
|
238
|
+
# AI/editor session state (chat-tool scratch — never commit)
|
|
239
|
+
# -----------------------------------------------------------------------------
|
|
240
|
+
.vibekit/
|
|
241
|
+
.claude/
|
|
242
|
+
.cursor/
|
|
243
|
+
.aider*
|
|
244
|
+
.aider/
|
|
245
|
+
.windsurf/
|
|
246
|
+
|
|
247
|
+
# -----------------------------------------------------------------------------
|
|
248
|
+
# Local overrides (last-resort escape hatch; document in PR if used)
|
|
249
|
+
# -----------------------------------------------------------------------------
|
|
250
|
+
*.local
|
|
251
|
+
*.local.*
|
|
252
|
+
.local/
|
|
253
|
+
LOCAL.md
|
|
254
|
+
NOTES.local.md
|
|
255
|
+
data/
|
|
256
|
+
docs/src/usecases/screenshots/
|
|
257
|
+
|
|
258
|
+
# Local Relata runtime state (CLI store, WAL, local data) — never commit
|
|
259
|
+
.relata/
|
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: relata-sdk
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Python SDK for the Relata enterprise-grade data engine
|
|
5
|
+
Project-URL: Homepage, https://relata.io
|
|
6
|
+
Project-URL: Documentation, https://docs.relata.io/sdk/python
|
|
7
|
+
Project-URL: Repository, https://github.com/OpenWorkBench-Co/RelataDB
|
|
8
|
+
Project-URL: Issues, https://github.com/OpenWorkBench-Co/RelataDB/issues
|
|
9
|
+
Author-email: Relata <sdk@relata.io>
|
|
10
|
+
License: Apache-2.0
|
|
11
|
+
Keywords: analytics,bi-temporal,data-engine,ontology,relata
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Database
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Python: >=3.11
|
|
23
|
+
Requires-Dist: httpx>=0.27
|
|
24
|
+
Requires-Dist: pydantic>=2.6
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: mypy>=1.10; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: respx>=0.21; extra == 'dev'
|
|
30
|
+
Requires-Dist: ruff>=0.4; extra == 'dev'
|
|
31
|
+
Description-Content-Type: text/markdown
|
|
32
|
+
|
|
33
|
+
# Relata Python SDK
|
|
34
|
+
|
|
35
|
+
Python SDK for the [Relata](https://relatadb.dev) enterprise-grade data engine.
|
|
36
|
+
|
|
37
|
+
Relata is a Rust-native, ontology-driven engine built for bi-temporal, governed knowledge workloads: link analysis, identity resolution, full-text and vector search, access-scoped restricted data, and provenance-tracked analytics.
|
|
38
|
+
|
|
39
|
+
## Requirements
|
|
40
|
+
|
|
41
|
+
- Python 3.11+
|
|
42
|
+
- `httpx >= 0.27`
|
|
43
|
+
- `pydantic >= 2.6`
|
|
44
|
+
|
|
45
|
+
## Installation
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install relata-sdk
|
|
49
|
+
# or with uv
|
|
50
|
+
uv add relata-sdk
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Quick start
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
from relata import RelataClient
|
|
57
|
+
|
|
58
|
+
with RelataClient("http://localhost:9090", purpose="analytics") as client:
|
|
59
|
+
result = client.query("SELECT * FROM Person WHERE name LIKE 'Ahmed%' LIMIT 10")
|
|
60
|
+
for row in result:
|
|
61
|
+
print(row)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Agent memory in three lines
|
|
65
|
+
|
|
66
|
+
For agent-memory workloads, `Memory` is a Mem0-style one-liner surface over the
|
|
67
|
+
governed `/memory/*` verbs — governance (purpose + ACL) stays on by default:
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
from relata import Memory
|
|
71
|
+
|
|
72
|
+
with Memory("http://localhost:9090", purpose="agent-notes") as m:
|
|
73
|
+
mem_id = m.add("Alice prefers dark mode") # store
|
|
74
|
+
hits = m.search("ui preferences", top_k=5) # recall (confidence × recency × relevance)
|
|
75
|
+
m.forget(mem_id) # governed retract, not a hard delete
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
See `examples/memory_quickstart.py`. For async apps, `AsyncMemory` has the same
|
|
79
|
+
surface: `async with AsyncMemory(...) as m: await m.add(...); await m.search(...)`.
|
|
80
|
+
|
|
81
|
+
## Agent-framework adapters
|
|
82
|
+
|
|
83
|
+
Drop-in, governed memory backends for the major agent frameworks — each maps the
|
|
84
|
+
framework's memory/storage interface onto Relata, and none imports its framework
|
|
85
|
+
(so they load with or without it installed):
|
|
86
|
+
|
|
87
|
+
| Framework | Import | Shape |
|
|
88
|
+
|---|---|---|
|
|
89
|
+
| LangChain | `relata_adapters.langchain.RelataMemory` | `BaseMemory` |
|
|
90
|
+
| LlamaIndex | `relata_adapters.llamaindex.RelataMemory` | `BaseMemory` |
|
|
91
|
+
| CrewAI | `relata_adapters.crewai.RelataStorage` | `Storage` |
|
|
92
|
+
| AutoGen | `relata_adapters.autogen.RelataMemory` | `Memory` (async) |
|
|
93
|
+
| LangGraph | `relata_langgraph.RelataCheckpointer` | checkpointer |
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
from relata_adapters.langchain import RelataMemory
|
|
97
|
+
|
|
98
|
+
mem = RelataMemory(base_url="http://localhost:9090", purpose="agent")
|
|
99
|
+
# chain = ConversationChain(llm=..., memory=mem)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
The adapters use the semantic-memory model (store + relevance recall), the same
|
|
103
|
+
paradigm as Mem0. They wrap the `Memory` client, so governance stays on.
|
|
104
|
+
|
|
105
|
+
## Core concepts
|
|
106
|
+
|
|
107
|
+
### Every query must declare a purpose
|
|
108
|
+
|
|
109
|
+
Relata enforces a mandatory `purpose` on every query. The purpose must be a string registered in the tenant's `PurposeRegistry` (e.g. `"analytics"`, `"audit"`, `"analysis"`). Queries without a purpose are rejected at the wire.
|
|
110
|
+
|
|
111
|
+
Set a default on the client:
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
client = RelataClient("http://localhost:9090", purpose="analytics")
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Or override per-call:
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
result = client.query("SELECT COUNT(*) FROM Person", purpose="audit")
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Bearer token authentication
|
|
124
|
+
|
|
125
|
+
When the server is configured with `RELATA_BEARER_TOKEN`, pass the token to the client:
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
client = RelataClient(
|
|
129
|
+
"https://relata.example.com",
|
|
130
|
+
bearer_token="your-token",
|
|
131
|
+
purpose="analytics",
|
|
132
|
+
)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
> **What identity does my SDK client use by default?**
|
|
136
|
+
>
|
|
137
|
+
> Without a bearer token, every request runs as the **`api-user`** principal —
|
|
138
|
+
> a built-in identity with read access to all domain types and write access
|
|
139
|
+
> in open (lite) mode. Audit entries, quota charges, and ACL decisions all
|
|
140
|
+
> attribute to `api-user`.
|
|
141
|
+
>
|
|
142
|
+
> MCP requests (`McpClient`) run as **`mcp-client`** — a different principal
|
|
143
|
+
> with separate audit and quota accounting.
|
|
144
|
+
>
|
|
145
|
+
> For multi-tenant production: set a bearer token + `tenant=` on every
|
|
146
|
+
> request. See `docs/src/end-users/defaults.md` for the full default-behavior
|
|
147
|
+
> reference.
|
|
148
|
+
|
|
149
|
+
### Fluent query builder
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
result = (
|
|
153
|
+
client.select("Person")
|
|
154
|
+
.where("nationality = 'IN'")
|
|
155
|
+
.where("age > 25")
|
|
156
|
+
.as_of("2025-01-01") # bi-temporal point-in-time
|
|
157
|
+
.with_provenance() # include PROV-O columns
|
|
158
|
+
.order_by("name ASC")
|
|
159
|
+
.limit(20)
|
|
160
|
+
.execute()
|
|
161
|
+
)
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Relata SQL extensions
|
|
165
|
+
|
|
166
|
+
| Extension | Example |
|
|
167
|
+
|---|---|
|
|
168
|
+
| Bi-temporal | `SELECT * FROM Person AS OF '2024-06-01'` |
|
|
169
|
+
| Provenance | `SELECT * FROM Person WITH PROVENANCE` |
|
|
170
|
+
| Graph traversal | `FROM PATHS_BETWEEN('person-123', 'org-456', max_hops => 4)` |
|
|
171
|
+
| Face search | `WHERE MATCH_FACE(probe_embedding, stored_embedding, 0.92)` |
|
|
172
|
+
| Identity lookup | `FROM LOOKUP_IDENTITY('+919876543210')` |
|
|
173
|
+
| Hybrid search | `SELECT *, HYBRID_SCORE('terror finance') AS score FROM Document` |
|
|
174
|
+
|
|
175
|
+
### QueryResult is iterable
|
|
176
|
+
|
|
177
|
+
```python
|
|
178
|
+
result = client.query("SELECT * FROM Person LIMIT 10")
|
|
179
|
+
|
|
180
|
+
# Iterate over rows
|
|
181
|
+
for row in result:
|
|
182
|
+
print(row["name"])
|
|
183
|
+
|
|
184
|
+
# Access by index
|
|
185
|
+
first = result.rows[0]
|
|
186
|
+
|
|
187
|
+
# Check if empty
|
|
188
|
+
if not result:
|
|
189
|
+
print("No results")
|
|
190
|
+
|
|
191
|
+
# Row count
|
|
192
|
+
print(f"{len(result)} rows in {result.elapsed_ms} ms")
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Async support
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
import asyncio
|
|
199
|
+
from relata import RelataClient
|
|
200
|
+
|
|
201
|
+
async def main():
|
|
202
|
+
async with RelataClient("http://localhost:9090", purpose="analytics") as client:
|
|
203
|
+
result = await client.aquery("SELECT * FROM Person LIMIT 5")
|
|
204
|
+
for row in result:
|
|
205
|
+
print(row)
|
|
206
|
+
|
|
207
|
+
asyncio.run(main())
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Error handling
|
|
211
|
+
|
|
212
|
+
```python
|
|
213
|
+
from relata.exceptions import (
|
|
214
|
+
PurposeError, # missing or unregistered purpose
|
|
215
|
+
QuotaError, # per-principal cost quota exhausted
|
|
216
|
+
AuthError, # invalid or missing bearer token
|
|
217
|
+
ConnectionError, # server unreachable
|
|
218
|
+
RelataError, # base class — catch all SDK errors
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
try:
|
|
222
|
+
result = client.query("SELECT * FROM Person")
|
|
223
|
+
except PurposeError as exc:
|
|
224
|
+
print(f"Fix: set purpose= on client or per query. {exc}")
|
|
225
|
+
except QuotaError as exc:
|
|
226
|
+
print(f"Quota exhausted — reduce query scope. {exc}")
|
|
227
|
+
except AuthError as exc:
|
|
228
|
+
print(f"Auth failed — check bearer_token. {exc}")
|
|
229
|
+
except ConnectionError as exc:
|
|
230
|
+
print(f"Cannot reach server. {exc}")
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## API reference
|
|
234
|
+
|
|
235
|
+
### `RelataClient`
|
|
236
|
+
|
|
237
|
+
```python
|
|
238
|
+
RelataClient(
|
|
239
|
+
base_url: str,
|
|
240
|
+
*,
|
|
241
|
+
bearer_token: str | None = None,
|
|
242
|
+
purpose: str | None = None,
|
|
243
|
+
timeout: float = 30.0,
|
|
244
|
+
tenant: str | None = None, # X-Organization-Id (multi-tenant)
|
|
245
|
+
acting_as: str | None = None, # X-Acting-As (delegation)
|
|
246
|
+
delegated_by: str | None = None, # X-Delegated-By
|
|
247
|
+
headers: dict[str, str] | None = None, # arbitrary header overlay
|
|
248
|
+
max_retries: int = 0, # retry on connection errors
|
|
249
|
+
retry_backoff_secs: float = 0.5, # exponential backoff base
|
|
250
|
+
)
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
| Method | Returns | Description |
|
|
254
|
+
|---|---|---|
|
|
255
|
+
| `query(sql, *, purpose)` | `QueryResult` | Execute a SQL query |
|
|
256
|
+
| `health()` | `HealthResponse` | Check node health |
|
|
257
|
+
| `status()` | `StatusResponse` | Node status + quota |
|
|
258
|
+
| `stats()` | `Stats` | Engine-wide counts (records/states/snapshot_rows/log_leaves/tokens) |
|
|
259
|
+
| `version()` | `VersionInfo` | Build info (version, commit, profile, schema_version) |
|
|
260
|
+
| `ready()` | `ReadyReport` | 9-condition readiness report |
|
|
261
|
+
| `audit_count()` | `AuditCountResponse` | Audit log entry count + chain validity |
|
|
262
|
+
| `cluster_nodes()` | `list[ClusterNode]` | List cluster nodes |
|
|
263
|
+
| `select(*cols)` | `QueryBuilder` | Start a fluent query |
|
|
264
|
+
| `close()` | — | Close sync connections |
|
|
265
|
+
| `aquery(...)` | `QueryResult` | Async query |
|
|
266
|
+
| `ahealth()` ... `astats()` ... `aready()` etc. | — | Async mirrors of every method above |
|
|
267
|
+
| `aclose()` | — | Close async connections |
|
|
268
|
+
|
|
269
|
+
### v1.1 typed clients (`from_client(client)`)
|
|
270
|
+
|
|
271
|
+
Each module inherits the parent client's auth, tenant, and purpose context:
|
|
272
|
+
|
|
273
|
+
| Module | Class | Surface |
|
|
274
|
+
|---|---|---|
|
|
275
|
+
| `relata.governance` | `GovernanceClient` | Rules, retention (holds + WORM), breakglass, alerts, DSAR |
|
|
276
|
+
| `relata.mcp` | `McpClient` | 22 typed MCP tool wrappers + generic `call_tool` |
|
|
277
|
+
| `relata.a2a` | `A2AClient` | A2A tasks + LangGraph checkpoints + agent card |
|
|
278
|
+
| `relata.audit` | `AuditClient` | Audit entries (filtered/paginated) + signed receipts + PDF export |
|
|
279
|
+
| `relata.identity` | `IdentityClient` | Identity label/uncertainty + lookup tables + ERASE SUBJECT |
|
|
280
|
+
| `relata.objects` | `ObjectClient` | Typed upsert + batch via `/ingest?object_type=` |
|
|
281
|
+
| `relata.ingest` | `IngestClient` | Bulk NDJSON + CSV + media status |
|
|
282
|
+
| `relata.vectors` | `VectorClient` | KNN + hybrid search + similar-to (SQL-backed) |
|
|
283
|
+
| `relata.s3` | `S3Client` | boto3 / httpx / aiobotocore wrapper for the S3 protocol door |
|
|
284
|
+
| `relata.system` | `SystemClient` | LLM config + test + jobs status |
|
|
285
|
+
| `relata.streaming` | `StreamingClient` | NDJSON row streams + SSE consumers (watch/alerts) + Arrow IPC |
|
|
286
|
+
| `relata.tenants` | `TenantAdminClient` | Tenant CRUD + quota + sharing agreements + platform admin |
|
|
287
|
+
|
|
288
|
+
Each has an async mirror (`Async*`).
|
|
289
|
+
|
|
290
|
+
### v1.1 transport hardening (#79)
|
|
291
|
+
|
|
292
|
+
- **RFC 7807 problem+json parsing** — every error carries `code`, `type_url`, `retryable`, `request_id`.
|
|
293
|
+
- **Typed exceptions** — `ForbiddenError` (403), `NotFoundError` (404), `ConflictError` (409), `ValidationError` (422), `RateLimitedError` (429, with `retry_after`).
|
|
294
|
+
- **Retry** — `RelataClient(..., max_retries=3, retry_backoff_secs=0.5)`.
|
|
295
|
+
- **X-Request-ID** — auto-generated per request; caller-supplied IDs respected; server's response ID stamped on exceptions.
|
|
296
|
+
|
|
297
|
+
### Custom object types
|
|
298
|
+
|
|
299
|
+
RelataDB is ontology-governed — unknown types are rejected on both ingest and
|
|
300
|
+
read. Register custom types at runtime via `POST /types` (persisted across
|
|
301
|
+
restart):
|
|
302
|
+
|
|
303
|
+
```python
|
|
304
|
+
# Register a custom type
|
|
305
|
+
client._sync.post("/types", {
|
|
306
|
+
"name": "AgentTask",
|
|
307
|
+
"fields": [
|
|
308
|
+
{"name": "task_id", "type": "string"},
|
|
309
|
+
{"name": "status", "type": "string"},
|
|
310
|
+
]
|
|
311
|
+
})
|
|
312
|
+
|
|
313
|
+
# Now ingest + query work
|
|
314
|
+
client._sync.post("/ingest?object_type=AgentTask", {"task_id": "t-1", "status": "done"})
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
For ACL access in strict mode, grant via env var:
|
|
318
|
+
```bash
|
|
319
|
+
RELATA_ACL_GRANT=AgentTask:read+write
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
Unknown types return `400` on both ingest and read — fail-closed by design.
|
|
323
|
+
|
|
324
|
+
### v1.1 QueryBuilder extensions (#76)
|
|
325
|
+
|
|
326
|
+
| Method | Description |
|
|
327
|
+
|---|---|
|
|
328
|
+
| `.limit(n, after="cursor")` | Keyset pagination (`LIMIT n AFTER 'cursor'`) |
|
|
329
|
+
| `.since(cursor)` | Incremental reads (`WHERE system_from > cursor`) |
|
|
330
|
+
|
|
331
|
+
The builder also validates identifiers (`from_()`, `select()`) and refuses
|
|
332
|
+
dangerous tokens in `where()` (SQL-injection stopgap).
|
|
333
|
+
|
|
334
|
+
### Agent-framework adapters
|
|
335
|
+
|
|
336
|
+
| Framework | Import | Shape |
|
|
337
|
+
|---|---|---|
|
|
338
|
+
| LangChain | `relata_adapters.langchain.RelataMemory` | `BaseMemory` |
|
|
339
|
+
| LlamaIndex | `relata_adapters.llamaindex.RelataMemory` | `BaseMemory` |
|
|
340
|
+
| CrewAI | `relata_adapters.crewai.RelataStorage` | `Storage` |
|
|
341
|
+
| AutoGen v0.2 | `relata_adapters.autogen.RelataMemory` | `Memory` (async) |
|
|
342
|
+
| LangGraph | `relata_langgraph.RelataCheckpointer` | checkpointer |
|
|
343
|
+
| AG2 (v0.4+) | `relata_adapters.ag2.RelataAG2Memory` | `MemoryProtocol` |
|
|
344
|
+
| Pydantic-AI | `relata_adapters.pydantic_ai.RelataMemoryBackend` | memory backend |
|
|
345
|
+
| smolagents | `relata_adapters.smolagents.RelataTool` | tool callable |
|
|
346
|
+
| Auto-detect | `relata_adapters.registry.get_memory_adapter()` | picks the right class |
|
|
347
|
+
|
|
348
|
+
### `QueryBuilder`
|
|
349
|
+
|
|
350
|
+
| Method | Description |
|
|
351
|
+
|---|---|
|
|
352
|
+
| `.select(*cols)` | Columns or table name shorthand |
|
|
353
|
+
| `.from_(table)` | FROM table |
|
|
354
|
+
| `.where(condition)` | Add WHERE predicate (multiple calls → AND) |
|
|
355
|
+
| `.as_of(timestamp)` | Bi-temporal AS OF |
|
|
356
|
+
| `.with_provenance()` | Append WITH PROVENANCE |
|
|
357
|
+
| `.purpose(p)` | Override purpose for this query |
|
|
358
|
+
| `.limit(n)` | LIMIT |
|
|
359
|
+
| `.offset(n)` | OFFSET |
|
|
360
|
+
| `.order_by(*cols)` | ORDER BY |
|
|
361
|
+
| `.paths_between(src, dst, max_hops)` | PATHS_BETWEEN graph operator |
|
|
362
|
+
| `.match_face(probe, candidate, threshold)` | MATCH_FACE operator |
|
|
363
|
+
| `.lookup_identity(value)` | LOOKUP_IDENTITY operator |
|
|
364
|
+
| `.hybrid_score(text)` | HYBRID_SCORE ranking |
|
|
365
|
+
| `.raw(sql)` | Raw SQL escape hatch |
|
|
366
|
+
| `.sql()` | Return assembled SQL without executing |
|
|
367
|
+
| `.execute()` | Execute (sync) |
|
|
368
|
+
| `.aexecute()` | Execute (async) |
|
|
369
|
+
|
|
370
|
+
### Response models
|
|
371
|
+
|
|
372
|
+
| Model | Fields |
|
|
373
|
+
|---|---|
|
|
374
|
+
| `QueryResult` | `rows`, `query_id`, `elapsed_ms`, `row_count` |
|
|
375
|
+
| `HealthResponse` | `status`, `profile`, `node_id` |
|
|
376
|
+
| `StatusResponse` | `profile`, `role`, `query_quota` |
|
|
377
|
+
| `AuditCountResponse` | `entries`, `chain_valid` |
|
|
378
|
+
| `ClusterNode` | `node_id`, `role`, `url` |
|
|
379
|
+
| `VersionInfo` | `version`, `commit`, `profile`, `schema_version`, `features` |
|
|
380
|
+
| `Stats` | `records`, `states`, `snapshot_rows`, `log_leaves`, `tokens` |
|
|
381
|
+
| `ReadyReport` | `is_ready`, `status`, `reason`, `detail` |
|
|
382
|
+
|
|
383
|
+
## Examples
|
|
384
|
+
|
|
385
|
+
See the `examples/` directory:
|
|
386
|
+
|
|
387
|
+
| File | Demonstrates |
|
|
388
|
+
|---|---|
|
|
389
|
+
| `basic_query.py` | Getting started, health check, quota check |
|
|
390
|
+
| `analytics.py` | Full analytics workflow: identity → cases → graph → provenance |
|
|
391
|
+
| `face_search.py` | MATCH_FACE operator, threshold comparison, CCTV temporal search |
|
|
392
|
+
| `graph_traversal.py` | PATHS_BETWEEN, temporal network shift, hub detection |
|
|
393
|
+
| `audit.py` | Chain verification, audit summary, anomaly detection |
|
|
394
|
+
|
|
395
|
+
## Deployment profiles
|
|
396
|
+
|
|
397
|
+
Relata ships three deployment profiles. The SDK works identically across all three:
|
|
398
|
+
|
|
399
|
+
| Profile | Use case | Binary |
|
|
400
|
+
|---|---|---|
|
|
401
|
+
| `lite` | Embedded / single-process | `RELATA_PROFILE=lite relata serve` |
|
|
402
|
+
| `server` | Single-node production | `RELATA_PROFILE=server relata serve` |
|
|
403
|
+
| `cluster` | Multi-node distributed | `RELATA_PROFILE=cluster relata serve` |
|
|
404
|
+
|
|
405
|
+
## License
|
|
406
|
+
|
|
407
|
+
AGPL-3.0-only. See the root `LICENSE` file.
|