Content Injection Design - Guides & Personas
Overview
Design for injecting selected guide and persona markdown content into chat sessions when users click on them in the respective panels.
Current State Analysis
What We Have
Backend Content Loading:
content-reader.jsreads markdown files and includes fullcontentfield- API returns complete markdown content for each guide/persona
Frontend Panels:
GuidesPanel.jsx: Shows categorized guides, clicks triggerhandleGuideClick()PersonasPanel.jsx: Shows personas list, clicks triggerhandlePersonaSelect()- Both currently just log to console and close panel
Chat Interface:
ChatInterface.jsxhandles message sending via WebSocket- Messages sent with:
{ message, sessionId, projectId }
Design Decisions
1. Injection Methods Comparison
| Method | Personas | Guides | Pros | Cons |
|---|---|---|---|---|
| System Context | Best | Good | Persistent, doesn't clutter chat | Not visible to user |
| Visible Badge | Good | Shows active state | Takes UI space | |
| Input Injection | Good | User can edit before sending | Disrupts flow | |
| Auto-Send | Quick | Too aggressive | ||
| Sidebar Panel | Good | Best | Always visible, clear state | Requires UI changes |
2. Recommended Approach
For Personas (Persistent Context):
- Selection: When user clicks a persona, set it as "active persona"
- Storage: Store in React context or state at App level
- Injection: Include persona content as system context with every message
- Visual: Show active persona badge in chat header
- Persistence: Remember across sessions in localStorage
- Clear Option: Button to clear/change active persona
For Guides (One-Time Injection):
- Selection: When user clicks a guide, inject immediately
- Method: Add as system context for current conversation
- Visual: Show brief notification "Guide applied: [name]"
- Format: Send as hidden context message to AI
- Multiple: Allow applying multiple guides in sequence
Implementation Architecture
// 1. App-level Context Management
const ChatContext = {
activePersona: {
id: 'analyst-sasha',
name: 'Analyst Sasha',
content: '...markdown content...'
},
appliedGuides: [
{ id: 'competitor-analysis', name: '...', content: '...' }
]
}
// 2. Message Enhancement
const enhancedMessage = {
message: userInput,
sessionId: currentSession,
projectId: currentProject,
context: {
persona: activePersona?.content,
guides: appliedGuides.map(g => g.content),
metadata: {
personaName: activePersona?.name,
guideNames: appliedGuides.map(g => g.name)
}
}
}
// 3. Visual Indicators
<ChatHeader>
{activePersona && (
<PersonaBadge>
<Icon /> {activePersona.name}
<CloseButton onClick={clearPersona} />
</PersonaBadge>
)}
{appliedGuides.length > 0 && (
<GuideIndicator>
{appliedGuides.length} guides active
</GuideIndicator>
)}
</ChatHeader>
UI/UX Flow
Persona Selection Flow:
- User opens Personas panel
- Clicks on a persona (e.g., "Analyst Sasha")
- Panel closes
- Badge appears in chat header: " Analyst Sasha"
- All subsequent messages include persona context
- User can click X on badge to clear persona
Guide Application Flow:
- User opens Guides panel
- Clicks on a guide (e.g., "Competitor Analysis")
- Panel closes
- Toast notification: " Applied: Competitor Analysis Guide"
- Guide content sent as context with next message
- Guide automatically clears after conversation
Technical Implementation Steps
Phase 1: Basic Injection
Update PersonasPanel.jsx:
- Pass full persona object (with content) to parent
- Use callback:
onPersonaSelect(persona)
Update GuidesPanel.jsx:
- Pass full guide object (with content) to parent
- Use callback:
onGuideSelect(guide)
Update App.jsx:
- Add state:
activePersona,appliedGuides - Pass callbacks to panels
- Pass context to ChatInterface
- Add state:
Update ChatInterface.jsx:
- Receive context props
- Include in WebSocket messages
- Show visual indicators
Phase 2: Enhanced Features
Persistence:
- Save activePersona to localStorage
- Restore on app load
Multi-Guide Support:
- Stack multiple guides
- Clear guides individually
Context Preview:
- Show what context is being sent
- Allow editing before sending
Server-Side Handling
// server/index.js WebSocket handler
socket.on('chat', async (data) => {
const { message, context } = data;
// Build enhanced prompt
let enhancedPrompt = message;
if (context?.persona) {
enhancedPrompt = `[Persona Context: ${context.metadata.personaName}]\n${context.persona}\n\n[User Message]\n${message}`;
}
if (context?.guides?.length > 0) {
const guideContext = context.guides.join('\n\n');
enhancedPrompt = `[Guide Context]\n${guideContext}\n\n${enhancedPrompt}`;
}
// Send to AI with enhanced context
// ... existing AI integration
});
Benefits of This Design
- Clear Mental Model: Users understand when context is active
- Flexibility: Can use personas, guides, or both
- Non-Intrusive: Doesn't clutter chat history
- Persistent: Personas stay active across messages
- Transparent: Visual indicators show what's active
- Reversible: Easy to clear/change context
Alternative Considerations
Option B: Visible Context Messages
- Show context as special message bubbles
- Pros: Full transparency
- Cons: Clutters chat history
Option C: Sidebar Context Panel
- Dedicated panel showing active context
- Pros: Always visible, detailed view
- Cons: Takes screen space
Migration Path
- Start with basic injection (Phase 1)
- Add visual indicators
- Implement persistence
- Add advanced features based on user feedback
Success Metrics
- Users can successfully apply personas/guides
- Context improves AI response quality
- No confusion about active context
- Easy to clear/change context
- Performance not impacted
How Context Works Under the Covers
What Actually Happens to Your Message
When you have an active persona or applied guides, here's the complete flow:
1. Frontend Context Building
When you send a message with active context:
// Your original message
"What are our main competitors?"
// With active persona (Analyst Sasha)
context = {
persona: "[Full markdown content of Analyst Sasha persona]",
personaMetadata: { id: "analyst-sasha", name: "Analyst Sasha" }
}
// With applied guide (Competitor Analysis)
context = {
guides: ["[Full markdown content of Competitor Analysis guide]"],
guidesMetadata: [{ id: "competitor-analysis", title: "Competitor Analysis" }]
}
2. WebSocket Transmission
The message sent over WebSocket includes:
{
type: 'claude-command',
command: "What are our main competitors?",
context: {
persona: "...[markdown content]...",
guides: ["...[markdown content]..."],
personaMetadata: {...},
guidesMetadata: [...]
},
options: { projectPath, sessionId, ... }
}
3. Server-Side Enhancement
The server (server/index.js) transforms your message:
// Original message
"What are our main competitors?"
// Enhanced message sent to Claude
"[Active Persona: Analyst Sasha]
You are a data analysis expert focused on market research...
[persona markdown content continues...]
[Applied Guide: Competitor Analysis]
When analyzing competitors, follow this framework...
[guide markdown content continues...]
[User Message]
What are our main competitors?"
4. Claude Receives Enhanced Context
Claude sees:
- The full persona description and behavior instructions
- Any applied guide frameworks or methodologies
- Your actual question at the end
This allows Claude to:
- Adopt the persona's expertise and communication style
- Follow the guide's framework or methodology
- Answer your question with the appropriate context
Key Technical Details
Context Injection Points
- Persona Context: Prepended as system instruction before every message
- Guide Context: Prepended as additional instructions for current message
- User Message: Always labeled clearly at the end
Message Format Sent to Claude
[Active Persona: {name}]
{persona markdown content}
[Applied Guide: {title}]
{guide markdown content}
[User Message]
{your actual message}
Why This Approach Works
- Personas persist because they define Claude's overall behavior
- Guides clear after use because they're task-specific instructions
- Context is invisible in chat UI to keep it clean
- Server handles enhancement to ensure consistency
Example: Complete Flow
You select "Analyst Sasha" persona
- System message appears: "π Applied persona: Analyst Sasha"
- Blue badge shows at top of chat
- Persona content stored in state
You select "Competitor Analysis" guide
- System message appears: " Applied guide: Competitor Analysis"
- Green badge shows "1 guide active"
- Guide content added to queue
You type: "What are our main competitors?"
Server receives and enhances:
[Active Persona: Analyst Sasha] You are a data analysis expert specialized in market research, competitive intelligence, and strategic insights. You approach problems with analytical rigor, using data-driven methodologies... [Applied Guide: Competitor Analysis] ## Competitor Analysis Framework When analyzing competitors, follow these steps: 1. Identify direct and indirect competitors 2. Analyze market positioning 3. Evaluate strengths and weaknesses... [User Message] What are our main competitors?Claude responds with Analyst Sasha's analytical approach, following the Competitor Analysis framework
After sending:
- Guides automatically clear (green badge disappears)
- Persona remains active for next message
- System shows what happened in chat history
Performance Considerations
- Markdown content size: Personas and guides can be lengthy, but are text-only
- Context limits: Claude has a context window limit; very long contexts may be truncated
- Network overhead: Minimal - just additional text in the WebSocket message
- Processing time: No noticeable delay; context is prepended instantly
Next Steps
- Basic persona selection with context - DONE
- Guide injection capability - DONE
- Visual indicators in chat header - DONE
- System messages in chat - DONE
- Monitor context effectiveness with real usage
- Optimize context content for best results