Complete reference for AgentDb's four public interfaces: the Elixir AgentDb
module, the mix agent_db.* CLI, MCP tools over Streamable HTTP, and WebSocket
v1.* events. Each section is written against its source of truth so it can
be checked, not taken on faith:
| Interface | Source of truth |
|---|---|
| Elixir API | lib/agent_db/agent_db.ex — rendered at hexdocs.pm/agent_db |
| CLI | lib/mix/tasks/ — each task's @switches |
| MCP | AgentDbWeb.Mcp.tools/0 in lib/agent_db_web/mcp.ex |
| WebSocket | handle_in clauses in lib/agent_db_web/channel.ex |
The generated documentation is the API reference for the Elixir module — this
guide maps entry points to it instead of copying signatures, which would go
stale the moment the code moves. Generate it locally with mix docs.
1. Elixir API (AgentDb module)
Start the application once, then every call below is available:
{:ok, _} = Application.ensure_all_started(:agent_db). Links go to the
versioned generated docs; local mix docs output matches them.
Tree operations
| Entry point | What it does | Docs |
|---|---|---|
AgentDb.write/3 | Writes a document, creating missing parents; acknowledges before embedding/summarization | link |
AgentDb.read/1 | Reads L2 content, falling back through generated layers | link |
AgentDb.abstract/1 | Reads the L0 abstract layer | link |
AgentDb.overview/1 | Reads the L1 overview layer | link |
AgentDb.stored_layers/1 | Which layers exist for a URI | link |
AgentDb.layers/1 | Reads all three layers (L0, L1, L2) in one call, each with source and character count | link |
AgentDb.list/1 | Direct children of a URI | link |
AgentDb.tree/2 | Depth-limited tree projection | link |
AgentDb.rm/1 | Removes the subtree at a URI | link |
AgentDb.find/2 | Literal URI-path discovery with scope: | link |
AgentDb.grep/2 | Literal L2 line matches with excerpts | link |
AgentDb.list_all_documents/2 | Paged listing of the whole tree | link |
Search
| Entry point | What it does | Docs |
|---|---|---|
AgentDb.search/2 | Keyword, vector, or hybrid search; mode:, scope:, top_k:, hybrid_weights:, fields: options | link |
fields: selects which per-result fields are returned: :uri (always
required — a result without its URI cannot be fetched), :content,
:abstract, :overview, :score. Omitted returns all of them, so an
existing caller sees the same result set as before. An unknown name, an empty
list, or a selection without :uri is {:error, {:invalid_fields, value}}
rather than a substituted answer, and the projection reaches the statement
that reads the rows — a caller selecting :abstract does not pay to read
document content it cannot receive.
# URIs and abstracts only, for deciding which documents to read
{:ok, results} = AgentDb.search("vector index", mode: :hybrid, fields: [:uri, :abstract, :score])Memory
| Entry point | What it does | Docs |
|---|---|---|
AgentDb.remember/3 | Stores a durable fact with confidence:, importance:, candidate:, source:; document, assertion, and embedding job land as one outcome | link |
AgentDb.recall/1 | Decay-aware recall with include_superseded:; each entry reports its own type, and a malformed URI is {:error, :invalid_uri} rather than a raise | link |
AgentDb.forget/1 | Removes a memory | link |
AgentDb.promote_memory/1 | Promotes a candidate to durable, carrying its value through the URI's document | link |
AgentDb.reject_memory_candidate/1 | Rejects a candidate | link |
AgentDb.pending_memory_candidates/1 | Candidates awaiting promotion | link |
AgentDb.memory_conflicts/1 | Read-only conflict surfacing | link |
AgentDb.memory_types/0 | The valid memory types | link |
AgentDb.default_confidence/0 | Default confidence for new memories | link |
Sessions
| Entry point | What it does | Docs |
|---|---|---|
AgentDb.create_session/0 | Creates an append-only session | link |
AgentDb.append_message/3 | Appends a message | link |
AgentDb.get_session/1 | Reads every message, in order | link |
AgentDb.commit_session/3 | Commits a session into the tree | link |
Agent Skills
| Entry point | What it does | Docs |
|---|---|---|
AgentDb.import_skills/2 | Imports a skill folder or tar archive | link |
AgentDb.list_skills/1 | Lists imported skills | link |
AgentDb.set_enabled/2 | Enables/disables one skill | link |
AgentDb.set_group/2 | Sets one skill's group | link |
AgentDb.bulk_set_enabled/2 | Bulk enable/disable | link |
AgentDb.bulk_set_group/2 | Bulk group assignment | link |
AgentDb.skill_import_limits/0 | Bounded import limits | link |
AgentDb.skill_import_error_message/1 | Human message for an import refusal | link |
Data portability
| Entry point | What it does | Docs |
|---|---|---|
AgentDb.export_data/2 | Exports store data to a tar archive | link |
AgentDb.import_data/2 | Imports an exported archive | link |
AgentDb.data_transfer_limits/0 | Bounded transfer limits | link |
AgentDb.export_data_error_message/1 | Human message for a transfer failure | link |
Vector index
| Entry point | What it does | Docs |
|---|---|---|
AgentDb.index_coverage/0 | Embedding coverage of the tree | link |
AgentDb.backfill_vector_index/0 | Re-embeds stale rows in the background | link |
AgentDb.prune_vector_index/1 | Drops stale vector rows | link |
Status, observability, and subscriptions
| Entry point | What it does | Docs |
|---|---|---|
AgentDb.health_check/0 | Aggregate readiness for orchestration probes | link |
AgentDb.model_status/0 | Per-role model state, latency, provider health | link |
AgentDb.queue_stats/0 | Queue depth by state | link |
AgentDb.queue_detail/1 | Oldest pending age + failed jobs with classified reasons | link |
AgentDb.operation_stats/0 | Operation counters by outcome | link |
AgentDb.cache_stats/0 | Cache sizes | link |
AgentDb.storage_stats/0 | Storage footprint and tree composition | link |
AgentDb.recent_errors/1 | Bounded recent operational errors | link |
AgentDb.runtime_snapshot/0 | Read-only BEAM runtime snapshot (bounded, redacted) | link |
AgentDb.subscribe/1 | Subscribes a process to {:context_changed, uri, kind, version} | link |
AgentDb.unsubscribe/1 | Unsubscribes | link |
Full signatures, option types with defaults, and every success/error return
shape live in the generated docs (hexdocs link per row, or mix docs).
2. CLI (mix agent_db.*)
Every task takes --json (machine-readable stdout) and --no-compile
(skips the app start). Without --json, output is human text. Failures write
to stderr and exit non-zero; exit code 0 means success.
| Task | Purpose | Switches |
|---|---|---|
mix agent_db.read | Reads a document's full content (L2) | --json, --no-compile |
mix agent_db.abstract | Reads a document's L0 abstract only | --json, --no-compile |
mix agent_db.overview | Reads a document's L1 overview only | --json, --no-compile |
mix agent_db.search | Searches the context tree | --mode, --scope, --top-k, --json, --no-compile |
mix agent_db.find | Discovers paths by literal substring | --scope, --limit, --json, --no-compile |
mix agent_db.grep | Searches document content by literal substring | --scope, --limit, --json, --no-compile |
mix agent_db.tree | Shows the context tree | --depth, --json, --no-compile |
mix agent_db.recall | Reads memories back | --type, --term, --include-superseded, --json, --no-compile |
mix agent_db.index | Indexes Elixir sources into the context tree | --project, --dir, --json, --no-compile |
mix agent_db.import_skills | Imports Agent Skills from a folder or a tar archive | --user, --json, --no-compile |
mix agent_db.export_data | Exports store data to a tar archive | --scope, --json, --no-compile |
mix agent_db.import_data | Imports store data from a tar archive | --json, --no-compile |
mix agent_db.doctor | Checks store health and configuration | --json, --no-compile |
mix agent_db.seed | Seeds a deterministic demo dataset (dev/test only) | --prefix, --force, --clean, --allow-prod, --json, --no-compile |
3. MCP tools (Streamable HTTP at POST /mcp)
The tool set is AgentDbWeb.Mcp.tools/0 — 19 tools. Requests are JSON-RPC
2.0 (tools/call with {"name": ..., "arguments": {...}}).
| Tool | Request arguments (required in bold) | Description |
|---|---|---|
context_read | uri | Reads a document's full content (L2) |
context_abstract | uri | Reads a document's L0 abstract only |
context_overview | uri | Reads a document's L1 overview only |
context_layers | uri | Reads L0, L1, and L2 together, each with its text, source (stored or fallback), and character count |
context_write | uri, content | Writes a document, creating missing parents |
context_rm | uri | Removes the subtree at a URI |
context_list | uri | Lists the direct children of a URI |
context_tree | uri, depth | Depth-limited projection of the tree |
context_search | term, mode, scope, top_k, fields | Searches by keyword, vector, or hybrid; fields selects which per-result fields to return |
context_find | term, scope, limit | Discovers paths by literal substring |
context_grep | term, scope, limit | Inspects L2 content lines by literal substring |
memory_recall | uri, type, term, include_superseded | Reads memories back by URI, type, or term |
memory_remember | uri, value, confidence, source | Records a durable fact as a memory |
memory_forget | uri | Removes a memory and its provenance |
session_create | — | Creates a session and returns its id |
session_append | session_id, role, content | Appends a message to a session |
session_get | session_id | Returns every message of a session, in order |
session_commit | session_id, destination_uri | Commits a session into the tree at a URI |
store_health | — | Store health, model status, and queue depth |
Success response — a JSON-RPC result whose content is the data as JSON:
{"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"{\"content\":\"...\"}"}]}}Error response — a JSON-RPC error; the bounded code rides in
data.reason. A model that is still loading is signalled distinctly as
-32001; every other failure is -32000 with the classified code:
{"jsonrpc":"2.0","id":1,"error":{"code":-32000,"message":"...","data":{"reason":"model_loading"}}}Confirm the live tool list with tools/list (what tools/install.sh --check
asserts against context_read). With Bearer auth enabled, send the token as
Authorization: Bearer <token>.
3.1 Local (sidecar) invocation
When AgentDb is embedded as a sidecar in a host Elixir application, the same
tool inventory is reachable in-process through AgentDb.Mcp, without JSON-RPC
or HTTP:
# Discover the inventory
tools = AgentDb.Mcp.tools()
# Invoke a tool directly
{:ok, %{"uri" => uri, "content" => content}} =
AgentDb.Mcp.call_tool("context_read", %{"uri" => uri})
# Or speak JSON-RPC locally
AgentDb.Mcp.handle_request(%{"jsonrpc" => "2.0", "id" => 1, "method" => "tools/list"}, [])AgentDb.Mcp.call_tool/3 returns {:ok, term()} or {:error, reason}. A tool
deferred only because a model is still loading returns {:error, :model_loading}.
AgentDbWeb.Mcp remains available as a compatibility shim delegating to
AgentDb.Mcp.
4. WebSocket events (Phoenix Channel /api)
Events are {"event": "v1.*", "payload": {...}}. The reply is
{:ok, <payload>} on success and
{:error, %{reason: <message>, code: <classified code>}} on failure. :ok-only
operations reply {:ok, %{status: "ok"}}.
| Event | Payload | Reply payload |
|---|---|---|
v1.write | uri, content (+ opts: async, abstract, overview) | write result |
v1.read | uri | content |
v1.abstract | uri | abstract |
v1.overview | uri | overview |
v1.list | uri | names |
v1.tree | uri, depth (default 2) | tree |
v1.rm | uri | :ok |
v1.search | term + mode/scope/top_k/hybrid_weights in opts | results |
v1.find | term, scope, limit | results |
v1.grep | term, scope, limit | results |
v1.remember | uri, value (+ confidence, importance, type, source) | memory result |
v1.recall | uri/type/term (+ include_superseded) | memories |
v1.forget | uri | :ok |
v1.create_session | — | session_id |
v1.get_session | session_id | messages |
v1.subscribe | uri | :ok |
v1.unsubscribe | uri | :ok |
v1.search_progress | term (as v1.search) | results + progress events |
v1.model_status | — | model status |
v1.health | — | health check |
Pushed events (server-to-client only): v1.append_message and
v1.commit_session are responses to their matching operations, and
v1.context_changed ({uri, kind, version}) is the subscription push.
Subscriptions are per-connection and do not survive a reconnect — re-subscribe after every reconnect.
Trace correlation: a traceparent is accepted as an HTTP header, at the
payload's top level, or inside opts (W3C format).
5. Error code catalog
One bounded taxonomy classifies every failure on every transport. The source
is AgentDb.Observability (classify_reason/1, the caller-error tags, and
the http_status/1 mapping); each code also appears as the log reason and
in transport error payloads.
| Category | Codes | HTTP |
|---|---|---|
| Missing | not_found, no_memory, assertion_not_found | 404 |
| Authorization | unauthorized | 401 |
| Retryable unavailability | model_loading, background_jobs_pending, vector_index_unavailable, storage_busy | 503 |
| Size limits | too_large, too_big, too_many_entries | 413 |
| Rate limiting | rate_limited | 429 |
| Caller errors | invalid_mode, invalid_uri, invalid_query, invalid_limit, invalid_document, invalid_memory, invalid_memory_type, invalid_session, invalid_user_id, invalid_scope, invalid_json, invalid_argument, invalid_payload, invalid_group, not_a_memory_uri, is_root, missing_argument, unknown_event, unknown_tool, unsafe_path, unsupported_entry, unexpected_entry, empty | 422 |
| Model and inference | model_not_found, model_load_failed, download_failed, inference_failed, inference_timeout, hybrid_leg_timeout, hybrid_leg_failed, embeddings_unavailable, no_provider_url, background_jobs_failed | 500 |
| Fallback | error (anything unrecognised) | 500 |
Any tagged reason ({tag, detail}) classifies to its tag, so the set grows
only by reusing or extending these codes — never free-form text.
Where the code appears per transport: Elixir — classify with
Observability.error_code(reason); CLI — stderr message; MCP —
error.data.reason (with -32001 for model_loading); WebSocket —
error.code in the reply payload.
For the operational side (alerting, log interpretation, symptom-driven diagnosis) see MONITORING.md and TROUBLESHOOTING.md.