Skip to main content

The official Python SDK for the Unison brain API

Project description

python-sdk

The Unison brain, in four lines of Python.

The memory layer for agents — powered by the Unison brain.

CI PyPI version Python 3.9+ License: MIT Stars

Installation · Quickstart · API Reference · Contributing


Quickstart

pip install unisonlabs
export UNISON_TOKEN=usk_live_...
from unisonlabs import UnisonBrain

client = UnisonBrain()                                          # reads UNISON_TOKEN env var
results = client.search("architecture decisions", limit=5)      # hybrid search
doc = client.write("/private/notes/my-note.md", "# Note\n...")  # write
doc2 = client.get("/private/notes/my-note.md")                  # read back
print(doc2.body)

AI agents: read AGENTS.md — install, auth with a usk_ key, and the search-first / write-back loop in four steps.

MCP Server

Use the Unison brain MCP server to give AI assistants direct access to your brain:

{
  "mcpServers": {
    "unison-brain": {
      "command": "npx",
      "args": ["-y", "@unisonlabs/mcp"],
      "env": {
        "UNISON_TOKEN": "usk_live_...",
        "UNISON_API_URL": "https://brain.unisonlabs.ai"
      }
    }
  }
}

Installation

pip install unisonlabs

Python 3.9 or higher required.

Environment variables

Variable Default Description
UNISON_TOKEN required Your usk_live_... API token
UNISON_API_URL https://brain.unisonlabs.ai Base URL for the brain API

Usage

Synchronous

import os
from unisonlabs import UnisonBrain

client = UnisonBrain(
    token=os.environ.get("UNISON_TOKEN"),  # default — can be omitted
)

# Confirm auth and check scopes
me = client.whoami()
print(me.user.email, me.scopes)

# Search (hybrid keyword + semantic)
results = client.search("architecture decisions", limit=5)
for hit in results.results:
    print(f"[{hit.score:.2f}] {hit.doc.path}")

# Read a document
doc = client.get("/workspace/projects/architecture.md")
print(doc.body)

# Write a document
# Writable roots: /private/..., /workspace/...
doc = client.write(
    "/private/notes/my-note.md",
    "# My Note\n\nContent here.",
    title="My Note",
    tags=["draft"],
)

# Surgical edit (old_str must match exactly once)
client.edit_doc("/private/notes/my-note.md", "Content here.", "Updated content.")

# Entity graph
resp = client.entities.resolve("Alice")
if resp.entity:
    facts = client.entities.facts(resp.entity.id)

# Record a fact
client.facts.record(
    subject_id="entity-id",
    predicate="works_at",
    fact_text="Joined Unison in 2026",
    confidence=0.9,
)

# Brain status
status = client.status()
print(f"{status.docCount} docs, {status.entityCount} entities")

client.close()

Async

import asyncio
from unisonlabs import AsyncUnisonBrain

async def main() -> None:
    async with AsyncUnisonBrain() as client:
        results = await client.search("auth decision", limit=3)
        for hit in results.results:
            print(hit.doc.path)

asyncio.run(main())

Context manager

with UnisonBrain() as client:
    doc = client.get("/workspace/notes/foo.md")

with_options

fast_client = client.with_options(timeout=10.0, max_retries=0)

Headless machine auth (no browser)

Three-step flow to provision a token programmatically:

import httpx

# Step 1 — provision (creates an unverified account + returns a usk_ key)
resp = httpx.post(
    "https://brain.unisonlabs.ai/v1/auth/provision",
    json={"email": "agent@example.com"},
)
api_key = resp.json()["apiKey"]  # immediately usable (unverified, 72h expiry)

# Step 2 — verify with the OTP emailed to agent@example.com
from unisonlabs import UnisonBrain
client = UnisonBrain(token=api_key)
verify_resp = client.auth.verify("agent@example.com", input("OTP: "))
# Workspace is now durable; key never expires unless rotated

# Key recovery (already-verified accounts)
client.auth.request_key("agent@example.com")
new_key_resp = client.auth.verify("agent@example.com", input("Recovery OTP: "))
print(new_key_resp.apiKey)

API Reference

client.documents

Method Description
search(q, *, k, kind, tag, memory_type, as_of) Hybrid search
grep(pattern, *, case_sensitive, limit) Regex scan over document bodies
get(path) Read a document (includes body)
write(path, body_md, *, kind, title, tldr, tags, visibility, ...) Write/create a document
edit(path, old_str, new_str) Surgical in-place edit
delete(path) Delete a document
tag(path, *, add, remove) Add/remove tags
share(*, kind, id) Promote private to workspace-visible
list(*, prefix, kind, tag, limit) List documents
fs_list(path) Directory listing
fs_read(path) Raw content (including read-only tiers)
neighbors(id_or_path, *, kind, limit) Graph neighbours
status() Health + counts

client.entities

Method Description
list(*, kind, status, limit) List entities
resolve(name, *, kind_hint) Find by name (fuzzy+alias)
get(entity_id) Get one entity
upsert(kind, display_name, *, slug, aliases, props, status) Create or update
facts(entity_id, *, as_of, include_invalidated) Facts about an entity
timeline(entity_id, *, from_, to) Chronological facts

client.facts

Method Description
list(*, limit, include_invalidated) Browse all facts
record(subject_id, predicate, fact_text, *, ...) Record a new fact
correct(fact_id, **fields) Correct/supersede a fact
invalidate(fact_id) Soft-delete (sets validTo=now)

client.links

Method Description
list(*, limit) List directed graph edges
create(from_id, to_id, kind) Create a link

client.auth

Method Description
whoami() Confirm auth + check scopes
provision(email) Headless account creation
verify(email, code) Verify OTP / key recovery
request_key(email) Request recovery OTP
device_code(client_id, scope?) Start device flow
device_token(device_code) Poll device flow
exchange_code(code, code_verifier, redirect_uri, client_id) PKCE exchange

client.review (requires brain:admin)

Method Description
conflicts() Pending dedup merge pairs
resolve_conflict(conflict_id, verdict) 'merge' or 'distinct'
merges(*, limit) Recent merges (undo feed)
undo_merge(merge_id) Enqueue unmerge

client.jobs (requires brain:admin)

Method Description
list(*, status, kind, limit) Job queue visibility
stats() Job counts by status
retry(job_id) Re-queue failed job

Brain FS contract

All document paths must end in .md. Writable roots:

Root Visibility
/private/... Private to the calling user
/workspace/... Entire workspace (use workspace/teams/<slug>/ for team folders)

Unqualified paths (no leading /) are automatically rewritten to /private/notes/<slug>.md. Invalid roots (/actions/, /raw/, /teams/, unknown namespaces) raise BrainContractError before any network call.

Error handling

import unisonlabs

try:
    doc = client.get("/workspace/missing.md")
except unisonlabs.NotFoundError as e:
    print(f"404: {e.message}")
except unisonlabs.AuthenticationError:
    print("Invalid token")
except unisonlabs.RateLimitError:
    print("Rate limited — back off")
except unisonlabs.APIConnectionError as e:
    print(f"Connection failed: {e}")
Status Exception
400 BadRequestError
401 AuthenticationError
403 PermissionDeniedError
404 NotFoundError
409 ConflictError
422 UnprocessableEntityError
429 RateLimitError
>=500 InternalServerError
network APIConnectionError
timeout APITimeoutError

Retries

The client retries 2 times by default with exponential backoff on connection errors, timeouts, and 408/409/429/5xx responses.

client = UnisonBrain(max_retries=0)  # disable retries

Star history

⭐ If Unison is useful to you, a star helps other developers find it.

Releasing

Set a PyPI token — either configure ~/.pypirc or export:

export TWINE_USERNAME=__token__
export TWINE_PASSWORD=pypi-...

Then:

python3 scripts/release.py

Builds, publishes unisonlabs to PyPI (idempotent — skips if the version is already live), then tags and pushes v<version>.

Contributing

Open issues and pull requests at github.com/unison-labs-ai/python-sdk. See CONTRIBUTING.md for development setup, conventions, and PR guidelines. Security issues: email security@unisonlabs.ai — do not open a public issue.


Part of the Unison Labs constellation

One brain, every agent. Every repo below reads from and writes to the same Unison brain — no per-tool memory silos.

Repo What it does
unison-brain CLI · SDK · MCP server — the core
claude-unison Memory for Claude Code
cursor-unison Memory for Cursor
codex-unison Memory for OpenAI Codex CLI
opencode-unison Memory for OpenCode
openclaw-unison Memory for OpenClaw
pipecat-unison Memory for Pipecat voice agents
python-sdk ← you are here Python SDK for the brain
install-mcp One-command MCP installer
code-chunk AST-aware code chunking
unison-fs Mount the brain as a filesystem
backchannel Async messaging between agents
Unison-evals Open memory benchmark suite

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

unisonlabs-0.2.0.tar.gz (82.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

unisonlabs-0.2.0-py3-none-any.whl (31.4 kB view details)

Uploaded Python 3

File details

Details for the file unisonlabs-0.2.0.tar.gz.

File metadata

  • Download URL: unisonlabs-0.2.0.tar.gz
  • Upload date:
  • Size: 82.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for unisonlabs-0.2.0.tar.gz
Algorithm Hash digest
SHA256 d6444cc862432cbc238e346c9ee438bcd7824b19f3eca5133eb67a00b4178493
MD5 8512f1b6b1ddb42cea9733f97d8e1a53
BLAKE2b-256 bc25b88bbf7f8cd08ddf19f8922560dafa825350afc1fbef8d1172ef770f2920

See more details on using hashes here.

File details

Details for the file unisonlabs-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: unisonlabs-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 31.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for unisonlabs-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5eac813de8255d525db224b395e0a0b364b4964cae7da861c46ff697fad21c19
MD5 35e1a4ec17bea16ce07c90a7e355334a
BLAKE2b-256 1d66f23427ed3b4a58848ced72a2a0e516fd5243f8ff5366f5c0800f5780a6f7

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page