Skip to main content

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.
  • FraiseClient defaults to a 30s request timeout (timeout= on the constructor or on individual query/remember/recall/explain calls overrides it); a request that exceeds it raises FraiseError naming 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)

Source distribution for fraise-sdk 0.3.0
File Size Uploaded Provenance
fraise_sdk-0.3.0.tar.gz 29.7 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for fraise-sdk 0.3.0
File Interpreter ABI Platform
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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page