APM Protocol (Agent Progressive Memory): Progressive disclosure protocol for group chat AND DM (main session) memory.
---
name: APM-agent-progressive-memory
description: "APM Protocol (Agent Progressive Memory): Progressive disclosure protocol for group chat AND DM (main session) memory."
---
# APM — Progressive Disclosure Protocol
APM supports **both group chat and private (main session DM)** memory management. The two structures are completely independent and do not interfere with each other.
## Group vs DM: Strategy Comparison
| Aspect | Group Chat | DM (Main Session) |
|-------|-----------|-------------------|
| **Memory path** | `memory/groups/{group_name}/` | `memory/main/` |
| **Loading** | 5-step progressive (index → P0 → P1 → P2 → P3) | 3-layer progressive (index → attention → longterm) |
| **Index file** | `memory/groups/{group_name}.md` | `memory/main/index.md` |
| **Priority files** | attention.md, project.md, experience.md, people.md | attention.md, longterm.md |
| **Entry rule** | Must read index first, no subdirectory bypass | Must read index first |
| **Flush trigger** | Per-group flush on `/remem` | Full-session flush on `/remem` |
**Key differences**:
- Group uses **5-step loading** with budget controls; DM uses simpler **3-layer**
- Group has **conventions/** sub-directory; DM does not
- DM reuses existing **MEMORY.md**; Group uses dedicated files
- Uninstaller: Group loses memory access; DM retains MEMORY.md
Agent must follow the **layered disclosure protocol** when accessing memory in group chats: read the index first, then load layers on demand.
## Core Rules
### 1. Entry Gate
- The **only legal entry point** for group chat memory is `memory/groups/{group_name}.md` (index file)
- **Forbidden**: directly reading any sub-files under `memory/groups/{group_name}/`
- **Forbidden**: bypassing the index to directly `memory_search` subdirectories
- **Group name mapping rule**: group chat room IDs must first be resolved via `memory/group_names.json` to a friendly name `{group_name}` before use
### 2. Five-Step Loading Flow
| Step | Action | Output |
|------|--------|--------|
| 0. Group name mapping | Check `memory/group_names.json`, convert room ID to `{group_name}` | Friendly name |
| 1. Route to index | `memory_get("memory/groups/{group_name}.md")` | Hard Rules + routing table |
| 2. Intent matching | Match current message to trigger scenario | File to load |
| 3. Explicit load | `memory_get("memory/groups/{group_name}/{file}.md")` | Actual memory content |
| 4. Sub-layer control | Load only if Step 3 file references `conventions/` | 1 sub-file max |
| 5. Budget circuit-breaker | Stop when cumulative tokens exceed `memory_budget` | Stop loading |
Only **one** best-matching file is loaded per session (highest priority wins).
### 3. Loading Discipline
- Maximum **2 P0-P2 files + 1 P3 file** per session
- `conventions/` files: only **1** at a time
- When switching group chats, clear old context first, then restart from Step 1
### 4. Write-Back on Updates
- New decision → append to `experience.md`
- Task status change → update `attention.md`
- Index files: append-only (mark deleted entries `[DEPRECATED]` instead of removing)
### 5. Memory Flush
| Trigger | Condition | Action |
|---------|-----------|--------|
| `/remem` | User manual trigger | Full flush |
| Pre-compact | Context near limit | Auto-flush before loss |
| Idle timeout | 30min inactive, no flush | One-time auto-flush |
### 6. Auto-Initialization on Missing Memory
> When a flush is triggered for a session whose memory system has **not yet been initialized**, the Agent must initialize it based on available information.
| Scenario | Action |
|----------|--------|
| Group index missing | Create from `group_names.json` + context |
| DM index missing | Create from `MEMORY.md` content |
**Initialization is not overwriting**: existing files are never overwritten — only created when completely absent.
## File Structure
```
memory/groups/
├── {group_name}.md # L0: Entry gate (mandatory read)
└── {group_name}/ # Group memory (direct access forbidden)
├── attention.md # P0: Current focus
├── project.md # P1: Project static info
├── experience.md # P2: Experience / decision log
├── people.md # P3: People profiles
└── conventions/ # L3: Detailed specifications
├── api.md
└── ...
memory/main/ # DM progressive disclosure
├── index.md # L0: DM entry index
├── attention.md # P0: Current tasks, blockers
├── longterm.md # P1: MEMORY.md distilled summary
├── daily-synced.md # P2: Daily notes summary
└── projects/ # P3: Project context
└── {name}.md
```
## Priority Definitions
| Priority | File | Content | When to Load |
|----------|------|---------|--------------|
| P0 | `attention.md` | Active tasks, blockers | Any work conversation |
| P1 | `project.md` | Tech stack, architecture | Technical decisions |
| P2 | `experience.md` | Lessons learned | Search hit + append |
| P3 | `people.md` | Team roles, contacts | Need to find someone |
## DM Entry Loading (to add in AGENTS.md)
```markdown
## Every Session
1. Read `SOUL.md` → USER.md → MEMORY.md
2. **If in MAIN SESSION** (DM):
- Read `memory/main/index.md` — DM progressive index
- Based on routing, load up to 2 files
- Report `上次 flush: YYYY-MM-DD HH:mm` (from `flush-state.json`)
3. Read `memory/YYYY-MM-DD.md` (today + yesterday)
```
## Flush State File
`memory/flush-state.json`:
```json
{
"groups": { "last_flush_time": "..." },
"main_session": { "last_flush_time": "..." },
"pending_items": []
}
```
## Anti-Pattern
```
❌ Load all at once → ✅ Load only one at a time
❌ Skip index → ✅ Read index first
❌ Load two groups → ✅ Clear old, reload from Step 1
```
## Complete Protocol Checklist
1. **Entry gate** — index is the only entry
2. **Five-step loading** — name mapping → index → intent → load → sub-layer → budget
3. **Loading discipline** — 2+1 file limit, clear on switch
4. **Write-back** — immediately update on decisions
5. **Memory Flush** — `/remem` + Pre-compact + Idle
6. **Auto-Flush** — precompact hook before compaction
7. **DM Progressive** — independent layout, survives uninstall
8. **Auto-Initialization** — init missing memory from known infodon't have the plugin yet? install it then click "run inline in claude" again.