v0.2.21
asheshgoplani/agent-deckv0.2.21Sep 9, 2026by het0814
Upgrading?
AI Summary
Introduces client-identity tracking and activity logging, allowing MEMANTO to attribute memory operations to specific AI tools and visualize sessions in the UI.
Key Highlights
- Tool identity and append-only activity tracking
- New session and liveness API endpoints
- Live context mesh and session timeline in the Web UI
- Hidden `--tool` flag for read operations
New Features
- Client identity detection via headers and environment
- ActivityService for logging memory operations
- Session API returning live tool counts
- UI update for Connections page with live context mesh
Full Release Notes
# Release Notes for v0.2.21
This release makes MEMANTO aware of *which* AI tool is talking to it. A new client-identity layer and append-only activity log record the tool and MEMANTO session behind every remember, recall, and answer, and the Connections page grows a live context mesh and session timeline built on top of them. Alongside it, `recall`/`answer` gain a `--tool` flag so agents can name themselves on reads, the MCP server attributes tool calls to its handshake client, connect templates embed each agent's own slug, and packaging moves to PyPI Trusted Publishing with a trimmed sdist.
## New Features
- **Tool identity and activity tracking** (`memanto/app/utils/client_identity.py`, `memanto/app/services/activity_service.py`)
- New `client_identity` module resolves the calling tool from, in order: `MEMANTO_CLIENT` / `X-Memanto-Client`, an MCP `initialize` handshake's `clientInfo`, or environment markers specific to a single tool (`CLAUDECODE`, `CURSOR_TRACE_ID`, `CODEX_HOME`, `WINDSURF_HOME`, `GEMINI_CLI`, `GOOSE_PROVIDER`, `OPENCODE`, `CLINE_SESSION_ID`, `CONTINUE_GLOBAL_DIR`, `PI_AGENT`, `ANTIGRAVITY_HOME`). Detection is conservative — an unidentified caller stays `unknown` rather than being guessed at.
- Free-text client names are folded onto registry slugs via an alias table, so a Cursor MCP write and a Cursor CLI write land on the same connection instead of two lookalike rows.
- New `ActivityService` writes one `O_APPEND` JSON line per memory operation (`remember`, `recall`, `answer`) recording tool, agent, MEMANTO session, and count. Logging is best-effort and never raises — a telemetry line is never worth failing a durable write over. Files older than `RETENTION_DAYS` (30) are pruned once per process.
- Liveness is derived on read: a tool that touched memory within `LIVE_WINDOW_SECONDS` (300) counts as connected now.
- Identity is bound per-request via a `ContextVar` (not a module global) so concurrent API requests cannot read each other's attribution.
- **Session and liveness API** (`memanto/app/ui/routes/ui_router.py`, `memanto/app/main.py`)
- `GET /api/ui/sessions` returns MEMANTO sessions with the tools that took part, per-tool liveness, and a `live_count`. Complements `/api/ui/connections`, which reports where MEMANTO is *installed*; this reports what has actually been running.
- `GET /api/ui/sessions/{session_id}` returns one session's summary plus its full event timeline, `404`-ing on an unknown id.
- Both clamp the `days` window to `ACTIVITY_MAX_DAYS` (30), matching the log's own retention.
- New `attribute_calling_tool` HTTP middleware binds `X-Memanto-Client` (and optional `X-Memanto-Project`) to the request. An anonymous HTTP call is bound to `UNKNOWN` rather than falling through to environment detection — otherwise an editor that started `memanto server` would be credited with every request it never made.
- Both endpoints stay local-only behind `_require_local`.
- **Live context mesh and session list in the UI** (`memanto/app/ui/static/index.html`)
- The Connections page now renders a live context mesh: a MEMANTO hub with one node per tool active in the last 7 days, live nodes and edges highlighted, and a live-count readout. The hub animates only when a tool is genuinely live, and respects `prefers-reduced-motion`.
- A collapsible **Sessions (last 7 days)** list shows each MEMANTO session, its status, and the tools that took part, expanding into a per-session event timeline.
- Live badges decorate the existing connection cards, and the mesh polls on an interval so a stale page stops claiming a tool is connected.
- **`--tool` flag on `recall` and `answer`** (`memanto/cli/commands/memory.py`)
- Reads carry no `--source`, so a new hidden `--tool` option lets an agent name itself exactly instead of relying on environment sniffing — the only way tools that leave no distinctive marker can be attributed at all. Hidden from `--help` because a human running `memanto` by hand has nothing to declare.
- `remember --source` now defaults to the detected calling tool instead of the hardcoded `"user"`; an explicit `--source` always wins, and a bare terminal still records `user`.
- Sources that name a person (`user`, `agent`, `human`) fall through to environment detection rather than putting "user" on the connected-tools diagram.
## Improvements
- **MCP tool calls are attributed to the handshake client** (`integrations/mcp/memanto_mcp/tools.py`)
- New `_attributed(ctx)` context manager binds the MCP `clientInfo` name for the duration of a tool call. The MCP server runs as its own process, so its environment says nothing about the driving editor — this is the only way a recall through MCP gets credited to Cursor rather than to an anonymous caller.
- `recall`, `recall_recent`, `recall_as_of`, `recall_changed_since`, and `answer` now accept `ctx`; `remember` and `batch_remember` were rewrapped to run their whole body under the attribution scope.
- **Activity logging wired through every read and write path** (`memanto/app/services/memory_read_service.py`, `memanto/app/services/memory_write_service.py`, `memanto/cli/client/direct_client.py`, `memanto/cli/client/sdk_client.py`, `memanto/app/routes/auth_deps.py`)
- Semantic recall, `--recent`, `--as-of`, `--changed-since`, `answer`, single `remember`, and `batch_remember` all emit an activity event.
- `get_current_session` and the CLI clients' `_get_validated_session_for_agent` bind the session id, since the memory services below them only ever receive an `agent_id`.
- The CLI `answer` RAG path calls Moorcheh directly rather than through `MemoryReadService`, so it logs its own event — otherwise `answer` would be the one memory operation leaving no trace.
- Generated instructions and `SKILL.md` now interpolate the connected agent's real slug into `--source "<slug>"` and `--tool "<slug>"` examples, instead of a generic `<your_agent_name>` placeholder. `_install_skill` passes `agent.name` through to `get_skill_content`.
- Recall/answer examples and the recall trigger matrix were updated to always pass `--tool`, with a new anti-pattern entry explaining why reads need it.
- **Packaging and publishing** (`pyproject.toml`, `.github/workflows/publish.yml`)
- PyPI publishing moved to Trusted Publishing: `PYPI_API_TOKEN` is gone, `id-token: write` added, and the workflow's OIDC identity is what PyPI authenticates — the action attaches PEP 740 provenance attestations by default.
- New `[tool.hatch.build.targets.sdist]` include list trims the sdist to `memanto/`, `tests/`, and build metadata; `assets/`, `examples/`, `integrations/`, `docs/`, and `sdks/` (whose demo GIFs and architecture PNGs dominated the archive) are excluded.
- Classifier bumped from `3 - Alpha` to `5 - Production/Stable`, Python 3.13 added, and project URLs repointed to `memanto.ai` / `docs.memanto.ai`.
## Tests
- `tests/test_tool_sessions.py` — new 500-line suite covering environment detection precedence, alias normalization, append-only event writing, failure-swallowing on broken storage, session grouping, liveness expiry, quiet-but-unexpired and zero-activity sessions, dead-session flooding, torn-line recovery, session timelines, HTTP header attribution, anonymous-caller safety, and the `--tool` flag on `recall`/`answer`.
- `tests/test_cli.py` — `remember` attributes the write to the calling tool, and an explicit `--source` overrides detection.
- `tests/test_connect_engine.py` — each connected agent gets its own slug in both its instructions and its installed `SKILL.md`.
- `tests/test_remaining_ui_auth.py` — both new session endpoints are rejected from remote callers.
- `tests/conftest.py` — new autouse fixture resets the bound client identity and session between tests, so one test's `--tool` cannot decide the attribution of every test after it.
## Full Changelog
Full Changelog: https://github.com/moorcheh-ai/memanto/compare/v0.2.20...v0.2.21Related Repositories
ollama/ollama★ 184,229
Get up and running with Kimi, GLM, MiniMax, DeepSeek, gpt-oss, Qwen, Gemma and other models.
fatedier/frp★ 110,060
A fast reverse proxy to help you expose a local server behind a NAT or firewall to the internet.
infiniflow/ragflow★ 92,627
RAGFlow is a leading open-source Retrieval-Augmented Generation (RAG) engine that fuses cutting-edge RAG with Agent capabilities to create a superior context layer for LLMs
gohugoio/hugo★ 90,197
The world’s fastest framework for building websites.
junegunn/fzf★ 83,716
:cherry_blossom: A command-line fuzzy finder