AI Copilot Architecture
For humans and LLMs contributing to Songbird’s AI features.
Overview
Songbird’s AI copilot is a realtime music production assistant that lives inside the DAW. It routes user messages to specialized agents, assembles context from the current project state, and provides suggestions driven by DAW events and learned user preferences. The architecture is organized into six subsystems:Core Pipeline
Request Flow
Intent Types
Chat Modes
copilot— Full tool-use mode. Agent can call tools to modify the project.advisor— Read-only conversational mode. No tools, just musical guidance.
Event-Driven Hooks
File:hooks/copilot-hooks.ts + hooks/store-integration.ts
The hook system maps DAW events to copilot behaviors. Hooks are async, non-blocking, and never touch the audio thread.
Hook Events
Architecture
- Hooks are throttled per event type (configurable
MIN_INTERVAL_MS) to prevent storms - Suggestion queue has TTL — stale suggestions are culled automatically
- The
initializedflag inside the transport subscriber skips the initial C++ hydration diff - Store subscriptions use dependency injection (passed as callbacks) to avoid circular imports
Registering Custom Hooks
Per-User/Per-Project Instincts
File:instincts/instinct-engine.ts
Tracks learned user preferences with confidence scoring. Inspired by ECC’s continuous learning pattern.
Instinct Categories
Confidence Mechanics
- Initial confidence: 0.5
- On acceptance: +0.1 (capped at 0.95)
- On rejection: -0.15 (floor at 0.1)
- Prompt threshold: Only instincts >= 0.3 confidence are injected into prompts
- Global promotion: Instincts appearing in 2+ projects with >= 0.6 confidence are promoted to global scope
Storage
JSON-serialized via juceBridge under keysongbird-instincts. Debounced saves (3s).
Pattern Key Matching
Whenobserve() is called with a patternKey, it’s stored as pattern._key in the instinct object. Future observe() calls match by category + _key, enabling stable reinforcement across sessions without needing exact pattern JSON equality.
Tiered Context Loading
File:context/tiered-context.ts
Instead of dumping the entire project state on every LLM call, context is assembled in tiers with per-intent token budgets.
Tiers
Token Budgets by Intent
Assembly Logic
- Always include hot context
- Add warm blocks if required by intent OR if < 50% of budget used
- Add cold blocks if required by intent OR if < 30% of budget used
- Each block is individually checked against remaining budget before inclusion
tiersUsedaccurately reports which tiers had blocks actually included
Generate-Then-Refine Pipeline
File:pipeline/generate-refine.ts
A two-pass pipeline for creative content: let the model be creative first, then evaluate against musical constraints.
When It Triggers
Only forbird_edit intent with creative keywords: compose, write, create, fill, extend, generate, add, build, arrange, orchestrate, harmonize, improvise.
Pass 1: Generate (Creative)
Standard copilot call — unconstrained generation using the balanced/pro model.Pass 2: Refine (Evaluation)
A fast-model call that evaluates the generated content against:Output
Timeline-Driven Pre-Computation
File:timeline/pre-compute.ts
Uses playback position and arrangement structure to predict what the user needs next and pre-generate suggestions before they’re needed.
How It Works
Suggestion Types
Configuration
Cache Invalidation
- Suggestions are invalidated when a section is edited (
invalidateSection()) - TTL-based expiry for stale suggestions
- Manual
cancelAll()available for cleanup
Integration Points
copilot.ts (Main Orchestrator)
The copilotsend() method integrates the subsystems:
- Step 3b: After building the agent/standard system prompt, appends tiered context from
assembleTieredContext()(transport + mixer + instincts) - Step 7: After generation, checks
shouldUseRefine()and optionally runs the refinement pass
store.ts (Store Subscriptions)
Hook integration is initialized via dynamic import to avoid circular dependencies:_unsubs array) to avoid race conditions with async imports.
index.ts (Barrel Exports)
All subsystems are exported from@/lib/ai:
Wiring Status
The subsystems are at different stages of integration:
Next steps to fully wire:
- Call
observe()/accept()/reject()on instincts from copilot response handlers - Wire
setComputeHandler()to call the copilot for pre-generation - Track
recentActionsand pass them toassembleContext() - Replace
'current-project'placeholder with actual project ID from .bird filename - Add UI for displaying hook suggestions to the user