Page:
Data Flow 09 Self Management Operations
Pages
Architecture Commands and API
Architecture Context System
Architecture Core Engine
Architecture Event Sourcing
Architecture Generative Reflection
Architecture Helpers
Architecture Journal System
Architecture LLM Interaction
Architecture LLM Providers
Architecture Logging
Architecture Memory and Sleep
Architecture Overview
Architecture Persona Protection
Architecture Prompt System
Architecture RAG Implementation
Architecture Resilience System
Architecture Safety System
Architecture Self Management
Architecture Sub Agent Delegation
Architecture Task Assessment
Architecture Token Management
Architecture Tool System
Configuration Reference
Context and Memory Flow Analysis
Data Flow 01 Context Compaction
Data Flow 02 ReAct Loop
Data Flow 03 Memory Consolidation
Data Flow 04 Message Classification
Data Flow 05 Entity Profile System
Data Flow 06 Tool Execution
Data Flow 07 Sleep Mode Transitions
Data Flow 08 LLM Provider Interaction
Data Flow 09 Self Management Operations
Home
LLM Decision Patterns
Research Foundations
User Guide 00 Index
User Guide 01 Getting Started
User Guide 02 Configuration and Customization
User Guide 03 Advanced Capabilities
User Guide 04 Troubleshooting
No results
1
Data Flow 09 Self Management Operations
blightbow edited this page 2025-12-08 03:55:12 +00:00
Data Flow 09: Self-Management Operations
Projects, Goals, and Session Memory Execution Flows
Overview
This document traces the execution flows for the assistant's self-management operations:
- Project context swapping
- Goal decomposition and rollup
- Session memory with persona protection
1. Project Context Swap
Sequence: swap_project Execution
LLM calls swap_project(project_key="quest_design",
current_project_update="Walls 60% done",
reasoning="Player asked about quests")
│
▼
SwapProjectTool.execute()
│
├── 1. Validate target exists
│ projects = character.db.projects
│ if project_key not in projects["slots"]:
│ return {error: "Project does not exist", available_projects: [...]}
│
├── 2. Save current project state
│ old_key = projects["active"]
│ if old_key and current_project_update:
│ projects["slots"][old_key]["context"] = current_project_update
│ projects["slots"][old_key]["last_active"] = now()
│ projects["slots"][old_key]["status"] = "paused"
│
├── 3. Activate target project
│ projects["active"] = project_key
│ projects["slots"][project_key]["last_active"] = now()
│ projects["slots"][project_key]["status"] = "active"
│
├── 4. Persist changes
│ character.db.projects = projects
│
└── 5. Return context for LLM
return {
old_project: "build_tavern",
new_project: "quest_design",
new_project_summary: "Design main quest line",
new_project_context: "Current: Act 1 outline complete...",
}
State Transition
┌─────────────────────────────────────────────────────────────────┐
│ character.db.projects │
├─────────────────────────────────────────────────────────────────┤
│ BEFORE AFTER │
│ ────── ───── │
│ active: "build_tavern" active: "quest_design" │
│ │
│ slots: slots: │
│ build_tavern: build_tavern: │
│ status: "active" status: "paused" │
│ context: "Walls 50%..." context: "Walls 60%..." │
│ │
│ quest_design: quest_design: │
│ status: "paused" status: "active" │
│ context: "Act 1 complete" context: "Act 1 complete" │
└─────────────────────────────────────────────────────────────────┘
2. Goal Decomposition Flow
Sequence: add_goal → decompose_goal
LLM calls add_goal(description="Build a complete tavern", priority="high")
│
▼
AddGoalTool.execute()
│
├── Find script via search.search_script("ai_assistant")
│
├── script.add_goal(description, priority)
│ goal = {
│ "id": f"goal_{tick_count}_{len(goals)}",
│ "description": description,
│ "priority": priority,
│ "status": "active",
│ "progress": 0,
│ "parent_id": None,
│ "subtask_ids": [],
│ }
│ script.db.current_goals.append(goal)
│
└── return {goal_id: "goal_42_0", ...}
Later, LLM calls decompose_goal(goal_id="goal_42_0")
│
▼
DecomposeGoalTool.execute() [ASYNC_REQUIRED - uses @inlineCallbacks]
│
├── Find parent goal
│ parent = script.find_goal("goal_42_0")
│
├── yield script.decompose_goal(goal_id)
│ │
│ ├── Build LLM prompt:
│ │ "Break down this goal into 3-7 actionable subtasks:
│ │ Goal: Build a complete tavern
│ │ Return JSON array of subtask descriptions."
│ │
│ ├── yield llm_client.complete(prompt)
│ │
│ ├── Parse response → subtasks = ["Design layout", "Build walls", ...]
│ │
│ └── For each subtask:
│ child = add_goal(subtask_desc, parent_id="goal_42_0")
│ parent["subtask_ids"].append(child["id"])
│
└── return {
goal_id: "goal_42_0",
subtasks_created: 5,
subtasks: [{id: "goal_42_1", description: "..."}, ...]
}
Parent Progress Rollup
LLM calls update_goal(goal_id="goal_42_1", status="completed", progress=100)
│
▼
UpdateGoalTool.execute()
│
├── script.update_goal(goal_id, status, progress)
│ │
│ ├── Update subtask
│ │ subtask = find_goal("goal_42_1")
│ │ subtask["status"] = "completed"
│ │ subtask["progress"] = 100
│ │
│ └── Trigger parent rollup
│ update_parent_progress("goal_42_0")
│ │
│ ├── Collect subtask progress
│ │ subtasks = [find_goal(id) for id in parent["subtask_ids"]]
│ │ total = sum(s["progress"] for s in subtasks)
│ │ parent["progress"] = total / len(subtasks)
│ │
│ └── Check auto-completion
│ if all(s["status"] == "completed" for s in subtasks):
│ parent["status"] = "completed"
│
└── return {goal_id: "goal_42_1", message: "Goal updated"}
Goal State Example
After decomposition and partial completion:
script.db.current_goals = [
{id: "goal_42_0", description: "Build tavern", progress: 40,
subtask_ids: ["goal_42_1", "goal_42_2", "goal_42_3", "goal_42_4", "goal_42_5"]},
{id: "goal_42_1", description: "Design layout", progress: 100, status: "completed"},
{id: "goal_42_2", description: "Build structure", progress: 100, status: "completed"},
{id: "goal_42_3", description: "Add furniture", progress: 0, status: "active"},
{id: "goal_42_4", description: "Create bartender", progress: 0, status: "active"},
{id: "goal_42_5", description: "Write descriptions", progress: 0, status: "active"},
]
# Parent progress = (100 + 100 + 0 + 0 + 0) / 5 = 40%
3. Session Memory Lifecycle
Add with Persona Protection
LLM calls add_session_memory(memory_type="fact", content="I helped Alice")
│
▼
AddSessionMemoryTool.execute()
│
├── Check for self-referential patterns
│ content_lower = content.lower()
│ patterns = ["i helped", "i did", "i was", "i should", ...]
│
│ if any(pattern in content_lower for pattern in patterns):
│ return {
│ success: False,
│ error: "Content appears to reference assistant actions",
│ suggestion: "Rephrase in third-person...",
│ rejected_content: "I helped Alice"
│ }
│
└── [REJECTED - flow ends here]
LLM retries: add_session_memory(memory_type="fact",
content="Player Alice completed the intro quest")
│
▼
AddSessionMemoryTool.execute()
│
├── Persona check passes (no self-reference detected)
│
├── Get current session memory
│ session_mem = character.db.session_memory
│
├── Append to appropriate list
│ if memory_type == "fact":
│ session_mem["key_facts"].append(content)
│ else:
│ session_mem["learned_patterns"].append(content)
│
├── Persist
│ character.db.session_memory = session_mem
│
└── return {
success: True,
memory_type: "fact",
added: "Player Alice completed the intro quest",
total_facts: 5,
total_patterns: 2
}
Compaction Flow
LLM reviews memory and calls compact_session_memory(
new_facts=["Alice is level 5 warrior", "Server has 10 active players"],
new_patterns=["Players explore before asking for help"],
summary="Consolidated 8 facts about players into 2 key facts"
)
│
▼
CompactSessionMemoryTool.execute()
│
├── Capture before state
│ old_fact_count = len(session_mem["key_facts"]) # 8
│ old_pattern_count = len(session_mem["learned_patterns"]) # 4
│
├── Replace with compacted memory
│ character.db.session_memory = {
│ "key_facts": new_facts, # 2 facts
│ "learned_patterns": new_patterns, # 1 pattern
│ "completed_tasks": old["completed_tasks"], # preserved
│ "last_compacted": now(),
│ }
│
└── return {
before: {facts: 8, patterns: 4},
after: {facts: 2, patterns: 1},
summary: "Consolidated 8 facts..."
}
4. Cross-System Coordination
Typical Multi-System Flow
Tick Event: Player asks "Can you help me build a tavern?"
│
▼
1. Check current project
list_projects() → No active project
│
▼
2. Create project for context preservation
create_project(
project_key="player_tavern_build",
summary="Help player build a tavern",
initial_context="Player requested help. Location: north district..."
)
│
▼
3. Create goal for progress tracking
add_goal(
description="Complete player's tavern request",
priority="high"
)
│
▼
4. Decompose into subtasks
decompose_goal(goal_id="goal_X_0")
→ Subtasks: requirements, location, design, construction, furnishing
│
▼
5. Work on first subtask, update progress
update_goal(goal_id="goal_X_1", progress=50)
│
▼
6. Record learned preferences
add_session_memory(
memory_type="fact",
content="Player prefers rustic architectural style"
)
│
▼
7. Periodic context save
update_project(
context_update="Requirements gathered. Player wants 3 rooms..."
)
Key Files
| File | Lines | Purpose |
|---|---|---|
tools/context.py |
330-411 | SwapProjectTool.execute() |
tools/context.py |
104-166 | AddSessionMemoryTool.execute() with persona filter |
tools/goals.py |
90-114 | UpdateGoalTool.execute() |
tools/goals.py |
134-158 | DecomposeGoalTool.execute() |
assistant_script.py |
480-520 | update_parent_progress() |
See also: Architecture-Self-Management | Data-Flow-02-ReAct-Loop | Data-Flow-06-Tool-Execution