titen
Health Warn
- License — License: Apache-2.0
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 8 GitHub stars
Code Pass
- Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Pass
- Permissions — No dangerous permissions requested
No AI report is available for this listing yet.
Lightweight Level 6 collaborative memory fabric for AI agents
Titen
The Level 6 collaborative memory fabric for AI agents.
Evidence-grounded recall, coordinated work, and governed sharing on infrastructure you control.
Website · Documentation · npm · Changelog
Built with C.A.D.I.S Agent.
Memory for a team, not a chatbot
A storage-only memory saves text. A retrieval-only memory embeds it and returns
nearby passages. Both leave the caller to decide what is current, permitted, or
true, and neither stops two agents from quietly claiming the same work.
Titen's Level 5 kernel turns source observations into evidence-linked, temporal
claims and compiles only the context a caller is allowed to see. Level 6 joins
that kernel to checkpoints, leases, handoffs, governance, audit, and signed
federation.
Level 6 = evidence-grounded context + coordinated work + governance
| Memory model | What it can do | Where it stops |
|---|---|---|
| Logs and files | Keep past text | The caller must decide what is current, trusted, and relevant |
| Vector recall | Find semantically similar passages | Similarity does not prove provenance, permission, or truth |
| Titen Level 5 kernel | Compile bounded context from scoped evidence, claims, time, trust, and conflicts | It remembers well, but does not coordinate parallel work by itself |
| Titen Level 6 fabric | Add task ownership, resumable state, handoffs, policy, audit, and federation | Titen records coordination; your agents or orchestrator still choose what runs next |
Level 6 is Titen's product model, not an external certification. The distinction
is observable in the API: memory and collaboration share one authorization,
evidence, and audit boundary.
You author the claims
Titen's default memory model is caller-authored claims. consolidate()
takes statements you wrote, each explicitly linked to a source observation you
already recorded. Titen does not read a transcript and decide on its own what is
worth remembering.
That is deliberate. Every claim has an author, a source, and a scope, which is
what makes provenance, permission, conflict, and audit answerable at all. It is
also a real cost, and it is the honest comparison point: systems that derive
memory from raw dialogue do work Titen hands back to you.
Model-assisted derivation and reflection are implemented and ship in the
package, but they are activation-gated and no candidate model has passed the
gate — the best result on record is 65.56% against a 90% contract threshold.
Treat them as unfinished work with a public gate, not as a feature you can
simply switch on. The roadmap
carries the current evidence.
The questions Titen answers
| Question | Titen's answer |
|---|---|
| Where did this memory come from? | Every claim points back to source observations and keeps its version history. |
| May this agent see it? | Organization, subject, project, workspace, and visibility checks run before retrieval. |
| What if two sources disagree? | Contradictions remain visible until an explicit lifecycle action resolves them. |
| Who is doing the work? | Leases prevent silent double ownership; checkpoints and handoffs make work resumable. |
| Can we audit or move it? | Canonical records live in SQL, with authenticated audit trails and versioned JSONL export/import. |
| Do we need an LLM or vector database? | No. FTS-only Titen is useful on day one; embeddings and model enrichment are opt-in projections. |
Agents connect through authenticated REST, Streamable HTTP MCP, the titen mcp
stdio bridge, or the TypeScript SDK. Titen never treats retrieved memory as an
instruction, and it does not run agent loops.
Project status
Titen is pre-1.0. Per SemVer clause 4,
the public API is not yet stable. Below 1.0.0 the minor slot is the only
breaking-change signal consumers get: 0.5.7 to 0.6.0 may break you, and^0.5.0 does not match 0.6.0. Pin an exact version and read the
changelog before
upgrading.
Where the word stable appears around Titen — the npm latest dist-tag,"channel": "stable" in titen.dev/version.json,
and titen version --check — it names the release channel: a deliberate
release rather than a prerelease on next. It never describes API stability,
and it is not a maturity badge. See
versioning and channels.
The current release includes the memory kernel, REST API, MCP server,
TypeScript SDK, collaboration tools, enterprise governance, signed federation,
and the operator dashboard.
You can run Titen on Bun with SQLite or on Cloudflare Workers with D1. Semantic
retrieval is optional: use sqlite-vec on Bun, or Vectorize and Workers AI on
Cloudflare — verified live only on the maintainer's isolated titen-test-*
stack, which is test production and not general availability
(scope note). Titen runs in your own infrastructure.
Clients. Titen ships a TypeScript/JavaScript SDK, the titen CLI, and a
minimal Python client inclients/python/.
The Python client is one standard-library-only file coveringobserve → consolidate → compile → evidence, with a generic request for every
other route. It is not published to PyPI: install it from a checkout withpip install ./clients/python, or vendor titen.py. There is no client for any
other language — those callers use the authenticated REST API directly, and
every route, scope, and error shape is in the
API reference.
See the maturity matrix
for detailed runtime evidence and remaining gates, or the
changelog for
release history.
Install and connect an agent
The local server needs Bun 1.2 or newer. The website
installer adds Bun when needed, then installs the titen command for your
current user:
curl -fsSL https://titen.dev/install.sh | bash
titen --version
Windows PowerShell:
irm https://titen.dev/install.ps1 | iex
titen --version
You can also run bun add --global titen-memory@latest. npm and pnpm global
installs work when Bun is already on PATH.
1. Create the store
Run this once in the directory where you want titen.db to live:
titen bootstrap --org "My Org"
Save the organization ID, API key, and temporary dashboard password from the
output. Titen stores only their hashes. The dashboard user is owner and must
change its password at first login.
Create a separate revocable key for each agent host. Replace the organization
ID and choose a stable principal name:
titen key create \
--org-id org_replace_me \
--principal agent-codex \
--kind agent \
--scopes "mcp:call,projects:create" \
--trust asserted \
--label codex
mcp:call includes write-capable memory and coordination tools. Do not share
one key across every agent.
2. Start the service
titen serve
Open another shell and check readiness:
curl --fail http://127.0.0.1:8787/readyz
export TITEN_MCP_URL="http://127.0.0.1:8787/mcp"
export TITEN_API_KEY="paste-the-agent-key-here"
Keep the key in your shell, service environment, or secret manager. Never put
it in a repository. If the agent runs in a container or on another machine,127.0.0.1 points at that agent, not the Titen server; use a private HTTPS,
Tailscale, or trusted tunnel URL instead.
3. Connect your agent host
Codex can connect to Titen's HTTP endpoint directly. It stores the environment
variable name, not the key:
codex mcp add titen --url "$TITEN_MCP_URL" \
--bearer-token-env-var TITEN_API_KEY
codex mcp get titen --json
Claude Code can launch the bundled stdio bridge. It inherits the two variables
from the Claude process:
claude mcp add --transport stdio --scope user titen -- titen mcp
claude mcp get titen
OpenClaw services read durable environment values from ~/.openclaw/.env.
Place TITEN_MCP_URL and TITEN_API_KEY there, set the file to mode 600,
then register and probe the remote server:
openclaw mcp set titen \
'{"url":"${TITEN_MCP_URL}","transport":"streamable-http","headers":{"Authorization":"Bearer ${TITEN_API_KEY}"}}'
openclaw gateway restart
openclaw mcp doctor titen --probe
Hermes can launch Titen's bundled stdio bridge. Put the same two variables in~/.hermes/.env, then run:
hermes mcp add titen \
--command titen \
--args mcp \
--env 'TITEN_MCP_URL=${TITEN_MCP_URL}' 'TITEN_API_KEY=${TITEN_API_KEY}'
hermes mcp test titen
Claude Desktop and any other client that supports stdio MCP can use this small
configuration. Start the client from an environment that contains the two
variables above:
{
"mcpServers": {
"titen": {
"command": "titen",
"args": ["mcp"]
}
}
}
The bridge keeps no state. It only forwards newline-delimited MCP messages to
the authenticated HTTP endpoint.
4. Prove the connection
Open the host's MCP status view, or ask the agent:
Resolve this repository from its Git origin, compile relevant Titen context
for the current task, and list the Titen tools you can access.
A healthy connection exposes nine titen_* tools. Titen's handshake tells the
host to compile once when the task or repository scope changes, to treat memory
as untrusted reference data, and never to capture transcripts or secrets.
The agent integration guide adds
Cursor, OpenCode, Windsurf, TRAE, Pi, and plugin installation. The
secure ingress guide
covers Tailscale Serve and Cloudflare Tunnel.
titen version --check is the only networked version check. It readstiten.dev/version.json only when you run it;
Titen does not poll during server or MCP startup.
Optional semantic retrieval
The default install is FTS-only and stays ready with no embedding configuration
at all. Semantic retrieval is all-or-nothing: set one TITEN_EMBED_*
variable and you have opted in, so every variable below must then be valid or
the service fails closed — /readyz returns 503 withchecks.semantic_index: "embedding_configuration_invalid" and no vector query
runs. A Bun vector deployment must also add [email protected].
| Variable | Required | Shipped default | Absent or invalid |
|---|---|---|---|
TITEN_EMBED_BASE_URL |
yes | none | configured_error; must be http:/https: with no credentials, query, or fragment |
TITEN_EMBED_MODEL |
yes | none on Bun; @cf/baai/bge-base-en-v1.5 on Workers |
configured_error |
TITEN_EMBED_DIMS |
yes | none on Bun; 768 on Workers |
configured_error; integer 1–65,536, must equal the index dimension |
TITEN_EMBED_REVISION |
yes | none | configured_error |
TITEN_EMBED_PROFILE |
yes | none | configured_error; exactly one value is accepted per model family |
TITEN_EMBED_MIN_COSINE |
yes | none | configured_error; every operator calibrates this alone |
TITEN_EMBED_API_KEY |
only if the provider needs a bearer token | none | supplying it without the rest still opts in, and then fails closed |
Three of these have no default anywhere and no value can be guessed safely:
TITEN_EMBED_REVISIONis an opaque immutable identifier for the exact
weights behind the endpoint, ≤200 characters. It is not validated for shape —
it is recorded in the stored index fingerprint, so changing it invalidates the
index and forces a rebuild. That is the point: it is how you promise Titen the
vectors already in the store came from the same weights as the next query. A
provider that cannot name an immutable revision should stay FTS-only.TITEN_EMBED_PROFILEselects the query/document input transform, and the
accepted value is forced by the model id. Any model id containingembeddinggemma(case- and punctuation-insensitive) accepts onlyembeddinggemma-retrieval-v1; every other model accepts onlyraw-unit-v1. There is no way to run an EmbeddingGemma model on raw
untransformed input, and no way to apply the EmbeddingGemma prompts to another
model. A mismatch isconfigured_error, not a warning.TITEN_EMBED_MIN_COSINEhas no shipped default. An unset variable
reads as the empty string, which is rejected, so semantic retrieval fails
closed rather than silently accepting weak matches. Titen ships no universal
or pre-inspected threshold: derive it from a locked evaluation of that exact
provider, model, revision, and profile.0is a valid, deliberate value
meaning "accept every candidate the index returns and let ranking decide".
Worked EmbeddingGemma example — an OpenAI-compatible endpoint servingembeddinggemma at 768 dimensions:
bun add titen-memory [email protected]
TITEN_EMBED_BASE_URL=http://127.0.0.1:11434/v1 \
TITEN_EMBED_MODEL=embeddinggemma \
TITEN_EMBED_DIMS=768 \
TITEN_EMBED_REVISION=embeddinggemma-q4-2026-07-31 \
TITEN_EMBED_PROFILE=embeddinggemma-retrieval-v1 \
TITEN_EMBED_MIN_COSINE=0.32 \
bunx titen-memory serve
embeddinggemma-retrieval-v1 is the only profile that model id will accept.embeddinggemma-q4-2026-07-31 is a placeholder: substitute the immutable
revision your provider reports, and treat any change to it as an index rebuild.0.32 is a placeholder too — replace it with your own calibrated floor and
record how you measured it. Verify with curl --fail http://127.0.0.1:8787/readyz;
a healthy vector deployment reports capabilities.vector: "enabled".
The packaged vector path is verified on glibc Linux x64 with Bun 1.3.13; other
platforms need their own ready, drain, and query smoke.
For backups, key rotation, containers, and durable service setup, use the
Bun/VPS deployment guide.
Use the SDK
The SDK uses fetch and runs on Node 22+, Bun, Deno, and edge runtimes.
titen-memory is ESM-only — it has no CommonJS entry — so the consuming
project must be ESM too. npm init -y writes "type": "commonjs", which is why
the second line below is not optional: without it Node fails withSyntaxError: Cannot use import statement outside a module before it reaches
any Titen code.
npm install titen-memory
npm pkg set type=module
Save this as titen-example.js and run node titen-example.js:
import { TitenClient } from "titen-memory";
const titen = new TitenClient({
url: process.env.TITEN_URL ?? "http://127.0.0.1:8787",
key: process.env.TITEN_API_KEY,
});
const subject = "release-runbook";
const observation = await titen.observe({
subject_id: subject,
kind: "imported_source",
content: "The release runbook requires a rollback smoke test after deployment.",
source: { type: "runbook", ref: "ops/release.md" },
trust: "verified",
});
await titen.consolidate(subject, [
{
kind: "procedural",
statement: "Run a rollback smoke test after deployment.",
sources: [
{ observation_id: observation.observation_id, relation: "supports" },
],
},
]);
const context = await titen.compile({
subject_id: subject,
task: "rollback smoke after deployment",
max_tokens: 900,
});
console.log(context.items);
The script needs a running service and a key: start one withtiten bootstrap --org "My Org" and titen serve, then exportTITEN_API_KEY. In TypeScript the same file works unchanged astiten-example.ts on Node 22.18+ or Bun; write process.env.TITEN_API_KEY!
there to satisfy strict null checks. Skipping npm pkg set type=module and
naming the file .mjs/.mts also works — those extensions are ESM regardless
of package.json.
max_tokens accepts 128 through 32,000. Every returned memory item includesuntrusted: true; the client still owns prompt boundaries and action policy.
Python callers useclients/python/,
which is not on PyPI and installs from a checkout. Any other language calls the
REST API in the
API reference
directly.
Typed methods cover common agent operations. request() and requestRaw()
cover the remaining authenticated JSON and streaming routes. Mutations accept
an idempotencyKey for safe retries.
See the agent guide
and API reference
for request contracts and scope rules.
Architecture
One Web-Standards TypeScript core serves both runtimes:
| Capability | Bun / VPS | Cloudflare |
|---|---|---|
| HTTP | Bun.serve |
Worker fetch |
| Canonical SQL | bun:sqlite |
D1 |
| Lexical retrieval | SQLite FTS5 | D1 FTS5 |
| Optional vectors | sqlite-vec |
Vectorize (see the scope note below) |
| Automatic model enrichment | Implemented, opt-in compatible HTTP | Implemented, opt-in compatible HTTP |
| Background work | Startup and bounded timer | Scheduled handler; trigger provisioning varies |
Vectorize scope. Vectorize and Workers AI are implemented and verified live
on titen-test-*, an isolated stack on the maintainer's own Cloudflare account,
with scoped BGE-M3 retrieval, bounded repair, Cron, persistence, and rollback.
That is test production and not a general-availability claim: no customer
deployment runs it, and your account needs its own ready, drain, and query
smoke before you rely on it. Without an AI/Vectorize binding a Worker stays
ready and retrieval is lexical D1 FTS5. The
maturity matrix
holds the exact evidence.
Automatic model-assisted claim derivation and reflection are implemented as an
opt-in capability with durable jobs, bounded validation, and separate
readiness. They are not production-activated: no candidate model has passed the
frozen activation gate, and the locked evaluation and real-runtime smokes are
not recorded. Callers author evidence-linked claims explicitly, as described in
You author the claims.
The base service does not require Docker, Redis, Postgres, a graph database, or
a vector database. Authorization runs before retrieval, and every candidate is
hydrated from canonical SQL before Titen returns it.
Read the architecture overview
for component and failure boundaries. Cloudflare operators should start with
the Cloudflare deployment guide.
Dashboard
The checked-in Astro client at /dashboard/ is a live operator surface for
Memories, Context, Work, Audit, Governance, and Federation. Each person signs
in with a username/password; the loopback adapter keeps the resulting
short-lived key behind an opaque HttpOnly session and never writes either secret
to browser storage. Bootstrap creates owner with a random temporary password,
and Add User follows the same forced-first-change flow. API keys remain for
agents, services, SDKs, and recovery. There is no fixture fallback when the
service is disconnected or denies a request.
The dashboard guide
covers configuration and verification. Use the
secure ingress guide
for private Tailscale Serve access or Cloudflare Tunnel protected by Access.
Documentation
| Read this | For |
|---|---|
| Golden path | A complete small-team example |
| API reference | REST, MCP, errors, and compatibility |
| Architecture | Core, runtime, storage, and policy boundaries |
| Agent integrations | Host-specific MCP and skill setup |
| VPS deployment | Bun, containers, persistence, and hardening |
| Cloudflare deployment | Worker and D1 setup |
| Secure dashboard ingress | Tailscale Serve or Cloudflare Tunnel with Access |
| Roadmap | Evidence-based maturity and planned work |
| Documentation index | Product, engineering, security, and research docs |
Development
The repository requires Node 22+, Bun 1.2+, and pnpm.
git clone https://github.com/RamaAditya49/titen.git
cd titen
pnpm install
pnpm test
pnpm check:workflow
Changes follow spec -> plan -> implement -> done. Read
CONTRIBUTING.md
before changing public behavior, storage, authorization, or runtime contracts.
Security
Keep Titen bound to 127.0.0.1. Remote agents should use a private network or
a trusted TLS reverse proxy. When that proxy exposes /mcp, setTITEN_MCP_ORIGIN to its exact public origin. Use TITEN_SECRET_KEYS as the
external encryption keyring for persisted webhook and federation signing
secrets, and set TITEN_WEBHOOK_ALLOWED_HOSTNAMES before enabling outbound
webhooks. The VPS security guide
defines the formats and rotation procedure.
Do not report vulnerabilities in a public issue. Use
GitHub Private Vulnerability Reporting
and follow SECURITY.md.
Never include real credentials or private memory content in a report.
License
Titen is licensed under the
Apache License 2.0.
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found