Something went wrong. Try again.
🐱 Medium-horizon agent planning MCP server
Something went wrong. Try again.
9plan Data Flow Diagrams #
Visual documentation of how data moves through the system during key operations.
Storage Overview #
┌─────────────────────────────────────────────────────────────────────────┐
│ Session Directory │
│ ~/.9plan/sessions/{session-name}/ │
│ │
│ ┌─────────────────────────────┐ ┌─────────────────────────────┐ │
│ │ session.db │ │ plans/ │ │
│ │ (SQLite) │ │ (Flat Files) │ │
│ │ │ │ │ │
│ │ ┌───────────────────────┐ │ │ ┌───────────────────────┐ │ │
│ │ │ metadata │ │ │ │ {plan-id}.txt │ │ │
│ │ │ - task_description │ │ │ │ - Context │ │ │
│ │ │ - created_at │ │ │ │ - Goal │ │ │
│ │ └───────────────────────┘ │ │ │ - Inputs │ │ │
│ │ │ │ │ - Outputs │ │ │
│ │ ┌───────────────────────┐ │ │ │ - Approach │ │ │
│ │ │ queue │ │ │ │ - Success Criteria │ │ │
│ │ │ - ordered plan IDs │ │ │ │ - Notes │ │ │
│ │ │ - active plan ref │ │ │ └───────────────────────┘ │ │
│ │ └───────────────────────┘ │ │ │ │
│ │ │ │ (Only queued + active │ │
│ │ ┌───────────────────────┐ │ │ plans have files) │ │
│ │ │ history (FTS5) │ │ │ │ │
│ │ │ - completed plans │ │ └─────────────────────────────┘ │
│ │ │ - full content │ │ │
│ │ │ - outcomes │ │ │
│ │ └───────────────────────┘ │ │
│ │ │ │
│ └─────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
Session Creation Flow #
9plan_session_create(task_description)
│
▼
┌─────────────────────┐
│ Generate Session │
│ Name (3 words) │
│ e.g. "amber-quiet- │
│ river" │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Check for │
│ Collision │◄─── Regenerate if exists
└──────────┬──────────┘
│ (unique)
▼
┌─────────────────────┐
│ Create Directory │
│ sessions/amber- │
│ quiet-river/ │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Initialize SQLite │
│ session.db │
│ - Create tables │
│ - Insert metadata │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Create plans/ │
│ subdirectory │
└──────────┬──────────┘
│
▼
Return: session_name,
session_path
Plan Addition Flow #
9plan_queue_add(context, goal, approach, success_criteria, inputs?, outputs?, position?)
│
▼
┌─────────────────────┐
│ Validate Plan │
│ (required fields) │──── Error if invalid
└──────────┬──────────┘
│ (valid)
▼
┌─────────────────────┐
│ Generate Plan ID │
│ (alphanumeric, │
│ 5+ chars) │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Check for │
│ Collision │◄─── Regenerate if exists
└──────────┬──────────┘
│ (unique)
▼
┌───────────────────────────────────────────────────┐
│ PARALLEL │
│ ┌──────────────────┐ ┌──────────────────────┐ │
│ │ Write Plan File │ │ Insert DB Record │ │
│ │ plans/{id}.txt │ │ - plan metadata │ │
│ │ - Full content │ │ - queue position │ │
│ │ - Empty Notes │ │ - status: queued │ │
│ └──────────────────┘ └──────────────────────┘ │
└───────────────────────────────────────────────────┘
│
▼
Return: plan_id,
plan_path,
queue_position
Position Logic:
position = "front" position = "back" (default)
Queue: [B, C, D] Queue: [B, C, D]
Add A at front Add A at back
Queue: [A, B, C, D] Queue: [B, C, D, A]
Plan Pull Flow #
9plan_queue_pull()
│
▼
┌─────────────────────┐
│ Check Active Plan │
│ Exists? │
└──────────┬──────────┘
│
┌───────┴───────┐
▼ ▼
(yes) (no)
│ │
▼ ▼
ERROR: ┌─────────────────────┐
"Plan │ Check Queue │
already │ Empty? │
active" └──────────┬──────────┘
│
┌───────┴───────┐
▼ ▼
(yes) (no)
│ │
▼ ▼
"Queue empty, ┌─────────────────────┐
task │ Get Front Plan ID │
complete" └──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Update DB │
│ - Remove from queue│
│ - Mark as active │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Verify Plan File │
│ Exists │
└──────────┬──────────┘
│
▼
Return: plan_id,
plan_path
Agent then reads plans/{id}.txt via filesystem tools
Plan Completion Flow #
9plan_plan_complete(outcome)
│
▼
┌─────────────────────┐
│ Get Active Plan │
│ from DB │──── Error if none active
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Read Plan File │
│ plans/{id}.txt │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Index into │
│ History (FTS5) │
│ - Full plan content│
│ - Outcome │
│ - Timestamp │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Delete Plan File │
│ plans/{id}.txt │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Clear Active Plan │
│ in DB │
└──────────┬──────────┘
│
▼
Return: success,
"pull next plan"
Data Migration on Completion:
BEFORE: AFTER:
plans/k7f3m.txt ─────────┐ plans/k7f3m.txt
# Context │ (DELETED)
Building Ghost... │
# Goal │ session.db
Create API client... │ history table:
# Notes │ ┌────────────────────┐
Progress: done auth │ │ id: k7f3m │
▼ │ content: (full) │
completion │ outcome: Created │
process │ ghost_client... │
│ │ completed_at: ... │
└────────────►└────────────────────┘
(searchable via FTS5)
Plan Deferral Flow #
9plan_plan_defer(reason, position?)
│
▼
┌─────────────────────┐
│ Get Active Plan │
│ from DB │──── Error if none active
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Append to Notes │
│ in Plan File │
│ [timestamp] reason │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Add Back to Queue │
│ (front or back) │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Clear Active Plan │
│ in DB │
└──────────┬──────────┘
│
▼
Return: success,
new queue position
State Change:
BEFORE: AFTER:
Active: k7f3m Active: (none)
Queue: [m2x9p, p4r2k] Queue: [m2x9p, p4r2k, k7f3m]
(if position=back)
plans/k7f3m.txt
# Notes plans/k7f3m.txt
(empty) # Notes
[2024-01-15 14:30] Deferred:
Waiting for auth dependency
Decomposition Flow #
Agent pulls plan, decides to decompose
1. Agent updates Notes in plan file:
"Decomposing into: A.1, A.2, A.3"
2. Agent adds subplans (reverse order for correct execution):
9plan_queue_add(A.3) → front Queue: [A.3, B, C]
9plan_queue_add(A.2) → front Queue: [A.2, A.3, B, C]
9plan_queue_add(A.1) → front Queue: [A.1, A.2, A.3, B, C]
3. Agent defers parent:
9plan_plan_defer("Decomposed into A.1, A.2, A.3", back)
Result: Queue: [A.1, A.2, A.3, B, C, A]
│
└── Parent at back
4. Execution proceeds:
- A.1 executes, completes
- A.2 executes, completes
- A.3 executes, completes
- B executes, completes
- C executes, completes
- A (parent) pulled again for aggregation
History Search Flow #
9plan_history_search(query)
│
▼
┌─────────────────────┐
│ FTS5 Query on │
│ history table │
│ │
│ Searches: │
│ - context │
│ - goal │
│ - inputs │
│ - outputs │
│ - approach │
│ - outcome │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Rank Results by │
│ Relevance │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Return Top N │
│ Matches │
│ │
│ For each: │
│ - plan_id │
│ - goal │
│ - outcome │
└──────────┬──────────┘
│
▼
Agent uses results
to resolve inputs
Example Search:
Query: "ghost client API authentication"
History:
┌─────────────────────────────────────────────────────────┐
│ k7f3m: "Create authenticated Ghost API client module" │
│ Outcome: "Created ghost_client module in src/lib/..." │ ← MATCH
├─────────────────────────────────────────────────────────┤
│ m2x9p: "Implement response caching system" │
│ Outcome: "Created caching layer..." │ ← no match
├─────────────────────────────────────────────────────────┤
│ x5k9m: "Create PostList UI component" │
│ Outcome: "Created PostList component..." │ ← no match
└─────────────────────────────────────────────────────────┘
Returns: [{id: k7f3m, goal: "Create authenticated...", outcome: "..."}]
Session Resume Flow #
9plan_session_resume(session_name)
│
▼
┌─────────────────────┐
│ Find Session │
│ Directory │──── Error if not found
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Open session.db │
└──────────┬──────────┘
│
▼
┌───────────────────────────────────────────────────┐
│ GATHER STATE │
│ │
│ ┌────────────────┐ ┌────────────────────────┐ │
│ │ Read metadata │ │ Read queue │ │
│ │ - task desc │ │ - ordered plan IDs │ │
│ └────────────────┘ │ - goals for each │ │
│ └────────────────────────┘ │
│ ┌────────────────┐ ┌────────────────────────┐ │
│ │ Get active │ │ Count completed │ │
│ │ plan (if any) │ │ plans in history │ │
│ └────────────────┘ └────────────────────────┘ │
│ │
└───────────────────────────────────────────────────┘
│
▼
Return: session_name,
session_path,
task_description,
queue (id + goal for each),
active_plan (if any),
completed_count
Tool Response Prefix Pattern #
All tool responses include the session name as a prefix:
┌─────────────────────────────────────────────────────────────┐
│ Tool Response │
│ │
│ [Session: amber-quiet-river] ◄── Always present │
│ │
│ Plan added: k7f3m │
│ Path: /Users/dev/.9plan/sessions/amber-quiet-river/... │
│ Queue position: 1 │
│ │
└─────────────────────────────────────────────────────────────┘
Purpose: Keep session name fresh in context for recovery
after context compaction
File System States by Plan Status #
┌─────────────────────────────────────────────────────────────┐
│ Plan Status │
├──────────────┬──────────────┬──────────────┬───────────────┤
│ QUEUED │ ACTIVE │ COMPLETED │ DISCARDED │
├──────────────┼──────────────┼──────────────┼───────────────┤
│ DB: queue[] │ DB: active │ DB: history │ DB: (removed) │
│ File: YES │ File: YES │ File: NO │ File: NO │
├──────────────┼──────────────┼──────────────┼───────────────┤
│ plans/ │ plans/ │ (deleted) │ (deleted) │
│ {id}.txt │ {id}.txt │ │ │
│ │ │ Content in │ No record │
│ │ │ session.db │ preserved │
└──────────────┴──────────────┴──────────────┴───────────────┘