Agent Monitoring & Real-Time Updates#
Overview#
Implement comprehensive agent monitoring with real-time status updates, performance metrics, and error visibility. This ticket delivers the agent fleet monitoring flow from spec:50650885-e043-4e99-960b-672342fc4139/c565e255-83e7-4d16-a4ec-d45011fa5cad.
Scope#
Included:
- Agent list view with status badges, hash rate, error indicators
- Agent detail page with tabbed interface (Overview, Errors, Configuration, Capabilities)
- Targeted Turbo Stream broadcasts for agent status updates
- AgentStatusCardComponent for list view
- AgentDetailTabsComponent for detail view
- Stimulus tabs controller for tab switching
- Real-time updates via scoped Turbo Streams
Excluded:
- Agent creation/editing forms (already exist)
- Agent API endpoints (already exist)
- Agent benchmarking (already exists)
Acceptance Criteria#
Agent List View#
-
Agent list displays cards (not table) with:
- Status badge (active=green/offline=danger/pending=gray with color coding)
- Agent name (custom_label or host_name)
- Hash rate (formatted: "—", "0 H/s", or "X.X MH/s")
- Error indicator (red badge with count if errors in last 24h)
- Link to agent detail page
-
Agent list uses grid layout (3-4 cards per row)
-
Empty state shown when no agents exist
-
Skeleton loader shown while loading
-
Real-time updates via Turbo Streams (individual cards update)
Agent Detail Page - Tabbed Interface#
Tab Structure:
- Four tabs: Overview, Errors, Configuration, Capabilities
- Tabs implemented with Stimulus controller (fast switching, no network requests)
- First tab (Overview) shown by default
- Tab content loaded upfront (all tabs rendered, hidden with CSS)
Overview Tab:
- Current task (with link to task detail page)
- Performance metrics (hash rate, temperature, utilization)
- Agent state and last seen timestamp
- Operating system and client signature
- Projects assigned
Errors Tab:
- Recent errors table (last 100 errors)
- Columns: Timestamp, Severity, Message
- Severity badges (fatal/error/warning/info with color coding)
- Pagination if > 50 errors
- Empty state if no errors
Configuration Tab:
- Advanced configuration display (agent_update_interval, use_native_hashcat, backend_device)
- Enabled/disabled status
- User assignment
- Edit button (links to existing edit form)
Capabilities Tab:
- Supported hash types (from benchmarks)
- Benchmark data (hash type, speed)
- Device information
- Last benchmark date
Real-Time Updates#
- Agent status broadcasts target individual cards in list view
- Agent detail broadcasts target tab content only (preserve tab structure)
- Broadcasts don't reset active tab
- Broadcasts don't disrupt user interaction
- Broadcast errors logged but don't break functionality
Components#
-
AgentStatusCardComponentcreated with status badge, hash rate, error count -
AgentDetailTabsComponentcreated with slot rendering for tabs - Components use plain Bootstrap HTML and utility classes (Railsboot abstraction layer has been removed)
- Components tested with component specs
Testing#
- System test: View agent list, verify real-time updates
- System test: Navigate agent detail tabs, verify content
- System test: Verify broadcasts update correct elements
- Component tests for AgentStatusCardComponent
- Component tests for AgentDetailTabsComponent
Technical References#
- Core Flows: spec:50650885-e043-4e99-960b-672342fc4139/c565e255-83e7-4d16-a4ec-d45011fa5cad (Flow 1: Agent Fleet Monitoring)
- Tech Plan: spec:50650885-e043-4e99-960b-672342fc4139/f3c30678-d7af-45ab-a95b-0d0714906b9e (Component Architecture, Turbo Stream Broadcasts)
Dependencies#
Requires:
- ticket:50650885-e043-4e99-960b-672342fc4139/[Database Schema & Model Extensions] - Needs cached metrics columns
- ticket:50650885-e043-4e99-960b-672342fc4139/[UI Components & Loading States] - Needs Stimulus tabs controller
Blocks:
- None (other features can be implemented in parallel)
Implementation Notes#
Turbo Stream Broadcast Pattern#
The PR implements targeted Turbo Stream updates using the broadcast_replace_later_to pattern with stable DOM IDs generated by Rails' dom_id helper. This approach minimizes re-rendering and preserves user interface state (such as active tabs) during updates.
Partials Created for Agent Index Cards:
app/views/agents/_index_state.html.erb- Status badge (updates on state transitions)app/views/agents/_index_hash_rate.html.erb- Hash rate display (updates when metrics change)app/views/agents/_index_errors.html.erb- Error count badge for last 24h (updates when new errors created)app/views/agents/_index_last_seen.html.erb- Last seen timestamp (updates on heartbeat)
Broadcast Callbacks Implemented:
Agent#broadcast_index_state- Fires only on state transitions to avoid excessive updatesAgent#broadcast_index_last_seen- Fires whenlast_seen_atchangesAgent#broadcast_index_errors- Fires after agent error creation (via callback) to update error count on agent index cardsHashcatStatus#update_agent_metrics- Manually broadcasts hash rate updates (sinceupdate_columnsbypasses callbacks)
DOM ID Pattern:
Each updateable element uses a consistent ID pattern: dom_id(agent, :index_state), dom_id(agent, :index_hash_rate), etc. This ensures broadcasts target the correct element and don't interfere with surrounding content.
Broadcast Method Organization:
All broadcast methods live on the Agent model following a consistent naming pattern (broadcast_index_state, broadcast_index_last_seen, broadcast_index_errors). The Agent#broadcast_index_errors method is triggered by AgentError via after_create_commit -> { agent.broadcast_index_errors }, keeping the broadcast contract centralized on the Agent model while allowing related models to trigger updates as needed.
Fragment Cache Invalidation:
Agent index cards use cache: agent (not cache: true) to ensure cache_key_with_version incorporates the agent's updated_at timestamp. This prevents stale cards from being served after state changes, error count updates, or other model changes that touch updated_at. Without this, fragment caching would serve outdated card content even after real-time broadcasts update individual card elements.
Gotchas for Broadcast Partials:
Broadcast partials run in background jobs without access to current_user, session data, or controller helpers. Keep partials minimal and self-contained:
- Use only model data passed via
locals - Avoid calling helper methods that require session/user context
- Query associations directly on the model (e.g.,
agent.agent_errors.where(...)) - Ensure all required locals are explicitly passed in the
broadcast_replace_later_tocall
Additional Implementation Details#
- Replace existing file/views/agents/index.html.erb with card-based layout
- Refactor existing file/views/agents/show.html.erb to use tabbed interface
- Use
dom_idhelper for consistent broadcast targets - Test Turbo Stream broadcasts don't interfere with Stimulus controller
- Ensure broadcasts work in air-gapped environment (no external dependencies)
Component Development Guidelines:
The Railsboot component abstraction layer has been fully removed from the codebase. All new components should follow this pattern:
- Use plain ERB templates
- Render direct Bootstrap classes and HTML structure
- Use ViewComponent for reusable components, but render plain Bootstrap markup
- Refer to AGENTS.md for frontend development patterns and layout guidelines
- Refer to GOTCHAS.md for accessibility considerations and common pitfalls when building real-time UI updates
Estimated Effort#
2-3 days (views + components + Turbo Streams + tests)