Python SDK for the Areev knowledge database — HTTP, gRPC, and MCP transports
Project description
Areev Python SDK
Python client library for the Areev knowledge database.
A grain is one typed memory fact — the atomic unit Areev stores (e.g. the Fact "John likes coffee"). Everything in this SDK ultimately reads or writes grains.
Installation
pip install areev
For gRPC transport:
pip install areev[grpc]
Quick Start
from areev import Areev
areev = Areev() # reads AREEV_API_KEY, AREEV_URL from env
areev.remember("John likes coffee")
results = areev.recall("what does John like?")
for hit in results.results:
print(f" {hit.grain_type}: {hit.fields}")
The synchronous Areev exposes the same full resource surface as
AsyncAreev (client.grains, client.compliance, client.scope, …) with
identical guardrails — automatic retry with idempotency keys, secret/PII
redaction in logs, confirm=True guards on irreversible operations, and
server-side tier/credit/authz verdicts surfaced as typed exceptions:
areev = Areev()
# Data-subject rights (GDPR/CCPA) — never tier- or credit-gated, PII kept out of logs
audit = areev.compliance.audit()
export = areev.compliance.export_user("user-123")
verify = areev.compliance.verify_latest()
# Irreversible erasure requires explicit confirm=True
areev.grains.forget_user("user-123", confirm=True) # GDPR Art. 17
areev.scope.erase("/org/team-a", confirm=True)
areev.consent.grant(user_id="user-123", purpose="marketing")
Configuration
The client reads from environment variables by default:
| Variable | Default | Description |
|---|---|---|
AREEV_API_KEY |
— | API key (sent as Authorization: Bearer <key>) |
AREEV_URL |
https://app.areev.ai |
Server endpoint |
AREEV_MEMORY_ID |
default |
Memory database ID |
Or pass them explicitly:
areev = Areev(api_key="ar_...", url="https://dub.areev.ai", memory_id="my-memory")
Async
from areev import AsyncAreev
async with AsyncAreev() as areev:
await areev.remember("John likes coffee")
results = await areev.recall("what does John like?")
API
The top-level client exposes two headline methods (remember, recall) plus
22 resource namespaces. They split into two groups.
Core — what most integrations use day to day:
| Namespace | What it's for |
|---|---|
remember(text) / recall(query) |
Store NL memory (LLM extracts structure) / search it |
grains |
Typed grain CRUD (add, get, recall, supersede, forget, …) |
harness |
Conversational harness (Areev's LLM-plus-tools runtime) |
tools |
v1 tools surface — bind/list/invoke tools on a harness |
connectors |
Third-party connector catalog + OAuth (Axtion-backed) |
memories |
Memory-database lifecycle + stats |
system |
Health, server models, capabilities |
Advanced / Compliance — governance, identity, and ingestion surfaces you
reach for as you scale: compliance (GDPR/CCPA audit, export, verify),
consent, scope, policy, authz, agent_identities, sessions,
namespaces, provenance, preferences, hooks, goals, chat,
connections, knowledge_sources, imports.
Common Core methods:
| Surface | Description |
|---|---|
remember(text) |
Store natural-language memory (LLM extracts structure) |
recall(query) |
Search memories → typed RecallResponse |
grains.add(grain_type, **fields) |
Add a typed grain → content hash |
grains.get(hash) |
Get a grain by hash |
grains.recall(query) |
Search → typed RecallResponse (same as top-level recall) |
grains.supersede(old_hash, **fields) |
Update a grain → new hash |
grains.forget(hash) / grains.forget_many(hashes) |
Delete grains |
harness.chat(slug=…, message=…) |
Single harness turn (completed / requires_action) |
harness.chat_resume(slug=…, session_id=…, tool_outputs=…) |
Resume a paused session |
harness.chat_cancel(slug=…, session_id=…) |
Cancel a paused session |
harness.chat_interactive(slug=…, message=…, executors=…) |
Harness chat with auto pause/resume for client:// tools |
system.health() |
Health check |
memories.stats(memory_id) |
Database statistics |
Harness Chat
Use harness.chat_interactive to drive a harness (Areev's LLM-plus-tools
runtime) with client-side tool executors. The helper runs the pause/resume
loop for you when the model calls a client:// tool:
from areev import Areev
areev = Areev()
def get_weather(_name, args):
city = args.get("city", "unknown")
return {"city": city, "temp_c": 22, "conditions": "sunny"}
response = areev.harness.chat_interactive(
slug="weather-harness",
message="What's the weather in Paris?",
executors={"get_weather": get_weather},
conversation_id="conv-1",
)
print(response["text"])
AsyncAreev exposes the same method as a coroutine. harness.chat,
harness.chat_resume, and harness.chat_cancel are the low-level primitives
if you want to run the loop yourself.
End-to-End Quickstart (async)
A full flow: connect → remember/recall → create a harness and chat → register a client-side tool → connect a third-party connector and bind one of its actions as a tool — without hand-writing a single JSON Schema.
import asyncio
from areev import AsyncAreev
async def main():
async with AsyncAreev(
api_key="ap_local_...", # ap_*/ar_* key
url="http://localhost:4210", # your cell
memory_id="my-first-memory",
) as areev:
# 1. Remember + recall
await areev.remember("Ada prefers email over Slack")
hits = await areev.recall("how should I contact Ada?")
for h in hits.results:
print(h.grain_type, h.fields)
# 2. Create a harness wired to a provider, then chat
await areev.harness.create(
name="Sales Bot",
slug="sales-bot",
description="Outbound sales assistant",
llm_config={"provider_id": "openai", "model": "gpt-4o-mini"},
# provider_type defaults to provider_id ("openai") automatically.
)
reply = await areev.harness.chat(slug="sales-bot", message="Say hi")
print(reply)
# 3. Add a client-side tool (executed in your process)
def get_weather(_name, args):
return {"city": args.get("city"), "temp_c": 22}
await areev.harness.chat_interactive(
slug="sales-bot",
message="What's the weather in Paris?",
executors={"get_weather": get_weather},
)
# 4. Connect a third-party connector (OAuth), then poll for completion
flow = await areev.connectors.authorize(
"gmail", redirect_uri="https://yourapp.example/oauth/cb"
)
print("Open this URL to authorize:", flow["authorize_url"])
# ... user consents in the browser, provider redirects back ...
status = await areev.connectors.poll_oauth("gmail", flow["state"])
# poll until status["status"] == "success"
# 5. Bind a connector action as a tool — schema fetched for you
await areev.tools.bind_axtion(
slug="sales-bot",
connector="gmail",
action="send-email", # the action key from connectors.actions()
description="Send an email via Gmail",
)
asyncio.run(main())
Connectors
connectorsvsconnectionsvsharnessvschat—connectorsis the third-party catalog + OAuth surface (discover providers, run the handshake);connectionsis the stored credential records for connectors you've already authorized;harnessis the chatbot-with-tools runtime (LLM + bound tools);chatis memory-engine chat (converse over your stored grains).
client.connectors is the catalog + OAuth surface (backed by Axtion). All
methods return clean, parsed data:
| Method | Returns |
|---|---|
connectors.list() |
[{"name", "display_name", "category", "version"}, ...] |
connectors.get(name) |
Raw connector detail (metadata + action descriptors) |
connectors.actions(name) |
[{"name", "display_name", "description", "param_schema", "required"}, ...] |
connectors.authorize(name, redirect_uri=…) |
{"authorize_url", "state", ...} |
connectors.poll_oauth(name, state) |
{"status": "pending"|"success"|"error"|"expired", ...} |
connectors.store_credentials(body) |
Store API-key credentials (non-OAuth connectors) |
Canonical connector flow (OAuth → bind a tool)
# 0. Discover what's available
catalog = await areev.connectors.list()
# → [{"name": "gmail", "display_name": "Google Gmail",
# "category": "Communication", "version": "1.0.0"}, ...]
# 1. Start the OAuth handshake for a connector key from the catalog
flow = await areev.connectors.authorize(
"gmail", redirect_uri="https://yourapp.example/oauth/cb"
)
# 2. Send the user to the authorize URL to consent
print("Open this URL to authorize:", flow["authorize_url"])
# 3. After the provider redirects back, poll until the handshake completes
# (back off between polls — don't hammer the endpoint in a tight loop)
import asyncio
status = await areev.connectors.poll_oauth("gmail", flow["state"])
while status["status"] == "pending":
await asyncio.sleep(2)
status = await areev.connectors.poll_oauth("gmail", flow["state"])
assert status["status"] == "success"
# 4. Bind one of the connector's actions as a harness tool — schema fetched
# for you (no hand-written JSON Schema)
await areev.tools.bind_axtion(
slug="sales-bot",
connector="gmail",
action="send-email", # an action key from connectors.actions("gmail")
description="Send an email via Gmail",
)
Prerequisite — redirect-uri allowlist. The
redirect_uriyou pass toconnectors.authorize(...)must be pre-registered on your org by an admin. An unregistered URI is rejected before any provider redirect — the call raisesValidationError(HTTP 400). Register your callback URL(s) in org settings before going live.
tools.bind_axtion(slug=…, connector=…, action=…) looks up the action's
parameter schema from connectors.actions() and binds it for you — so the
agent gets a fully-typed tool without you writing any JSON Schema.
The sync client (Areev) exposes the identical surface without await.
Transports
| Transport | Extra | Status |
|---|---|---|
| HTTP/REST | (default) | Available |
| gRPC | areev[grpc] |
Available |
| MCP | — | Planned |
Code Generation
Generate gRPC stubs, Pydantic models, the async raw-HTTP resource clients, and the synchronous SDK surface from the Areev spec:
pip install areev[dev]
./scripts/generate.sh
The async modules under src/areev/resources/ and src/areev/http.py are
the single source of truth. The sync twin (src/areev/_sync/) is derived
mechanically from them by scripts/generate_sync.py (via
unasync) — so the two surfaces cannot
drift in their guardrails. Run python scripts/generate_sync.py --check in CI
to fail the build if the committed sync tree is stale.
License
BUSL-1.1
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file areev-0.2.0.tar.gz.
File metadata
- Download URL: areev-0.2.0.tar.gz
- Upload date:
- Size: 288.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
43f550fd36202b932803a10a1d70d49c94ff4006b22500b6e056ae6cc888c281
|
|
| MD5 |
0bf2aa10aae60927f1ac28b9d9734201
|
|
| BLAKE2b-256 |
fcac7d71861248b4458e87999ccf94b75ead5b6a475b69f87885d72d04b113b5
|
File details
Details for the file areev-0.2.0-py3-none-any.whl.
File metadata
- Download URL: areev-0.2.0-py3-none-any.whl
- Upload date:
- Size: 163.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8c312567461482c4e1ed8b709207d084bbac78de1276d60f9f6fec64873f90f8
|
|
| MD5 |
413d1086a8a950ec07c23f6c8495e1b1
|
|
| BLAKE2b-256 |
575f12dfc5d61f9c9e04482de3832dcca5bade87d4d68a68d6a9c9abc66b8be4
|