Import CloudClient, then write, recall, and inspect hosted state.
import os
from bilinc import CloudClient
client = CloudClient(api_key=os.environ["BILINC_API_KEY"])
client.commit("user.preference", {"theme": "dark"})
results = client.recall("user preference", limit=5)
# What can this key do? (authenticated, never billed)
status = client.status()
# Is the service reachable? (public service health)
health = client.health()Write, correct, checkpoint, inspect, forget, recover.
import os
from bilinc import CloudClient
client = CloudClient(api_key=os.environ["BILINC_API_KEY"])
# 1. Write. The returned version is your optimistic-concurrency token.
written = client.commit("user.preference", {"theme": "dark"})
version = written["entryVersion"]
# 2. Read.
client.recall("user preference", profile="balanced", limit=5)
# 3. Correct something you already know. Fails if it does not exist.
client.revise(
"user.preference",
{"theme": "light"},
reason="user changed it in settings",
expected_version=version,
)
# 4. Checkpoint before risky agent work.
snapshot = client.create_snapshot(label="before-autonomous-run")["snapshot"]
# 5. See what the run changed. Values are redacted by default.
client.diff(snapshot["id"])
# 6. Review what is stored and how one memory changed. Both reads are free.
client.list_memories(prefix="user.", limit=50)
client.history("user.preference")
# 7. Drop obsolete state. A reason is required and is audited.
client.forget("user.preference", reason="superseded by profile service")
# 8. Recover. Preview is free; execute is destructive and needs the token.
preview = client.rollback_preview(snapshot["id"], reason="undo bad agent run")
client.rollback(
snapshot["id"],
confirmation_token=preview["confirmationToken"],
reason="undo bad agent run",
)The public surface, and what each call costs.
commit(key, value, ...)
Write a memory. Returns an entry version for optimistic concurrency.
recall(query, profile=, limit=)
Read memories. Profiles are entitlement gated; limit is 1–100.
revise(key, value, reason=, expected_version=)
Replace an existing memory. Never creates.
confirm(key, expected_version=, reason=)
Record that a memory is still accurate without resending it. One write operation.
forget(key, reason=)
Destructive. Remove a memory. A reason is required.
list_memories(prefix=, memory_type=, updated_after=, updated_before=, cursor=, limit=50, values="preview")
Free. One page of stored memories, ordered by key. Pass nextCursor back as cursor.
iter_memories(prefix=, memory_type=, updated_after=, updated_before=, page_size=100, values="preview")
Free. Yields every matching memory, following the cursor for you.
history(key, limit=20, values="full")
Free. One memory’s most recent changes, newest first: 20 by default, up to 100, with truncated set when older ones exist. Values from before a forget are never returned.
export(prefix=, memory_type=)
Free. Every matching memory with its full value, as one JSON-ready dict. History is not included.
create_snapshot(label=) / list_snapshots(limit=)
Checkpoint the project, or list checkpoints.
snapshot(action="create"|"list")
The same two operations behind one MCP-shaped call.
diff(from_snapshot_id, to_snapshot_id=, include_values=)
Free comparison; values redacted by default.
rollback_preview(snapshot_id, reason=)
Free. Returns a short-lived confirmation token.
rollback(snapshot_id, confirmation_token=, reason=)
Destructive. Requires that token.
status()
Authenticated workspace, plan, capabilities, limits, usage. Never billed.
health()
Public service health.
See what Bilinc remembers, and how it changed.
list_memories, history, and export only read and are never billed. The time filters take a datetime (a naive one is read as UTC) or an ISO-8601 string. The same commands are in the CLI: bilinc list, bilinc history KEY, bilinc confirm KEY, and bilinc export -o FILE.
import json
import os
from bilinc import CloudClient
client = CloudClient(api_key=os.environ["BILINC_API_KEY"])
# Every memory under a prefix, page by page (free).
for entry in client.iter_memories(prefix="user."):
print(entry["key"], entry["updatedAt"], entry.get("value"))
# How one memory changed, newest first (free).
for step in client.history("user.preference")["entries"]:
print(step["at"], step["op"], step.get("before"), "->", step.get("after"))
# Still accurate? Confirm it without resending the value (one write).
client.confirm("user.preference", reason="user said it is still right")
# Everything, with full values, as one JSON file (free).
with open("bilinc-memory.json", "w") as handle:
json.dump(client.export(), handle, indent=2)Use the right shape for the right state.
working
Active short-lived context.
episodic
Event and session memory.
procedural
Reusable workflows.
semantic
Durable facts and beliefs.
Reads retry themselves; writes do not.
The SDK retries read-only calls a bounded number of times on transport and 5xx failures. Writes are single-shot on purpose: a retried write could apply twice. Pass idempotency_key on a write you might retry, and the server replays the original result instead of executing again.
