fraise-sdk (Python)
A Python client for a Fraise memory server, plus ready-made memory tools for agent frameworks.
Install
pip install fraise-sdk # core client only
pip install 'fraise-sdk[openai]' # + OpenAI Agents SDK tools
pip install 'fraise-sdk[anthropic]' # + Claude Agent SDK tools
pip install 'fraise-sdk[huggingface]' # + Hugging Face embedder
Client
remember stores a fact and recall searches for facts, both through the server's query endpoint:
from fraise_sdk import FraiseClient
with FraiseClient("http://localhost:9876") as fraise:
fraise.remember("anne loves the color orange", topics=["color"], entities=["anne"])
result = fraise.recall("anne", "color", top=5)
for hit in result:
print(hit.value, hit.score)
recall returns a RecallResult (.count, .hits, and it iterates/len()s over the hits). Vector search is supported by passing an embedding:
fraise.remember("the kingfisher is electric blue", graph=6, vector=embedding)
hits = fraise.recall(graph=6, vector=embedding) # seeded only by the vector
A recall needs a seed, not a keyword: a vector or a topics/entities anchor is one on its own, so fraise.recall(topics=["birds"]) — everything about a topic — is a query in its own right.
The typed helpers take any value and write the FQL for you: a topic, entity or keyword is quoted whenever it is not letters and digits only, such as e-mail or new york, and a keyword is also quoted when it spells a reserved word such as since — with a FraiseWarning, since recall("since", "7d") may have meant a since:7d bound rather than the word. Anything they do not cover, such as a since:/until: time bound, goes through the raw fraise.query("recall@3 ...") escape hatch, which sends the FQL exactly as written and leaves the checking to the server.
Some queries run but carry something that cannot help them — a keyword that is an English stop word, e.g. fraise.recall("ferry", "the"): stored facts never contain "the", so it cannot match. The server answers them and attaches a warning; the SDK lists it on result.warnings and re-emits it as a FraiseWarning:
import warnings
from fraise_sdk import FraiseWarning
warnings.filterwarnings("ignore", category=FraiseWarning) # silence wholesale
The query shapes that warn (and the neighbouring ones that stay silent) are catalogued in Warnings.
To see why a fact ranked where it did, explain takes the same arguments as recall and returns the same ranking, with each hit's contributions — the text, vector, graph or anchor sightings its score was folded from — and the query's background rate on the result:
result = fraise.explain("polly", entities=["polly"], depth=2)
for hit in result:
print(hit.value, [(c.source, c.score, c.via) for c in hit.contributions])
A hit whose only contribution is graph was reached through an anchor without matching the query itself. See Explain for how the contributions fold into the score.
Embeddings (optional)
Give the client an embedder and it encodes text to a vector automatically — remember embeds its value, recall embeds its query phrase (or its keywords):
from fraise_sdk import FraiseClient
from fraise_sdk.providers.openai import OpenAIEmbedder # needs fraise-sdk[openai]
fraise = FraiseClient("http://localhost:9876", embedder=OpenAIEmbedder(dimensions=128))
fraise.remember("the kingfisher is electric blue", graph=6) # stored with its vector
hits = fraise.recall(query="small bright bird", graph=6)
An embedder is anything implementing the Embedder ABC (subclass it and define embed(text) -> Sequence[float]) or a plain callable(text) -> Sequence[float], so a lambda over your own model works too. Per call you can force it with embed=True, skip it with embed=False, or override with an explicit vector=. Two ship ready-made: OpenAIEmbedder (fraise-sdk[openai]) and HuggingFaceEmbedder (fraise-sdk[huggingface]); Anthropic has no embeddings API.
Extraction (optional)
Give the client an extractor and remember files each fact under the topics and entities it is about, without you choosing them:
from fraise_sdk import FraiseClient
from fraise_sdk.providers.openai import OpenAIExtractor # needs fraise-sdk[openai]
fraise = FraiseClient("http://localhost:9876", extractor=OpenAIExtractor())
fraise.remember("Anne's flight lands at Lisbon airport") # stored verbatim, anchored for you
An extractor is anything implementing the Extractor ABC (subclass it and define extract(text, context) -> list[Anchor]) or a plain callable(text, context) -> list[Anchor], where an Anchor has a value and a type, "topic" or "entity". Extracted anchors are added after any topics=/entities= you pass, without repeating one you gave, and the text itself is never rewritten. If extraction fails, the fact is stored anyway under the anchors you gave, with a FraiseWarning. Per call, extract=True requires an extractor and extract=False skips it. OpenAIExtractor (gpt-5-mini by default) uses the same instructions the published benchmark ingests with.
The context is what the fact's graph already holds: its three latest facts (recent), and the fifty anchors extraction has filed most often there (vocabulary). It lets the extractor file "she" under the person a nearby message named, and a recurring subject under the anchor it already has, so related facts share the anchors the graph walk follows. The client keeps one context per graph, for as long as it lives.
OpenAI Agents tools
memory_tools(client) returns two FunctionTools, recall_memory and remember_fact, bound to one memory graph, so the agent decides what to store and retrieve:
from agents import Agent, Runner
from fraise_sdk import FraiseClient
from fraise_sdk.integrations.openai_agents import memory_tools
fraise = FraiseClient("http://localhost:9876")
agent = Agent(
name="Assistant",
instructions="Remember durable facts the user shares, and recall them when relevant.",
tools=memory_tools(fraise),
)
result = Runner.run_sync(agent, "My favourite colour is orange. Remember that.")
print(result.final_output)
Pass an embedder — memory_tools(fraise, embedder=OpenAIEmbedder()) — to make the tools vectorise implicitly: recall and remember encode their text through it and carry the vector alongside.
See examples/openai-agents/ for a complete, Docker-runnable script.
Claude Agent SDK tools
The Claude Agent SDK groups tools into an in-process MCP server, so the entry point is memory_server(client); pair it with allowed_tools():
from claude_agent_sdk import ClaudeAgentOptions, ClaudeSDKClient
from fraise_sdk import FraiseClient
from fraise_sdk.integrations.claude_agents import memory_server, allowed_tools
fraise = FraiseClient("http://localhost:9876")
options = ClaudeAgentOptions(
system_prompt="Remember durable facts the user shares, and recall them when relevant.",
mcp_servers={"fraise_memory": memory_server(fraise)},
allowed_tools=allowed_tools(),
)
memory_server(fraise, embedder=OpenAIEmbedder()) makes the tools vectorise implicitly, exactly as in the OpenAI integration.
See examples/claude-agent-sdk/ for a complete, Docker-runnable script.
Notes & limits
- A fact value is stored inside a single-quoted phrase where every character is literal; the SDK escapes apostrophes for you, so
remember("it's blue")stores the text exactly as written. - Keywords, topics, and entities may contain spaces and punctuation: a value that is not one plain word (letters and digits only) is quoted for you, and so is a keyword that spells a reserved word.
- The first vector written to a graph fixes that graph's embedding dimension; later writes to the same graph must match it.
FraiseClientdefaults to a 30s request timeout (timeout=on the constructor or on individualquery/remember/recall/explaincalls overrides it); a request that exceeds it raisesFraiseErrornaming the timeout, distinct from the error raised when the server can't be reached at all.
Metadata
Release files for fraise-sdk 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| fraise_sdk-0.3.0.tar.gz | 29.7 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| fraise_sdk-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 75.9 kB
Release files / fraise_sdk-0.3.0.tar.gz
| Download URL | fraise_sdk-0.3.0.tar.gz |
|---|---|
| Size | 29.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
19253eb51649e92c55c9c792ef791758e6b083a91eafec0e9f2b9f2835273882
|
|
BLAKE2b-256 checksum How to use checksums |
ac0fdc659f16582e60f408c08c6e2d0b64359c238b1d4718a26a2bba5bb2b6a6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.24 {"installer":{"name":"uv","version":"0.12.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / fraise_sdk-0.3.0-py3-none-any.whl
| Download URL | fraise_sdk-0.3.0-py3-none-any.whl |
|---|---|
| Size | 46.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e8e86527ac765e9addb9e8b2d3ec17df9d48f6abb796c2f5e7b99d8954703843
|
|
BLAKE2b-256 checksum How to use checksums |
364769039571e1402bee2969c53a52f74e02e6df6c3f3f0bfc61825fbff1af22
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.24 {"installer":{"name":"uv","version":"0.12.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for fraise-sdk 0.3.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.