219 files, 2.0 MB, untracked in souveraine/docs and existing nowhere else. The volume is at 100% with no snapshots.
6.3 KiB
6.3 KiB
| task_id | title | status | assignee | priority | phase |
|---|---|---|---|---|---|
| subagent-pool-001 | Subagent Pool - Fork/Spawn/Integrate Lifecycle | scoped | TBD | high | 2 |
Task: Subagent Pool Implementation
Objective
Build the subagent pool from 17-line stub to working fork/spawn/integrate system for parallel and delegated execution.
Background
Current state: src/core/subagent/mod.rs is a 17-line stub:
pub struct SubagentPool;
impl SubagentPool {
pub fn new() -> Self { Self }
}
From docs/CONTEXT_CONSTITUTION.md and Letta heritage:
- Subagents enable parallel processing
- Fork/join pattern for complex tasks
- Parent-child relationship tracking
- Result integration back to primary
What Was Lost from Letta
Letta had 7 built-in subagent types with full lifecycle:
reflection- N+25 style witnessarchival- N+100 style compressionanalysis- Deep analysis of code/dataresearch- Information gatheringcoding- Code generationtesting- Test executiondocumentation- Doc generation
Capabilities lost:
- Persistent subagent identity
- Model inheritance from parent
- Parent-child tracking
- Automatic result integration
- Circuit breaker protection (from Aster)
Souveraine Subagent Model
From Constitution: "Skills Before Agents" (Law 10)
Souveraine differs from Letta:
- Single consciousness (not multi-agent)
- Subagents are temporary forks, not persistent peers
- Subagents share parent's memfs (read-only or copy-on-write)
- Results integrate back, then subagent dissolves
Fork/Spawn/Integrate Lifecycle
Parent (Ani)
↓
FORK ──► Create subagent context (copy-on-write or read-only view)
↓
SPAWN ──► Launch Tokio task with subagent
↓
[subagent runs in parallel]
↓
INTEGRATE ──► Merge results back to parent
↓
DISSOLVE ──► Clean up subagent
Implementation
New Files:
src/core/subagent/pool.rs- Subagent pool managementsrc/core/subagent/fork.rs- Context forking logicsrc/core/subagent/spawn.rs- Tokio task spawningsrc/core/subagent/integrate.rs- Result integrationsrc/core/subagent/types.rs- Subagent type definitions
Modify:
src/core/subagent/mod.rs- Replace stub with full implementationsrc/server/consciousness_engine.rs- Wire up subagent triggers
Key Components
1. SubagentPool
pub struct SubagentPool {
active: DashMap<SubagentId, SubagentHandle>,
completed: Arc<Mutex<Vec<SubagentResult>>>,
}
impl SubagentPool {
pub async fn spawn<F>(&self, config: SubagentConfig, task: F) -> SubagentId
where F: Future<Output = Result<String>> + Send + 'static;
pub async fn join(&self, id: SubagentId) -> Result<SubagentResult>;
pub fn integrate(&self, parent: &mut Conversation, result: SubagentResult);
}
2. Fork Strategies
| Strategy | Use Case | Implementation |
|---|---|---|
| Read-Only View | Analysis, research | Shared memfs reference |
| Copy-on-Write | Modifying tasks | Overlay filesystem |
| Full Copy | Isolated experiments | Clone git repo |
| Named Branch | Long-running work | Git branch + merge |
3. Subagent Types
pub enum SubagentType {
Reflection, // N+25 witness
Archival, // N+100 compression
Analysis, // Deep analysis task
Research, // Information gathering
CodeReview, // Code review skill
Documentation, // Doc generation
Custom(String), // User-defined
}
4. Integration Patterns
| Pattern | When | How |
|---|---|---|
| Append | Additional info | Add to conversation |
| Summarize | Large result | LLM summary then add |
| File Write | Generated content | Write to memfs |
| Surfacing | Urgent finding | Inject into primary view |
| Silent | Background task | Log only, don't surface |
Configuration
[subagents]
enabled = true
max_concurrent = 3
default_fork_strategy = "read_only"
inherit_model = true
timeout_seconds = 300
[subagents.types.reflection]
model = "qwen2.5-7b" # Smaller model for reflection
fork_strategy = "read_only"
[subagents.types.analysis]
model = "kimi-k2-5" # Full model for analysis
fork_strategy = "copy_on_write"
Use Cases
1. Parallel Code Review
// Spawn subagents for each file
for file in files {
pool.spawn(SubagentConfig::code_review(), async move {
review_file(file).await
});
}
// Join all results
let results = pool.join_all().await;
let summary = synthesize_results(results);
2. Background Research
// Spawn research subagent
let research_id = pool.spawn(SubagentConfig::research(), async {
gather_information(topic).await
});
// Continue main conversation
// ... later ...
let research = pool.join(research_id).await;
conversation.integrate(research);
3. N+25 Reflection (as subagent)
// Every 25 messages
let reflection_id = pool.spawn(SubagentConfig::reflection(), async {
witness_four_elements(conversation.history()).await
});
// Don't block - reflection writes to journal asynchronously
Success Criteria
- SubagentPool manages fork/spawn/integrate/dissolve
- Read-only fork strategy working
- Copy-on-write fork strategy working
- Tokio task spawning with proper cleanup
- Result integration back to parent
- Parent-child relationship tracking
- Model inheritance from parent
- Timeout and cancellation
- 7 built-in subagent types defined
- Custom subagent type support
- Unit tests for lifecycle
- Integration test showing parallel execution
References
src/core/subagent/mod.rs(current stub)docs/SUBAGENT_INVESTIGATION.md(research)docs/saf/gaps.md("Port subagent system from Letta")- Letta subagent documentation (reference)
Estimated Scope
- Core pool management: 3-4 days
- Fork strategies: 3-4 days
- Integration patterns: 2-3 days
- Built-in types: 2-3 days
- Testing: 2-3 days
Total: 12-17 days
Dependencies
- Tokio runtime (✅ done)
- Memory system (✅ done)
- Model router (✅ done)
- Optional: Chain modes (for complex subagent workflows)
Alternative: Simpler First Pass
Start with just:
- Single subagent spawn/join (no pool management)
- Read-only fork only
- Async task integration
Add complexity (pool, COW, types) incrementally.