Agentic Memory
The Agentic Memory server provides a persistent, local-first memory and knowledge management system for AI agents, combining core memory operations, advanced hybrid search, a temporal knowledge graph, multi-agent coordination, skills management, feedback-driven ranking, maintenance, and monitoring.
Core Memory Operations: Save, read, update, delete, restore, supersede, and patch memories with structured Markdown content, categories (lessons, decisions, etc.), tags, importance, and pinning; soft-delete with recovery and hard-delete safeguards.
Advanced Search: Hybrid 14‑phase pipeline merging semantic (embedding), full-text (FTS5), knowledge graph, and fact retrieval; supports temporal filtering, reranking, and click-through feedback to continuously improve relevance.
Knowledge Graph: Explore, traverse, find shortest paths, and retrieve stats for a temporal, contradiction-aware graph with belief tracking, entity extraction, and low‑confidence belief review.
Multi-Agent Coordination: Manage tasks (create, claim, update, release, complete), lock/unlock files, exchange inter-agent messages, and share project state.
Session & Context: Generate structured cold‑start briefings; recall context for session continuity with pinned memories, user profiles, recent digests, and high‑importance items.
Skills Management: Extract skills from memories, list them by usage, and compile lesson notes into validated, executable agent rule files.
Feedback & Reinforcement: Record implicit click-through feedback and explicit success/failure signals to improve future search ranking.
Audit & Revision History: Review recent activity, errors, and full revision logs for supersede, amend, revert, and delete events.
Maintenance & Organization: Safely compact databases, consolidate and deduplicate entries, purge expired data, rewrite links, and curate auto‑saved tool invocations.
Health Monitoring: Multi‑dimensional health dashboard (database, search, workers, crons, auto‑save, disk) with detailed JSON health checks.
Sharing: Share specific memories between agents and manage the shared memory pool.
Advanced & Profiling: Power‑user maintenance escape hatch; view system profiles, agent scopes, Adaptive Resonance Theory (ART/ARC) statistics, and cached skills.
Provides a search tool for CrewAI agents, allowing them to access Agentic Memory's knowledge base.
Provides tools for integrating Agentic Memory with LangChain agents, enabling search and save operations within LangChain workflows.
Supports exporting memories to an Obsidian vault using the Open Knowledge Format (OKF), enabling easy integration with Obsidian note-taking.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Agentic Memory remember that I prefer dark mode"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Agentic Memory
Quick Start · Features · Architecture · MCP Server · SDKs · Comparison · Docs · Contributing
What is Agentic Memory?
Agentic Memory gives AI agents persistent, cross-session, local-first memory — no cloud, no vendor lock-in, no API keys required. Memories are stored as human-readable Markdown files. A derived SQLite index enables fast full-text, semantic, and knowledge-graph search.
Built for Claude Code, OpenCode, the Agentic Memory IDE, and any MCP-compatible agent harness.
graph TD
A[Agentic Memory] --> B[Markdown - source]
A --> C[SQLite FTS5 - derived]
A --> D[14-Phase Search Pipeline]
B --> E[.md files - Git-ready]
C --> F[Temporal Knowledge Graph]
D --> G[CQRS + CRDT Multi-Agent Sync]
A --> H[19 MCP tools]
A --> I[55 cron scripts -> 1 scheduler]
A --> J[9 hooks]
A --> K[Python SDK + TypeScript SDK + REST API]Related MCP server: mem-persistence
Quick Start
Python SDK (Recommended)
from agentic_memory import MemoryClient
mc = MemoryClient()
mc.save("User prefers dark mode", category="preferences")
results = mc.search("dark mode")
for r in results:
print(f"[{r.score:.2f}] {r.content}")Agent Scoping
from agentic_memory import AgentMemory
coder = AgentMemory(agent_id="coder")
coder.save("Frontend uses React with TypeScript")
designer = AgentMemory(agent_id="designer")
designer.save("Brand colors are #FF5733 and #33FF57")MCP Server
# Add to your MCP config
{
"agentic-memory": {
"command": "agentic-memory-server"
}
}REST API
agentic-memory api --port 9879
curl http://localhost:9879/api/v1/search?q=dark+modeFeatures
Search — 14-Phase Hybrid Pipeline
Phase | Technique | Purpose |
1 | Query parsing + expansion | Normalization, reasoning expansion |
2 | Skill-first lookup | Conditional early return on skill match |
3 | Cache check | Return cached results if fresh |
4 | DB setup + filter construction | Open connection, build filters |
5 | FTS5 BM25 + KG facts | Keyword + fact retrieval |
6 | Embedding fallback | Semantic vector search (usearch + model2vec) |
7 | Hybrid fusion (RRF) | Merge sparse + dense results |
8 | Temporal filtering | Decay old memories, exclude outdated |
9 | Chunk enhancement + session clustering | Enrich with sub-document chunks |
10 | KG boost + multi-hop traversal | Concept centrality, graph expansion |
11 | Reranking | Cross-encoder + ColBERT late-interaction |
12 | Build output items | Assemble result objects |
13 | Postprocessing | Safety gates, quality filters, profiling |
14 | Finalization | Access recording, telemetry, envelope |
Each phase is independently isolated — no single failure kills the search.
Write — Crash-Safe, Conflict-Preserving
Saga transactions — Crash-consistent writes with undo/redo
CQRS write journal — Lock-free multi-agent writes via journal.db
CRDT field-level LWWES — Concurrent edits to different fields both win
Safe atomic write — POSIX rename, conflict file preservation
Knowledge Graph — Temporal + Contradiction-Aware
Entity extraction with Jaccard fuzzy matching
Temporal edges with
valid_at/invalid_atContradiction detection and supersession chains
Graph analytics (centrality, community detection)
Neural Forget Curve
Surprise-based retention formula considering access patterns, query relevance, recency, and importance:
retention = sigmoid(w_acc × access + w_surp × surprise + w_imp × importance + w_fit × fitness - w_rec × recency - bias)Cron Consolidation
39 crontab entries replaced with 1 consolidated scheduler that runs every 5 minutes, checks which jobs are due by frequency tier, and runs them sequentially.
System Health Dashboard
memory_system_health MCP tool returns green/yellow/red across 6 dimensions with actionable next steps: database, search, worker, crons, auto-save, disk.
Architecture
agentic-memory/
├── agentic_memory/ # Python SDK (pip installable)
│ ├── client.py # MemoryClient (save/search/CRUD)
│ ├── temporal.py # TemporalKG
│ ├── kg.py # KnowledgeGraph
│ ├── integrations/ # LangChain + CrewAI adapters
│ └── models.py # 8 typed dataclasses
├── search/ # 14-phase search pipeline
│ ├── orchestrator.py # Main pipeline (2,825 LOC)
│ ├── scoring.py # RRF, temporal decay, KG boost
│ ├── rerankers.py # Cross-encoder, ColBERT
│ ├── chunk_index.py # Semantic chunking
│ └── synthesis.py # Answer synthesis
├── save/ # Write path
│ ├── pipeline.py # Saga-wrapped save
│ ├── backlinks.py # Wiki-style backlinks
│ └── post_save_hooks.py # Post-save operations
├── infra/ # Infrastructure
│ ├── db.py # Connection pool + WAL
│ ├── write_journal.py # CQRS write journal
│ ├── embedding_search.py # Semantic embeddings
│ ├── reranker.py # Neural reranker
│ ├── vector_store.py # ANN index abstraction
│ ├── api_server.py # REST + WebSocket
│ └── cache.py # Multi-level caching
├── knowledge_graph/ # KG extraction + search
├── kg/ # Temporal KG + analytics
├── crdt/ # Field-level CRDT merge
├── fact/ # Fact extraction + temporal
├── background/ # Daemon + worker + circuit breaker
├── cron/ # 47+ cron jobs + consolidated scheduler
├── hooks/ # 6 lifecycle hooks
├── migrations/ # 57 reversible migrations
├── eval/ # 363 test files, 5,703+ test functions
├── ts-sdk/ # TypeScript SDK
├── mcp_*.py # 31 MCP modules
├── mcp_health.py # System health MCP tool
└── dashboard.py # Streamlit observabilityProduction stats: ~147K LOC, 365 test files, 5,735+ test functions, schema v76, 77 reversible migrations, 25 CORE MCP tools, 1 consolidated scheduler, 7 lifecycle hooks.
SDKs
Python
pip install agentic-memoryfrom agentic_memory import MemoryClient, AgentMemory, TemporalKG
mc = MemoryClient()
mc.save("Important context", category="lessons")
results = mc.search("context")
stats = mc.stats()TypeScript
npm install @agentic-memory/sdkimport { MemoryClient } from '@agentic-memory/sdk';
const client = new MemoryClient();
await client.add('Important context');
const results = await client.search('context');REST API
agentic-memory api --port 9879curl -X POST http://localhost:9879/api/v1/memories \
-H "Content-Type: application/json" \
-d '{"content": "Important context"}'MCP Server
17 CORE tools always visible to your agent. 95 ADMIN + 3 DEPRECATED behind memory_maintenance(operation="...").
CORE Tools
memory_search memory_save memory_delete
memory_recall memory_note memory_learn
memory_audit memory_organize memory_share
memory_graph memory_profile memory_session_start
memory_advanced memory_review_beliefs memory_curate_autosave
memory_health_check memory_system_healthSetup
{
"agentic-memory": {
"command": "agentic-memory-server",
"env": {
"MEMORY_KNOWLEDGE_GRAPH": "1",
"MEMORY_DB_PATH": "./memory.db"
}
}
}Integrations
LangChain
from agentic_memory.integrations.langchain.tool import search_tool, save_tool
agent = create_react_agent(llm, tools=[search_tool, save_tool])CrewAI
from agentic_memory.integrations.crewai.tool import AgenticMemorySearchTool
agent = Agent(..., tools=[AgenticMemorySearchTool()])OKF (Open Knowledge Format)
mc.okf_export("~/ObsidianVault/agent-memory")Configuration
Install Extras
pip install agentic-memory # Core
pip install agentic-memory[embeddings] # + semantic search
pip install agentic-memory[reranker] # + cross-encoder
pip install agentic-memory[langchain] # + LangChain
pip install agentic-memory[crewai] # + CrewAI
pip install agentic-memory[all] # EverythingKey Environment Variables
Variable | Default | Description |
|
| Database path |
|
| Markdown directory |
|
| Enable KG extraction |
|
| Enable semantic search |
|
| Enable LLM fact extraction |
Comparison
Feature | Agentic Memory | Mem0 | Letta | Zep |
Local-first | Yes | No | No | No |
MCP-native | 17 CORE tools | No | No | 1 tool |
14-phase search | Yes | No | No | No |
Temporal KG | Yes | Partial | No | Yes |
CRDT sync | Field-level | No | No | No |
CQRS journal | Yes | No | No | No |
Neural forget | Yes | No | No | No |
Python SDK | Yes | Yes | Yes | Yes |
TypeScript SDK | Yes | Yes | Yes | Yes |
LangChain | Yes | Yes | Yes | Yes |
CrewAI | Yes | Yes | Yes | No |
OKF support | Yes | No | No | No |
Test coverage | 5,703+ tests | ~500 | ~2,000 | ~300 |
License | Apache 2.0 | Apache 2.0 | Apache 2.0 | Apache 2.0 |
Documentation
Section | Description |
Get running in 5 minutes | |
Full API reference | |
Full API reference | |
HTTP endpoints | |
System design | |
Integration guide | |
Integration guide | |
Search pipeline, KG, CRDT, tiers | |
Integration, debugging, cron setup | |
MCP tools, configuration, schema |
Contributing
See CONTRIBUTING.md for dev setup, coding conventions, and PR guidelines.
Issues and PRs welcome. For security vulnerabilities, see SECURITY.md.
License
Available Tools
24 toolsmemory_advancedA
Power user escape hatch — pass through to any memory_maintenance operation.
Use this when a verb doesn't cover your use case.
Args: operation: Any memory_maintenance operation name. tenant_id: Tenant identity for tenant-scoped operations. **kwargs: Operation-specific parameters.
Security: this delegates to memory_maintenance, so the confirmation
gate on destructive operations applies here too. A destructive op
(e.g. purge_expired, okf_export, crdt_sync) called without
confirm=True is refused; pass confirm=True to proceed.
Inputs: kwargs (required), operation (required), tenant_id. Returns: result
memory_auditA
Review recent memory activity, errors, and system health.
Combines audit_query + circuit_breaker_status into one call.
Args: hours: Look back window (default 24h). limit: Max results (default 20). include_errors: Include error entries (default True).
Inputs: hours, limit, include_errors. Returns: result
memory_compile_skillC
Compile a lesson note into a validated executable agent skill rule file in ~/.agents/skills/.
Inputs: skill_name (required), lesson_slug (required), primary_triggers (required), secondary_triggers. Returns: result
memory_coordinateA
Multi-agent coordination tool for task management, file locking, and messaging.
Actions: create_task: Create a new task claim_task: Reserve a task for this agent update_task_status: Update task status (the primary coordination primitive) release_task: Release a task back to the pool complete_task: Mark task done, share result list_tasks: List tasks for a project lock_file: Acquire exclusive lock on a file unlock_file: Release file lock check_lock: Check if a file is locked send_message: Send message to another agent read_messages: Read pending messages get_project_state: See what others are doing update_project_state: Share what you're doing
Coordination model: Messages are notifications. Task status transitions are the ack. When Agent B reads a message and calls update_task_status, that IS the acknowledgement. No separate ack channel needed.
Inputs: key, value, action, status, +9 more. Returns: result
memory_curate_autosaveA
Review auto-saved tool invocations and promote or discard them.
The agent can list auto-saved notes, then batch-promote them into
intentional lessons or decisions with epistemic_source='agent'.
Args: start_date: ISO date filter start (e.g. "2026-06-01"). Empty = no start bound. end_date: ISO date filter end (e.g. "2026-07-01"). Empty = no end bound. action: "list" | "promote" | "discard". note_ids: List of note IDs to promote/discard (required for promote/discard). category: Target category for promotion (default "lessons").
Inputs: action, category, end_date, note_ids, +1 more. Returns: result
memory_deleteA
Delete a memory note by ID. Soft-delete by default (recoverable for 30 days).
Args: note_id: The note ID (e.g. "lessons/my-note"). hard: If True, permanently delete immediately (default False). confirm: Required to be True to allow a hard (permanent) delete. This is a safety gate: hard deletes cannot be recovered, so they must be explicitly confirmed. Soft-deletes (hard=False, the default) are unaffected.
Inputs: note_id (required), hard, confirm. Returns: result
memory_extract_skillsA
Manually trigger skill extraction.
P0 fix #5: lets the operator re-run the lower-threshold extractor
on a specific memory (memory_id="lessons/foo") or on every
memory when memory_id is empty. Uses the cron implementation
so the same code path runs in both places.
Args: memory_id: when non-empty, extract a skill from just this single memory. When empty, run the full extraction pass (same as cron_skill_extraction.py). dry_run: when True, count what would be extracted without writing to the DB.
Inputs: dry_run, memory_id. Returns: result
memory_graphC
Explore the knowledge graph.
Args: query: Natural language KG query (for action=explore). start: Starting entity/node ID (for action=traverse). edge_patterns: Edge type filter (for action=traverse). max_depth: Max traversal depth (default 2). action: "explore" | "traverse" | "shortest_path" | "stats".
Inputs: query, start, action, max_depth, +1 more. Returns: result
memory_health_checkB
Unified health-check: returns a JSON dict summarising subsystem state.
Checks DB availability, row counts, vec-index drift, FTS sync status, connection-pool depth, background-worker liveness, disk space, and CQRS write-journal health.
Inputs: no named parameters. Returns: result
memory_learnA
Save a lesson or compile a skill from content.
Auto-categorizes and tags the memory. Optionally compiles a skill.
Args: content: The lesson/skill content. as_skill: If True, compile as a skill (default False). skill_name: Skill directory name (required if as_skill=True). category: Target category (default: lessons). tags: Additional tags.
Inputs: content (required), tags, as_skill, category, +1 more. Returns: result
memory_list_revisionsA
List revision-log entries for a memory or across the store.
Surfaces supersede / amend / revert / delete events recorded in
memory_revision_log so the operator can audit what changed.
Args: memory_id: Filter to a specific memory id (empty = all). limit: Max results (default 20). revision_type: Filter by type: supersede, amend, revert, delete (empty = all types).
Inputs: limit, memory_id, revision_type. Returns: result
memory_list_skillsA
List extracted skills, ordered by hit_count desc.
P0 fix #5: gives the operator a way to inspect what the lower-threshold extractor actually pulled in. The list includes the topic, hit count, last-used timestamp, and a preview of the description so it's easy to spot good vs bad extractions.
Inputs: limit. Returns: result
memory_noteA
CRUD operations on a specific memory note.
Sprint 2 additions: patch, revert_supersede actions + rationale capture.
Args: note_id: The note ID (e.g. "lessons/my-note"). action: "read" | "update" | "delete" | "restore" | "supersede" | "patch" | "revert_supersede". content: New content (required for update). category: New category (for update). title_slug: New slug (for update/supersede target). tags: New tags (for update). rationale: Reason for the action (required for supersede, patch, revert_supersede; recommended for delete). additions: Text segments to insert (for patch action). deletions: Text segments to remove by content match (for patch action).
Inputs: note_id (required), tags, action, content, +5 more. Returns: result
memory_organizeA
Run safe memory maintenance batch.
Targets: safe_default: compact + consolidate + rewrite_links full: safe_default + backfill + dedup + purge_expired compact: FTS5 compact only dedup: KG entity dedup only
Args: target: Which batch to run (default: safe_default). dry_run: Preview without changes (default False). confirm: Required when target='full' and dry_run=False (purge is destructive).
Inputs: target, confirm, dry_run. Returns: result
memory_profileB
View user profile, agent scopes, ARC stats, and cached skills.
Args: action: "stats" | "user" | "agents" | "skills" | "arc". agent_id: Agent ID (for action=agents).
Inputs: action, agent_id. Returns: result
memory_recallB
Recall context for the current session or a named thread.
Combines session_start + recall_context into one call. If no query is given, returns recent session activity.
Args: query: What to recall (default: recent activity). session_id: Specific session/thread to recall.
Inputs: query, tenant_id, session_id. Returns: result
memory_recall_contextC
Assemble a structured memory recall briefing for agent cold-start or session continuity.
deep_rerank: when True, runs the Qwen3-0.6B / BGE-m3 deep reranker on
the relevant-memories section (1-5s extra CPU, best ranking quality).
Default False so the briefing is bounded to <100ms. ON APPLE SILICON
(MPS) the deep reranker can hang indefinitely in a PyTorch MPS kernel
(2026-06-19 incident: PIDs 68335, 10086). If you don't need the
best-quality ranking, leave this False. If you do need it and the call
hangs, set the MEMORY_RERANKER_DISABLED env var or
reranker_disabled = true in memory.toml to fully disable the
reranker (falls back to the lightweight weak cross-encoder).
Inputs: limit, query, action, days_recent, +5 more. Returns: result
memory_record_ctr_feedbackA
Record click-through rate feedback for a search result.
G4 fix (2026-06-22): memory_record_ctr_feedback (this tool)
and memory_reinforce (mcp_memory.py) record two different
signals on purpose — they are not interchangeable.
memory_record_ctr_feedbackrecords the implicit signal: "the user saw this result in the response." Writes a row toctr_feedbackwith action=returned/clicked/etc. The search re-ranker reads this table to adjust ranking over time. Use this when a search result is delivered to the user, regardless of whether the user does anything with it.memory_reinforcerecords the explicit signal: "the user judged this memory useful (or not)." Updatessuccess_scoreand recomputesfitness_score. Use this when a user acts on a memory — e.g. cites it in a lesson, marks a decision as right, or undoes a save because the memory was wrong. Skippingmemory_reinforceon every "user saw it" event would over-credit the success score.
In short: record_ctr_feedback = "delivered to user",
reinforce = "user acted on it positively". Call both when
a user follows up on a search hit. Call only
record_ctr_feedback when the user just sees the result.
Call only reinforce when the success/failure signal comes
from outside the search path (e.g. a downstream agent confirms
the memory was correct).
Inputs: id (required), query_id (required), action, source, +2 more. Returns: result
memory_review_beliefsA
Review beliefs that may need agent attention — low confidence, old, or stale.
Returns a structured list of belief assertions with subject/predicate/object for the agent to confirm, supersede, retract, or reinforce.
Args: min_confidence: Maximum confidence threshold (returns beliefs BELOW this). belief_status: Filter by status (default "active"). older_than_days: Only return beliefs last reviewed more than this many days ago. limit: Max results (default 20).
Inputs: limit, belief_status, min_confidence, older_than_days. Returns: result
memory_saveA
Save a memory note with sensible defaults.
Args: content: The memory content (markdown). category: lessons / decisions / projects / preferences / sessions (default: lessons). title_slug: URL-friendly slug (auto-generated if empty). tags: Optional keyword tags. pinned: Pin to hot tier (default False). importance: 1-5 (default 3). is_global: Save to global memory (default False). safety_wiring: If False, skip prompt-injection scanning (default True). Set to False for legitimate structured content with section headers and requirement keywords that may trigger false positives.
Inputs: content (required), tags, pinned, category, +4 more. Returns: result
memory_searchA
Search memories by semantic + FTS5 hybrid search.
The primary recall tool. Returns ranked memories matching the query. When the CQRS write journal is enabled, pending (not-yet-materialized) entries are also checked and surfaced as a supplement when the main search returns no results.
Args: query: Natural-language search query (required). category: Filter to a category (e.g. "lessons", "decisions"). limit: Max results (default 10). include_global: Include global memories (default True for default agent, scoped for non-default agents). mode: "hybrid" (default), "semantic", "fts", "facts", "graph". belief_status: Filter KG facts by belief status (active, retracted, deprecated, unconfirmed). epistemic_source: Filter KG facts by epistemic source (agent, auto_save, hook, import, cron). fact_type: Filter KG facts by type (observation, agent_inference, external_stated, hypothesis, derived). memory_source: Filter memories by source type ("agent", "auto_save", "import"). Only returns memories whose source file category matches the given type. shared_with_me: If True, also include memories explicitly shared with the current agent (via the shared pool's target_agent_id).
Inputs: query (required), mode, limit, category, +7 more. Returns: result
memory_session_startB
Retrieve the session startup briefing.
Args: query: Optional topic to scope the briefing to.
Inputs: query. Returns: result
memory_system_healthA
Comprehensive system health: green/yellow/red with actionable next steps.
Consolidates 6 health dimensions into one response:
Database: accessibility, schema, vec index drift
Search: semantic search probe
Worker: background worker liveness
Crons: cron job execution success rate
Auto-Save: circuit breaker and recent activity
Disk: free space
Each subsystem returns green/yellow/red with details and action.
Inputs: conn. Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 24 tools
Most tools have distinct purposes, but there is overlap between `memory_recall_context` and `memory_recall`, and between `memory_system_health` and `memory_health_check`. Descriptions help differentiate, but these overlaps could cause minor confusion.
All tools follow a consistent `memory_<verb>_<noun>` pattern in snake_case. The naming is predictable and uniform across the entire set.
With 24 tools, the set is on the larger side but each tool serves a specific function within the memory management domain. A few tools could potentially be merged, but the count is still reasonable.
The tool surface covers all major aspects of memory management: CRUD, search, revision, beliefs, skills, health, coordination, sharing, and graph. No obvious gaps are present.
Maintenance
Related MCP Connectors
Persistent memory, knowledge graph, task management and more for AI agents via MCP.
One memory, every AI. A shared, user-owned markdown memory your AI clients read and write over MCP.
Hosted memory for AI agents over MCP. One memory shared by all your agents.
An MCP memory server. One memory your agents share — across models, devices and apps.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceA local-first MCP memory server providing persistent, searchable memory for AI agents, powered by SQLite.1 npm1Apache 2.0
- AlicenseNot gradedqualityDmaintenancePersistent memory MCP server that stores and retrieves memories in Markdown files, enabling shared context across multiple AI agents with hybrid search and deduplication.MIT
- AlicenseBqualityDmaintenanceLocal-first memory server for AI coding agents that stores work sessions, tasks, and durable memories in Markdown files, exposed through MCP tools for session management and memory retrieval.1011 npm1MIT
- AlicenseNot gradedqualityCmaintenanceMCP server that provides agentic memory management for markdown vaults, enabling hybrid search, governed writing, and maintenance of episodic, semantic, procedural, and working memories for LLM agents.MIT