Open-source project
halofyai/halofy avatar
halofyai/halofy

Halofy: a server-owned identity and policy layer for AI agents, built on Postgres

Halofy is the open access and governance layer for AI agents across your organization. Identity, policy, provenance, audit, and signed erasure.

425 stars33 forksTypeScriptAGPL-3.0

At a glance

What is it?
Halofy puts namespace ACLs, provenance, append-only audit and signed erasure in front of agent memory, exposing it over MCP and HTTP. The design is sound for multi-tenant agent fleets, but the project is young, AGPL-3.0 licensed, and its retrieval boundary is deliberately read-only.
Who is it for?
Adopt Halofy if you run multiple agents against shared organizational context and need one server-resolved identity, ACL and audit path rather than a separate policy stack per agent. Do not adopt it if you only need a local vector store or a single-user assistant with no tenancy boundary.
Can I use it commercially?
Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem Halofy targets: agents that each become their own identity system

The README states the problem directly: as AI spreads across an organization, every agent needs shared context without becoming its own identity system, policy engine, or audit silo. That is a real failure pattern. A support agent, a sales agent and an internal research agent each end up with their own credential store, their own notion of who is asking, and their own log file. When someone asks which agent read a customer record last Tuesday, there is no single place to look.

Halofy's answer is to sit between organizational knowledge and the agents that consume it, and to own four things: identity resolution, access enforcement, change governance, and outcome recording. The intended user is a platform or infrastructure team running more than one agent against shared data, on infrastructure they can self-host and run offline. The README describes the result as infrastructure you can inspect, self-host, run offline, and connect to any agent over MCP or HTTP. Single-user assistants and one-off scripts are not the audience.

Identity comes from the credential, not the request body

The first architectural boundary is the one that matters most: namespace, actor, role and source scope come from the credential, never from a request body. The MCP tool schemas do not accept caller-asserted identity fields at all, so an agent cannot claim to be someone else by passing a field. A key is minted with a namespace, an actor and a role:

npx tsx src/cli.ts keygen org/support/agent-1 user:dana owner

That key is then supplied as HALOMEM_API_KEY when the MCP server starts. The README gives the example HALOMEM_API_KEY=hm_... npm run mcp. Everything downstream resolves from that string.

The namespace rule is deliberately small. A caller in namespace N sees rows belonging to N or an exact slash-split ancestor of N. Siblings and descendants stay invisible unless an explicit, audited administration path allows a subtree operation. So a caller at org/support/agent-1 can see org and org/support, but not org/sales or org/support/agent-2. This is a prefix rule with no wildcards and no implicit inheritance downward, which is easy to reason about and easy to get wrong when your team naming does not nest the way you assumed.

The mem_* surface and the governed write path

Agents interact through a fixed set of operations exposed over both MCP and HTTP: mem_write, mem_read, mem_search, mem_assemble, mem_fault, mem_stats, mem_forget, plus policy, sharing, pinning, export and manifest operations. The naming is consistent enough that the pipeline is legible from the tool list alone. mem_assemble builds a working set, mem_fault pages missing context in from a colder tier, mem_forget erases.

Writes are the interesting part. The README describes a governed context lifecycle with provenance, entity resolution, exact and semantic dedupe, supersedence chains and append-only audit. Corrections close the prior fact's validity interval and link the replacement rather than overwriting history. That is a bitemporal-shaped model, and it is the reason the audit trail can be trusted: nothing is mutated in place.

Reads are delegated. A retriever sees only an ACL-scoped ScopedView and can return references only. It cannot write, and it cannot reach audit or storage modules. This is the strongest design decision in the repository. Retrieval engines are swappable precisely because they are powerless.

Two tiers, and Postgres as the single authority

Context, embeddings, policy, provenance, tombstones and audit all live together in Postgres, with pgvector for the vector side. PGlite embeds the same model for local development and tests, which is why the demo can boot with no database server and no network call. The cold tier is described as encrypted, Git-versioned knowledge, which is an unusual choice: it means the cold store inherits Git's history model rather than a database's, and it means cold-tier reads depend on Git being reachable and decryptable.

The README claims the two tiers sit under one organizational authority. Whether that holds in practice depends on how the cold tier is mounted and encrypted, and the README does not spell out the encryption key management. That is a gap worth closing before a production deployment. The four public connectors (filesystem, Postgres, Obsidian, manual CSV import) all feed the same governed write path, so provenance is uniform regardless of source.

Getting it running: the offline demo, the test lane, and the control room

The quickstart is unusually complete for a project at this stage. Clone, then:

cd halofy/kernel npm ci npm run demo

The README states the demo needs no API key, no database server, no model download and no network call. It boots the kernel on embedded PGlite and exercises pinning, assembly, writes, hybrid search, an L3 context fault, audit, import, fragmentation and signed erasure. The sample output shows embedder=hash(dim=256) and llm=stub, which tells you the demo runs against deterministic substitutes rather than a real model.

Verification is two commands: npm test, and npx tsx src/cli.ts conformance baseline. The README reports 2,678 tests across 205 files and 6/6 driver-conformance checks, and notes that timings and generated identifiers vary by machine. Treat those numbers as the project's own claim, not an independent measurement.

For a live server, npm run serve, then open http://localhost:8787/console/login. The control room is described as frameworkless and covers access, teams, sources, policies, conflicts, retrieval quality, audit, alerts, skills, connected apps and export. A durable self-hosted deployment with Postgres, generated keys and Docker Compose is documented in docs/self-hosting.md. The hermetic test lane uses embedded PGlite, a deterministic StubLlm, a HashEmbedder and zero network access, which is what makes the conformance claim reproducible on a laptop.

Where Halofy is the wrong tool, and what to use instead

Halofy is the wrong tool when you have one agent and one user. The identity layer, the ACL tree, the provenance chain and the audit log all cost you configuration and operational surface, and with a single principal there is nothing to isolate. A plain Postgres table with pgvector, or a hosted retrieval API, will get you further with less to run.

It is also the wrong tool if you want the retrieval engine to be smart. The ScopedView contract is intentionally narrow: references only, no writes, no access to storage or audit. If your design depends on a retriever that rewrites or enriches stored memory, Halofy's boundary forbids it. That is the point of the boundary, but it is a real constraint.

A concrete alternative in approach is Mem0 or Zep-style memory services, which treat memory as a managed retrieval product: you send text, you get back relevant memories, and tenancy and audit are secondary concerns handled per integration. Halofy inverts the priority. Postgres is the authority and retrieval is a replaceable, read-only plug-in behind an ACL. The trade is that Halofy asks you to run and operate a database and a governance model, while a managed memory API asks you to trust someone else's. The README's own framing, that retrieval engines plug in through an ACL-scoped, read-only driver interface, is exactly the difference. If you need a retrieval feature Halofy's driver contract does not expose, you are extending the kernel, not configuring it.

Licence, maintenance and what to verify first

Halofy is AGPL-3.0-or-later. That matters more here than for a library, because the AGPL's network clause attaches to software users interact with over a network, and Halofy is explicitly a server you expose over MCP and HTTP. If you modify the kernel and let external users reach it, the licence's terms are likely to reach your changes. This is not legal advice; get counsel to review your deployment shape before you fork the kernel for internal use.

The repository shows no retrieved releases, so there is no tagged version to pin against. You would be tracking the main branch, and the README's own verification numbers describe a moving target. Budget for reading diffs rather than upgrading between versions. The last push recorded is 2026-09-10 and the project is not archived.

Before adopting, verify three things. First, that the exact slash-split ancestor rule matches your namespace design; run the keygen command with your real hierarchy and check what a sibling key can see. Second, that the cold-tier encryption and Git-versioning story in docs/architecture.md is one you can operate. Third, that the driver-conformance baseline passes on your hardware, since the README states timings vary by machine even though behavior does not.

Editorial conclusion

Adopt Halofy if you run multiple agents against shared organizational context and need one server-resolved identity, ACL and audit path rather than a separate policy stack per agent. Do not adopt it if you only need a local vector store or a single-user assistant with no tenancy boundary. Before committing, read docs/architecture.md and docs/self-hosting.md, run npm run demo and npx tsx src/cli.ts conformance baseline in kernel/, and confirm the namespace rule (a caller in namespace N sees N or an exact /-split ancestor) matches how your teams are actually named, because that rule is the whole isolation model.

Official sources

  1. halofyai/halofy on GitHub
  2. Issues
  3. License: AGPL-3.0
  4. Project website
  5. README
Community notes

Community notes