Skip to main content

adk-flair — Flair memory backend for Google ADK

Flair is the open-source memory + identity layer for agents. adk-flair makes Flair the durable memory backend for Google ADK agents — self-hosted, federated, portable to your non-ADK agents.

Drop-in for ADK's InMemoryMemoryService. The same memories your ADK agent writes are then visible to every other Flair-enabled harness:

  • Claude Code / Gemini CLI / Codex CLI (via @tpsdev-ai/flair-mcp)
  • Hermes (via hermes-flair)
  • OpenClaw (via @tpsdev-ai/openclaw-flair)
  • n8n (via @tpsdev-ai/n8n-nodes-flair)
  • LangGraph (via @tpsdev-ai/langgraph-flair)

Why Flair underneath ADK

Vertex AI Memory Bank is the managed memory.load(userId) — the assumption we position against. ADK's memory layer is a designed third-party seam (BaseMemoryService + a documented services.py/services.yaml scheme registry), and Google's maintainers have ruled that non-Google backends live outside core. adk-flair makes the pitch concrete: run your agent on Google's stack, keep your memory yours — self-hosted, federated, portable. Consolidation belongs to the memory, not the vendor.

Quickstart

# 1. Install Flair
npm i -g @tpsdev-ai/flair
flair init

# 2. Provision an Ed25519 identity for your ADK app
flair agent add my-adk-app
# → writes ~/.flair/keys/my-adk-app.key

# 3. Install adk-flair (litellm powers the Gemini model in the example)
pip install adk-flair litellm

# 4. Set environment variables
export FLAIR_URL=http://localhost:19926
export FLAIR_AGENT_ID=my-adk-app
export FLAIR_KEYFILE=$HOME/.flair/keys/my-adk-app.key
export GOOGLE_API_KEY=...   # or GEMINI_API_KEY, to run the agent

# 5. Use in your agent
#    from adk_flair import FlairMemoryService
#    memory_service = FlairMemoryService()
#    agent = LlmAgent(..., memory_service=memory_service)

# 6. Or via the CLI / dev UI (requires services.py — see below)
adk web --memory_service_uri="flair://localhost:19926"

Run it end to end

A complete, copy-paste-runnable demo lives at examples/quickstart.py. After the steps above:

python examples/quickstart.py

It plants a fact in session 1, waits for Flair to make it searchable, then asks for it back in a fresh session 2 and prints whether the fact was recalled.

Configuration

Setting Env var Default Notes
Server URL FLAIR_URL http://localhost:19926 Must be localhost unless opt-in (below)
Agent ID FLAIR_AGENT_ID (required) Must match flair agent add <id>
Private key path FLAIR_KEYFILE (required) Keyfile from flair agent add (raw seed; base64/PEM also accepted). A leading ~ is expanded.
Allow remote URL FLAIR_ALLOW_REMOTE_URL (unset) Set to 1 to allow non-localhost URLs

All settings can also be passed as constructor arguments:

FlairMemoryService(
    url="http://localhost:19926",
    agent_id="my-adk-app",
    keyfile="/home/agent/.flair/keys/my-adk-app.key",
)

Explicit durability and visibility (opt-in)

The add_memory() method accepts optional durability and visibility keyword args that let application code control how memories persist and who can read them:

await memory_service.add_memory(
    app_name="my-app",
    user_id="user-123",
    memories=[...],
    durability="persistent",     # permanent | persistent | standard | ephemeral
    visibility="shared",         # private | shared
)
  • Omitted (default) -> durability=standard, no visibility key in the POST body. The server applies its durability-keyed default (standard/ephemeral -> private, permanent/persistent -> shared).
  • Supplied -> included in the POST body verbatim. The server still validates against the allowed enum values (same set: permanent, persistent, standard, ephemeral for durability; private, shared for visibility).

These knobs are a trust-anchor opt-in: application code sets them, not the LLM. If your adapter wraps add_memory() in an LLM-callable tool, fix the durability/visibility flags in the wrapper -- the model should never choose them.

services.py registration

To use adk-flair via the flair:// URI scheme (CLI, dev UI, eval harness), add a services.py to your agent directory:

from adk_flair import register
register()

Or use services.yaml:

services:
  - scheme: flair
    type: memory
    class: adk_flair.memory_service.FlairMemoryService

Then:

adk web --memory_service_uri="flair://localhost:19926"

Remote Flair URLs

By default, adk-flair only allows localhost URLs (localhost, 127.0.0.1, ::1, [::1]). This prevents a typo'd FLAIR_URL from silently shipping every user query to a stranger.

To connect to a remote Flair instance, set FLAIR_ALLOW_REMOTE_URL=1:

export FLAIR_ALLOW_REMOTE_URL=1
export FLAIR_URL=https://flair.example.com:19926

The resolved URL is logged once at WARNING on the first request.

Security

Per-user isolation

All users of one ADK app share one Flair principal. Per-user isolation is enforced by tag-based server-side filtering, not cryptographic key separation. A bug in that filter would leak cross-user memories. For key-level isolation, use per-org Flair principals (the org layer).

Tag encoding

The compound scope tag uses : as a delimiter (adk:<app_name>:<user_id>). Reserved characters (:, _, %) are percent-encoded so distinct inputs never collide: user_id = "alice:admin"alice%3Aadmin (not alice_admin). This is a reversible, collision-free encoding.

Key safety

The Ed25519 private key never leaves the host. Only signed requests cross the wire. The keyfile is parsed and validated in the constructor — a missing or invalid key raises ValueError immediately, never deferring the failure to first use (where ADK's exception-swallowing search path would turn it into permanent silent empty recall).

URL safety

Non-localhost URLs refuse to construct unless FLAIR_ALLOW_REMOTE_URL=1 is set. The error message names the exact URL it refused. This is a control, not just documentation — a typo'd FLAIR_URL cannot silently exfiltrate queries.

Timeouts

The search path has a 2s total budget covering the full lifecycle including DNS:

  • Connect: 0.5s
  • Read: 1.5s
  • Write: 1.0s
  • Pool: 0.5s

One attempt, no retry on the turn path. A hung Flair will never add seconds to every turn. Write paths use the same timeout budget and log structured warnings on failure (session id, event count, HTTP status).

Scope mapping

ADK scopes everything by {app_name, user_id}. Flair's model is agentId-keyed. The adapter bridges this with a compound tagadk:<app_name>:<user_id> — on every record, filtered on every search.

  • user_id is mandatory in the search path — missing/empty returns empty, never searches unscoped.
  • The adapter re-verifies the compound tag on every search hit before mapping it out — defense-in-depth against filter bypass.
  • user_id comes from ADK's session context, never from caller-supplied input.

MemoryEntry mapping

Search hits are mapped to ADK's MemoryEntry type:

MemoryEntry(
    id=record["id"],
    content=types.Content(role="model", parts=[types.Part(text=record["content"])]),
    author=record.get("author"),
    timestamp=record.get("createdAt"),  # ISO 8601
)

Idempotent writes

Record ids are deterministic: {app_name}:{user_id}:{session_id}:{event.id}. Re-ingestion upserts the same record, statelessly. Flair's REM consolidates content; it never sees duplicates.

custom_metadata

custom_metadata keys are not supported by adk-flair. Passing unsupported keys logs a warning once per session — a user setting TTL must not believe it worked.

What this adapter deliberately doesn't do

  • No consolidation logic. Flair's REM (nightly) owns consolidation — the adapter stays small.
  • No retrieve_profiles parity. Phase 2.
  • No TTL/revision semantics. Phase 2.
  • No per-user Flair principals. One Flair agent per ADK app. Per-user principals are key sprawl at user cardinality.
  • No Flair server changes. This adapter works against any existing Flair deployment.

License

Apache 2.0 — same as Flair and Google ADK.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

adk_flair-0.46.0.tar.gz (14.3 kB view details)

Uploaded Source

Built Distribution

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

adk_flair-0.46.0-py3-none-any.whl (13.6 kB view details)

Uploaded Python 3

File details

Details for the file adk_flair-0.46.0.tar.gz.

File metadata

  • Download URL: adk_flair-0.46.0.tar.gz
  • Upload date:
  • Size: 14.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for adk_flair-0.46.0.tar.gz
Algorithm Hash digest
SHA256 2da5a38c563773437e6a74876a3d352e8e49061d569257d08b031fb219b29bf1
MD5 f6d235ae3d845ba07efbd29bb929ae7e
BLAKE2b-256 7e7f2b3963fa592b412a6ff672c719547cfc694582cc9f8154a8ca41d40f23f6

See more details on using hashes here.

Provenance

The following attestation bundles were made for adk_flair-0.46.0.tar.gz:

Publisher: adk-flair-publish.yml on tpsdev-ai/flair

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file adk_flair-0.46.0-py3-none-any.whl.

File metadata

  • Download URL: adk_flair-0.46.0-py3-none-any.whl
  • Upload date:
  • Size: 13.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for adk_flair-0.46.0-py3-none-any.whl
Algorithm Hash digest
SHA256 cf3e26d708d2f571e71eef73b1efddfc0748f2390f8d60f6190a2887e04519bd
MD5 afba62e92af81e11fdd6f9521171369d
BLAKE2b-256 a354ac2778753666ab7cfbd19564c7b3de81bda9bee5fe00a39df3b2c33b03cd

See more details on using hashes here.

Provenance

The following attestation bundles were made for adk_flair-0.46.0-py3-none-any.whl:

Publisher: adk-flair-publish.yml on tpsdev-ai/flair

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.51.1

2 files

0.51.0

2 files

0.50.0

2 files

0.49.0

2 files

0.48.0

2 files

0.47.1

2 files

0.47.0

2 files

This release

0.46.0 This release

2 files

0.45.0

2 files

0.44.13

2 files

0.44.12

2 files

0.44.11

2 files

0.44.10

2 files

0.44.9

2 files

0.44.8

2 files

0.44.7

2 files

0.44.6

2 files

0.44.5

2 files

0.44.3

2 files

0.39.0

2 files

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