# Session Context Pattern ## Problem **Context Fragmentation in Multi-Agent Orchestration** When orchestrating complex features across multiple agents (TaskManager → CoderAgent → TestEngineer), each agent is stateless and loses context between delegations: - **TaskManager** creates subtasks but doesn't know what ContextScout discovered - **CoderAgent** doesn't see what ArchitectureAnalyzer decided - **TestEngineer** doesn't know what files CoderAgent created - **Orchestrator** has to manually pass context in every delegation This leads to: - ❌ Repeated context discovery (inefficient) - ❌ Inconsistent decisions (agents don't see previous choices) - ❌ Lost architectural context (bounded contexts, contracts, ADRs) - ❌ Manual context passing (error-prone, verbose) ## Solution **Persistent Session Context File** Create a single `context.md` file that all agents read and update throughout the feature lifecycle: ``` .tmp/sessions/{session-id}/context.md ``` This file acts as the **shared memory** for the entire orchestration session. ## Architecture ### Session Lifecycle ``` 1. Orchestrator creates session → context.md initialized 2. ContextScout updates → adds context_files 3. ArchitectureAnalyzer updates → adds bounded_context, module 4. TaskManager reads context → creates subtasks with full context 5. CoderAgent reads context → knows all decisions, files, contracts 6. TestEngineer reads context → knows what to test 7. Orchestrator marks complete → session archived ``` ### Context.md Structure ```markdown # Task Context: {Feature Name} Session ID: {session-id} Created: {timestamp} Status: in_progress | completed | blocked ## Current Request {Original user request - what we're building} ## Context Files to Load - {Standards paths - coding conventions, patterns, security rules} ## Reference Files - {Source material - existing project files to look at} ## Architecture - Bounded Context: {DDD context from ArchitectureAnalyzer} - Module: {Package/module name} - Vertical Slice: {Feature slice from StoryMapper} ## User Stories - {Story 1 from StoryMapper} - {Story 2} ## Priorities - RICE Score: {score from PrioritizationEngine} - WSJF Score: {score} - Release Slice: {v1.0.0, Q1-2026, MVP} ## Contracts - {type}: {name} ({status}) Path: {contract file path} ## Architectural Decision Records - {ADR-ID}: {title} Path: {adr file path} ## Progress Current Stage: {Stage N: Name} Completed Stages: - {Stage 0: Context Loading} - {Stage 1: Planning} Stage Outputs: - {Stage 0}: - {Output 1} - {Output 2} ## Key Decisions - [{timestamp}] {decision} Rationale: {why this choice was made} ## Files Created - {file path 1} - {file path 2} ## Exit Criteria - [ ] {criterion 1} - [ ] {criterion 2} - [x] {completed criterion} ``` ## When to Use ### Use Session Context When: ✅ **Multi-agent orchestration** - Feature requires 3+ agents working sequentially ✅ **Complex features** - Needs architecture analysis, contracts, ADRs ✅ **Stateful workflows** - Later agents need to know what earlier agents did ✅ **Context-heavy tasks** - Lots of standards, patterns, decisions to track ### Don't Use Session Context When: ❌ **Single agent tasks** - Simple subtask execution (CoderAgent alone) ❌ **Stateless operations** - Each task is independent ❌ **Quick fixes** - Bug fixes, small updates ## Usage by Agent Type ### Orchestrator (MetaAgent) **Stage 0: Initialize Session** ```typescript import { createSession } from ".opencode/skill/task-management/scripts/session-context-manager"; const result = createSession(feature, request, { contextFiles: [], // Will be populated by ContextScout referenceFiles: [], exitCriteria: [ "All subtasks completed", "Tests passing", "Documentation updated", ], }); const sessionId = result.sessionId; // Pass sessionId to all subsequent agents ``` **Between Stages: Update Context** ```typescript import { updateSession, markStageComplete } from "./session-context-manager"; // After ContextScout completes updateSession(sessionId, { contextFiles: [ ".opencode/context/core/standards/code-quality.md", ".opencode/context/core/standards/security-patterns.md", ], }); // After ArchitectureAnalyzer completes updateSession(sessionId, { architecture: { boundedContext: "authentication", module: "@app/auth", }, }); // Mark stage complete markStageComplete(sessionId, "Stage 1: Planning", [ ".tmp/tasks/auth-system/task.json", ".tmp/tasks/auth-system/subtask_01.json", ]); ``` **Final Stage: Complete Session** ```typescript updateSession(sessionId, { status: "completed" }); ``` ### TaskManager **Stage 0: Load Session Context** ```typescript import { loadSession } from ".opencode/skill/task-management/scripts/session-context-manager"; const result = loadSession(sessionId); if (!result.success) { throw new Error(`Session not found: ${sessionId}`); } const session = result.session; // Use session context for task planning const contextFiles = session.contextFiles; // Standards to follow const referenceFiles = session.referenceFiles; // Source files to look at const architecture = session.architecture; // Bounded context, module const contracts = session.contracts; // API contracts const adrs = session.adrs; // Architectural decisions ``` **Stage 2: Create Tasks with Full Context** ```json { "id": "auth-system", "name": "Authentication System", "context_files": ["...from session.contextFiles..."], "reference_files": ["...from session.referenceFiles..."], "bounded_context": "...from session.architecture.boundedContext...", "module": "...from session.architecture.module...", "contracts": ["...from session.contracts..."], "related_adrs": ["...from session.adrs..."] } ``` **Stage 3: Update Progress** ```typescript import { addDecision } from "./session-context-manager"; addDecision(sessionId, { decision: "Split authentication into 3 subtasks: schema, service, middleware", rationale: "Each subtask is atomic (1-2 hours) and has clear dependencies", }); ``` ### CoderAgent **Before Coding: Load Session Context** ```typescript import { loadSession } from ".opencode/skill/task-management/scripts/session-context-manager"; const result = loadSession(sessionId); const session = result.session; // Read context files (standards) session.contextFiles.forEach((file) => { // Load coding standards, security patterns }); // Read reference files (existing code) session.referenceFiles.forEach((file) => { // Study existing patterns }); // Check architectural constraints const boundedContext = session.architecture?.boundedContext; const contracts = session.contracts; // API contracts to implement const adrs = session.adrs; // Architectural decisions to follow ``` **After Coding: Track Files Created** ```typescript import { addFile } from "./session-context-manager"; addFile(sessionId, "src/auth/jwt.service.ts"); addFile(sessionId, "src/auth/jwt.service.test.ts"); ``` ### ContextScout **After Discovery: Update Session** ```typescript import { updateSession } from "./session-context-manager"; updateSession(sessionId, { contextFiles: [ ".opencode/context/core/standards/code-quality.md", ".opencode/context/core/standards/security-patterns.md", "(example: .opencode/context/core/standards/naming-conventions.md)", ], referenceFiles: [ "src/middleware/auth.middleware.ts", "src/config/jwt.config.ts", ], }); ``` ### ArchitectureAnalyzer **After Analysis: Update Session** ```typescript import { updateSession, addDecision } from "./session-context-manager"; updateSession(sessionId, { architecture: { boundedContext: "authentication", module: "@app/auth", verticalSlice: "user-login", }, }); addDecision(sessionId, { decision: "Place authentication in separate bounded context", rationale: "Auth is a core domain with clear boundaries, used by multiple features", }); ``` ### ContractManager **After Contract Definition: Update Session** ```typescript import { updateSession } from "./session-context-manager"; updateSession(sessionId, { contracts: [ { type: "api", name: "AuthAPI", path: "src/api/auth.contract.ts", status: "defined", }, { type: "interface", name: "JWTService", path: "src/auth/jwt.service.ts", status: "draft", }, ], }); ``` ## API Reference ### createSession(feature, request, options) Initialize a new session with context.md file. **Parameters:** - `feature` (string) - Feature name (kebab-case) - `request` (string) - Original user request - `options` (object) - Optional configuration - `contextFiles` (string[]) - Standards paths - `referenceFiles` (string[]) - Source file paths - `exitCriteria` (string[]) - Completion criteria - `architecture` (object) - Bounded context, module, vertical slice - `stories` (string[]) - User stories - `priorities` (object) - RICE/WSJF scores, release slice - `contracts` (array) - API/interface contracts - `adrs` (array) - Architectural decision records **Returns:** ```typescript { success: boolean; sessionId?: string; error?: string } ``` **Example:** ```typescript const result = createSession("auth-system", "Implement JWT authentication", { exitCriteria: ["All tests passing", "JWT tokens signed with RS256"], }); // result.sessionId = "auth-system-2026-02-15T10-30-00-000Z" ``` ### loadSession(sessionId) Read session context from context.md. **Parameters:** - `sessionId` (string) - Session identifier **Returns:** ```typescript { success: boolean; session?: SessionContext; error?: string } ``` **Example:** ```typescript const result = loadSession("auth-system-2026-02-15T10-30-00-000Z"); if (result.success) { const contextFiles = result.session.contextFiles; const architecture = result.session.architecture; } ``` ### updateSession(sessionId, updates) Append new information to session context. **Parameters:** - `sessionId` (string) - Session identifier - `updates` (object) - Fields to update - `status` - 'in_progress' | 'completed' | 'blocked' - `contextFiles` - Add standards paths (merged with existing) - `referenceFiles` - Add source file paths (merged with existing) - `architecture` - Update bounded context, module, vertical slice - `stories` - Add user stories - `priorities` - Update RICE/WSJF scores - `contracts` - Add contracts - `adrs` - Add ADRs **Returns:** ```typescript { success: boolean; error?: string } ``` **Example:** ```typescript updateSession(sessionId, { architecture: { boundedContext: "authentication", module: "@app/auth", }, contracts: [ { type: "api", name: "AuthAPI", path: "src/api/auth.contract.ts", status: "defined", }, ], }); ``` ### markStageComplete(sessionId, stage, outputs) Mark a workflow stage as complete and record outputs. **Parameters:** - `sessionId` (string) - Session identifier - `stage` (string) - Stage name (e.g., "Stage 1: Planning") - `outputs` (string[]) - Files/artifacts created in this stage **Returns:** ```typescript { success: boolean; error?: string } ``` **Example:** ```typescript markStageComplete(sessionId, "Stage 1: Planning", [ ".tmp/tasks/auth-system/task.json", ".tmp/tasks/auth-system/subtask_01.json", ".tmp/tasks/auth-system/subtask_02.json", ]); ``` ### addDecision(sessionId, decision) Log a key decision with rationale. **Parameters:** - `sessionId` (string) - Session identifier - `decision` (object) - `decision` (string) - What was decided - `rationale` (string) - Why this choice was made **Returns:** ```typescript { success: boolean; error?: string } ``` **Example:** ```typescript addDecision(sessionId, { decision: "Use RS256 for JWT signing instead of HS256", rationale: "RS256 (asymmetric) is more secure for distributed systems where tokens are verified by multiple services", }); ``` ### addFile(sessionId, filePath) Track a file created during the session. **Parameters:** - `sessionId` (string) - Session identifier - `filePath` (string) - Path to created file **Returns:** ```typescript { success: boolean; error?: string } ``` **Example:** ```typescript addFile(sessionId, "src/auth/jwt.service.ts"); addFile(sessionId, "src/auth/jwt.service.test.ts"); ``` ### getSessionSummary(sessionId) Get current session state summary. **Parameters:** - `sessionId` (string) - Session identifier **Returns:** ```typescript { success: boolean; summary?: { sessionId: string; feature: string; status: string; currentStage: string; completedStages: number; totalDecisions: number; filesCreated: number; exitCriteriaMet: number; exitCriteriaTotal: number; }; error?: string; } ``` **Example:** ```typescript const result = getSessionSummary(sessionId); console.log(`Progress: ${result.summary.completedStages} stages complete`); console.log(`Files: ${result.summary.filesCreated} created`); console.log( `Exit Criteria: ${result.summary.exitCriteriaMet}/${result.summary.exitCriteriaTotal}`, ); ``` ## CLI Usage ```bash # Create session npx ts-node session-context-manager.ts create auth-system "Implement JWT authentication" # Load session npx ts-node session-context-manager.ts load auth-system-2026-02-15T10-30-00-000Z # Show summary npx ts-node session-context-manager.ts summary auth-system-2026-02-15T10-30-00-000Z ``` ## Benefits ✅ **No context loss** - All agents see the full picture ✅ **Consistent decisions** - Architectural choices tracked and visible ✅ **Efficient** - Context discovered once, used by all agents ✅ **Auditable** - Complete history of decisions and progress ✅ **Self-documenting** - context.md is human-readable ✅ **Resumable** - Can pause and resume orchestration ## Best Practices ### 1. Initialize Early Create session at the start of orchestration, before any agent work begins. ### 2. Update After Each Stage Every agent that completes work should update the session context. ### 3. Read Before Acting Every agent should load session context before starting work. ### 4. Track Decisions Use `addDecision()` for any architectural or design choice. ### 5. Track Files Use `addFile()` for every file created (helps with cleanup, rollback). ### 6. Use Exit Criteria Define clear, binary exit criteria at session creation. ## Example: Full Orchestration Flow ```typescript // Orchestrator: Initialize const { sessionId } = createSession( "auth-system", "Implement JWT authentication", { exitCriteria: ["All tests passing", "JWT tokens signed with RS256"], }, ); // Stage 0: ContextScout discovers context updateSession(sessionId, { contextFiles: [".opencode/context/core/standards/code-quality.md"], referenceFiles: ["src/middleware/auth.middleware.ts"], }); markStageComplete(sessionId, "Stage 0: Context Loading", []); // Stage 1: ArchitectureAnalyzer analyzes updateSession(sessionId, { architecture: { boundedContext: "authentication", module: "@app/auth" }, }); addDecision(sessionId, { decision: "Separate bounded context for auth", rationale: "Core domain with clear boundaries", }); markStageComplete(sessionId, "Stage 1: Architecture Analysis", []); // Stage 2: TaskManager creates tasks const { session } = loadSession(sessionId); // Use session.contextFiles, session.architecture in task.json markStageComplete(sessionId, "Stage 2: Task Planning", [ ".tmp/tasks/auth-system/task.json", ]); // Stage 3: CoderAgent implements const { session } = loadSession(sessionId); // Read session.contextFiles, session.contracts addFile(sessionId, "src/auth/jwt.service.ts"); markStageComplete(sessionId, "Stage 3: Implementation", [ "src/auth/jwt.service.ts", ]); // Stage 4: Complete updateSession(sessionId, { status: "completed" }); ``` ## Related - `.opencode/skill/task-management/scripts/session-context-manager.ts` - Implementation - `.opencode/context/core/task-management/standards/task-schema.md` - Task JSON schema - `.opencode/context/core/workflows/task-delegation-basics.md` - Multi-agent orchestration - `.tmp/sessions/test-task-manager/context.md` - Example session context