Data Flow
This document explains how messages flow through the Happy system, from user input to agent response and back to the mobile device.Message Types
Happy supports multiple message formats to accommodate different agent types:Session Protocol (New)
The modern message format used by Claude Code and other agents:text: User/agent text messagestool-call: Agent invoking a tooltool-result: Tool execution resultfile-edit: File modificationthinking: Agent reasoningturn-start/turn-end: Conversation turn boundaries
Legacy Protocol
Older format still supported for backward compatibility:ACP (Agent Communication Protocol)
Unified format for generic agent messages:packages/happy-cli/src/api/apiSession.ts:27 for full ACP message types.
End-to-End Message Flow
User Message (Mobile → CLI)
Implementation:packages/happy-cli/src/api/apiSession.ts:229 (onUserMessage handler)
Agent Response (CLI → Mobile)
Implementation:- CLI mapping:
packages/happy-cli/src/claude/utils/sessionProtocolMapper.ts - CLI sending:
packages/happy-cli/src/api/apiSession.ts:352(sendClaudeSessionMessage) - Server handling:
packages/happy-server/sources/app/api/routes/v3SessionRoutes.ts
WebSocket Communication
Connection Establishment
Connection Types:- user-scoped
- session-scoped
- machine-scoped
Used by: Mobile appReceives:
- All sessions owned by user
- All messages across sessions
- Machine online status
- Session activity updates
Event Types
Server → Client Events
'update' - New Message or State Change
'update' - New Message or State Change
Primary event for delivering updates to clients.Payload:Body Types:
new-message: New message in sessionupdate-session: Metadata or state changedupdate-machine: Machine metadata changed
packages/happy-server/sources/app/events/eventRouter.ts:buildNewMessageUpdate'rpc-request' - Remote Procedure Call
'rpc-request' - Remote Procedure Call
Mobile app invoking function on CLI.Payload:Response: Client calls callback with encrypted resultImplementation:
packages/happy-cli/src/api/apiSession.ts:158'session-activity' (Ephemeral)
'session-activity' (Ephemeral)
Real-time presence indicator for sessions.Payload:Note: Not persisted to database, sent only to connected clients
Client → Server Events
'message' - Send Message (Legacy)
'message' - Send Message (Legacy)
Deprecated: Use HTTP POST instead for better reliabilityPayload:Implementation:
packages/happy-server/sources/app/api/socket/sessionUpdateHandler.ts:186'session-alive' - Keep-Alive Ping
'session-alive' - Keep-Alive Ping
Sent every 2 seconds by CLI to indicate session is active.Payload:Implementation:
- CLI:
packages/happy-cli/src/api/apiSession.ts:475 - Server:
packages/happy-server/sources/app/api/socket/sessionUpdateHandler.ts:139
'update-metadata' - Update Session Metadata
'update-metadata' - Update Session Metadata
Optimistic concurrency control for metadata updates.Payload:Response:Implementation:
packages/happy-server/sources/app/api/socket/sessionUpdateHandler.ts:12'usage-report' - Token Usage Tracking
'usage-report' - Token Usage Tracking
CLI reports token usage after each agent response.Payload:Implementation:
packages/happy-cli/src/api/apiSession.ts:497Message Batching
Outbox Pattern (CLI)
The CLI uses an outbox pattern to batch messages efficiently:- Reduces HTTP requests (multiple messages in one POST)
- Preserves message order
- Automatic retry on network failure
packages/happy-cli/src/api/apiSession.ts:311
Message Fetching (CLI)
When CLI reconnects or receives out-of-order update, it fetches missing messages:hasMore: true
State Synchronization
Session Metadata
Metadata contains human-readable session information:- Encrypted with session key
- Versioned with optimistic concurrency
- Synced via
update-metadataWebSocket event
packages/happy-cli/src/api/apiSession.ts:528
Agent State
Agent state contains execution context for remote mode:- Similar to metadata (encrypted, versioned)
- Used to persist conversation history
- Synced via
update-stateWebSocket event
packages/happy-cli/src/api/apiSession.ts:553
Optimistic Concurrency Control
Both metadata and agent state use version numbers to handle concurrent updates: Implementation:packages/happy-server/sources/app/api/socket/sessionUpdateHandler.ts:33
Sequence Numbers
The system uses two types of sequence numbers:User Sequence (Global)
- Increments for every update sent to user
- Used to order updates across all sessions
- Allocated per user:
packages/happy-server/sources/storage/seq.ts:allocateUserSeq
Session Sequence (Per-Session)
- Increments for every message in a session
- Used to detect missing messages
- Allocated per session:
packages/happy-server/sources/storage/seq.ts:allocateSessionSeq
RPC (Remote Procedure Calls)
Handler Registration
CLI registers RPC handlers that mobile can invoke:${sessionId}:file.read prevents cross-session calls
Invocation Flow
Timeout: Server times out after 30 seconds if CLI doesn’t respond Implementation:packages/happy-cli/src/api/rpc/RpcHandlerManager.ts
Error Handling
Network Errors
Connection Loss
Connection Loss
Symptoms: WebSocket disconnect, HTTP timeoutCLI Behavior:
- Buffer outgoing messages in outbox
- Attempt reconnection with exponential backoff
- Fetch missed messages on reconnect
- Continue local operation (agent still runs)
- Show “Offline” indicator
- Queue user messages locally
- Reconnect automatically
- Sync state on reconnect
Message Loss
Message Loss
Detection: Sequence number gapRecovery:
- CLI detects
messageSeq != lastSeq + 1 - Triggers
fetchMessages()to retrieve missing messages - Replays messages in order
packages/happy-cli/src/api/apiSession.ts:183Version Conflict
Version Conflict
Cause: Two clients updating metadata/state simultaneouslyResolution:
- Server returns
version-mismatchwith current data - Client merges changes and retries with new version
- Backoff algorithm prevents retry storms
packages/happy-cli/src/api/apiSession.ts:536Encryption Errors
Decryption Failure
Decryption Failure
Causes: Wrong key, corrupted data, version mismatchHandling:
- Log error with details (seq number, session ID)
- Skip message (don’t crash)
- Continue processing subsequent messages
Key Rotation
Key Rotation
Not yet implementedFuture: Support for re-encrypting session with new key
Performance Considerations
Message Throughput
Bottlenecks:- Database writes (SessionMessage inserts)
- Encryption/decryption overhead
- WebSocket serialization
- Batch message inserts (up to 100 per request)
- Reuse encryption context (avoid key derivation)
- Use
volatileevents for keep-alive (no delivery guarantee)
Memory Usage
CLI:- Outbox bounded at ~100 messages (auto-flush)
- Message history not kept in memory (fetch on demand)
- Session cache: ~1KB per active session
- Connection map: ~500 bytes per WebSocket
- Redis pub/sub: Minimal memory (transient)
Next Steps
Encryption Layer
Understand TweetNaCl encryption implementation
Session Lifecycle
Learn session creation and termination
Server Component
Explore server endpoints and schemas
Architecture
High-level system overview