You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Part of an ActiveAgent + actionagent dashboard functional review (multi-agent, adversarially verified). Severity: 🟡 Minor.
A cluster of Traces read-side defects: the read API caps at 500 rows with no pagination and no truncation signal (so charts/totals under-report at volume); the dark-mode branch of TracesView is missing the Tools view, the time-window selector and the Conversation view the light branch has; the server-rendered "no-JS" traces console depends on three external CDNs (defeating its stated purpose); and TelemetryTrace#tool_usage reads only tool.input.args/tool.output.result, missing the ruby_llm adapter's tool.arguments/tool.result keys.
Findings
Traces read API caps at 500 rows with no pagination and no truncation signal, so the throughput chart and error/request totals silently under-report at volume
Where:actionagent/app/controllers/action_agent/api/trace_reports_controller.rb:28 · severity: minor · kind: missing · repo: activeagent
What breaks: TraceReportsController#index returns at most limit traces (default 500, hard max 1000) with no offset/cursor, and the response carries no indication that the window was truncated. The frontend never passes limit and computes everything client-side from the returned rows: the 'Agent Requests / Minute' chart, 'Total Requests', 'Errors', 'Avg Latency' and 'Throughput' summary tiles all claim to describe the selected time window but are actually computed over only the newest 500 traces. At a modest 9+ traces/min over a 1-hour window (or any longer window), the numbers are silently wrong — older buckets in the chart read as zero traffic. The activeagents app's Api::TracesController is a verbatim copy with the same behavior, and the server-rendered console index similarly hard-limits to 50 rows with no paging despite its controller doc claiming 'List view with filtering and pagination'.
Evidence: actionagent/app/controllers/action_agent/api/trace_reports_controller.rb:16,28-29 (DEFAULT_LIMIT 500, .recent.limit(limit), no offset, response lacks any total/truncated field); actionagent/frontend/components/dashboard/TracesView.jsx:118 (fetch sends only minutes+agent), :53-87 buildThroughputData buckets the returned rows, :513-522 summary tiles sum those buckets. Mirror: activeagents app/controllers/api/traces_controller.rb:14,26-27. Console: actionagent/app/controllers/action_agent/traces_controller.rb:7 ('filtering and pagination') vs :73 traces.limit(params[:limit] || 50) — no pagination anywhere.
Suggested fix: In both copies (engine trace_reports_controller.rb and app api/traces_controller.rb): compute window aggregates server-side (window_scope.count, with_errors.count, average duration) and include them plus a truncated flag (scope.count > limit) in the JSON; have TracesView.jsx use those aggregates for the summary tiles and surface a "showing newest N of M" notice on the chart when truncated. Optionally add cursor pagination (before=<timestamp/id>) for the trace list. Separately, fix the console fetch_traces to clamp params[:limit] and either add real paging or drop "pagination" from the class doc.
Engine TracesView dark branch: 'Tools' view button renders nothing and the time-window selector is missing
Where:actionagent/frontend/components/dashboard/TracesView.jsx:544 · severity: minor · kind: bug · repo: activeagent
What breaks: In the engine dashboard's TracesView, the dark-mode branch offers a 'tools' entry in the view-mode toggle but contains no viewMode === 'tools' render block — only the light branch renders the tool-usage table. In dark mode (the default for OS-dark users), clicking Tools leaves the content area under the throughput chart empty with no explanation. The dark branch also never renders TimeWindowSelector (only the light branch does, line 949), so dark-mode users cannot change the traces time window from this page. Unlike the app copy, the engine's dark branch does share TraceCard/TraceDetail, so this is limited to the tools block and window selector.
Evidence: actionagent/frontend/components/dashboard/TracesView.jsx:544 dark-branch toggle ['timeline', 'agents', 'actions', 'tools', 'spans'] inside the if (darkMode) return (:527); grep for viewMode === shows dark-branch render blocks only for 'agents' (:768), 'actions' (:817), 'spans' (:900), 'timeline' (:903) — 'tools' renders only at :1211 in the light return; TimeWindowSelector appears only at :949 (light). actionagent/frontend/contexts/ThemeContext.jsx defaults to prefers-color-scheme, so this is the default experience for OS-dark users.
Suggested fix: In both copies (engine actionagent/frontend/components/dashboard/TracesView.jsx and app app/javascript/components/dashboard/TracesView.jsx): extract the light branch's tools-usage table (engine :1211) into a theme-aware render helper mirroring renderSpansBreakdown(dark) and invoke it from the dark branch alongside the other viewMode blocks (after :900); add (already theme-aware or wrap with dark styles) to the dark header's control cluster next to the view-mode toggle (~:541). For the engine, rebuild the prebuilt bundle into actionagent/app/assets/builds after the frontend change.
Server-rendered traces console depends on three external CDNs, defeating its stated purpose as the no-bundle fallback
Where:actionagent/app/views/layouts/action_agent/application.html.erb:7 · severity: minor · kind: dx · repo: activeagent
What breaks: The engine routes describe the :console scope as 'Same data, no JavaScript — useful when the bundle can't run' (routes.rb:10-12), but its layout loads Tailwind from cdn.tailwindcss.com and Turbo + Stimulus from unpkg.com. On a self-hosted/air-gapped install, behind a strict CSP, or when those CDNs are unreachable, the console renders unstyled and its interactive pieces die: the expandable trace detail rows (data-action="click->traces#toggle" in index.html.erb) and the auto-refresh both depend on the CDN-loaded Stimulus, so trace details become unreachable in exactly the degraded environments the console exists for. This parallels the already-confirmed Font Awesome CDN dependency in the app dashboard layout (ground truth Update standard and rerun automatic fixes #6) but is a separate file in the engine.
Evidence: actionagent/app/views/layouts/action_agent/application.html.erb:7-9 (<script src="https://cdn.tailwindcss.com">, unpkg turbo 7.3.0, unpkg stimulus 3.2.2), :20-30 (the 'traces' Stimulus controller powering row expansion), :33-55 (auto-refresh); actionagent/config/routes.rb:10-12 ('useful when the bundle can't run'); actionagent/app/views/action_agent/traces/index.html.erb:69-71 rows are inert without that Stimulus controller.
Suggested fix: Make the console truly zero-dependency: replace the CDN Tailwind script with a small vendored/inline stylesheet covering the classes the console views use; replace the Stimulus row toggle with / (or a 3-line inline onclick that toggles the detail row's hidden class) plus an always-visible plain link from each row to traces#show; replace the Turbo-based auto-refresh with or a dependency-free setInterval + location.reload. Prefer inline over the asset pipeline, since the host may lack propshaft/sprockets (ground truth Any plans to support tools? #5).
TelemetryTrace#tool_usage reads only tool.input.args/tool.output.result, missing the ruby_llm adapter's tool.arguments/tool.result keys
Where:actionagent/app/models/action_agent/telemetry_trace.rb:196 · severity: minor · kind: drift · repo: activeagent
What breaks: The activeagents-telemetry ruby_llm adapter records tool span I/O under the attribute keys "tool.arguments" and "tool.result" (ruby_llm.rb:146-149). The engine's TraceInteractionSerializer was already taught both key families — it reads tool.arguments || tool.input.args and tool.result || tool.output.result (trace_interaction_serializer.rb:144,149) — but ActionAgent::TelemetryTrace#tool_usage still reads only the framework's keys: arguments: attributes["tool.input.args"], result: attributes["tool.output.result"] (telemetry_trace.rb:196-197). tool_usage feeds ToolDiscovery (tool_discovery.rb:177-190), where usage[:arguments] becomes the Tools view's sample_arguments and usage[:error]/duration feed per-tool stats. For any traffic ingested from the ruby_llm adapter with capture_bodies enabled, the Tools inventory therefore shows no sample arguments/results even though the data is in the stored spans — while the Interactions view shows it fine. The model is the side that is behind; the serializer's dual-key fallback is the fix to port.
Suggested fix: In TelemetryTrace#tool_usage (telemetry_trace.rb:196-197), fall back across both key families as TraceInteractionSerializer does: arguments: attributes["tool.input.args"] || attributes["tool.arguments"]; result: attributes["tool.output.result"] || attributes["tool.result"]. Add coverage using the "tool.arguments" key in test/telemetry_trace_test.rb and test/tool_discovery_test.rb, which currently exercise only "tool.input.args". Note the user-visible effect is the Tools view's missing sample_arguments; the result fallback is for API completeness since ToolDiscovery does not read usage[:result].
Verification
Each finding above was produced by a dedicated per-feature review agent, then confirmed by an independent adversarial verifier (all rated high-confidence; zero rejected in this set). File:line citations are against the current main/HEAD of each repo; many were reproduced live against a booted dashboard.
A cluster of Traces read-side defects: the read API caps at 500 rows with no pagination and no truncation signal (so charts/totals under-report at volume); the dark-mode branch of TracesView is missing the Tools view, the time-window selector and the Conversation view the light branch has; the server-rendered "no-JS" traces console depends on three external CDNs (defeating its stated purpose); and
TelemetryTrace#tool_usagereads onlytool.input.args/tool.output.result, missing the ruby_llm adapter'stool.arguments/tool.resultkeys.Findings
Traces read API caps at 500 rows with no pagination and no truncation signal, so the throughput chart and error/request totals silently under-report at volume
actionagent/app/controllers/action_agent/api/trace_reports_controller.rb:28· severity: minor · kind: missing · repo:activeagentlimittraces (default 500, hard max 1000) with no offset/cursor, and the response carries no indication that the window was truncated. The frontend never passes limit and computes everything client-side from the returned rows: the 'Agent Requests / Minute' chart, 'Total Requests', 'Errors', 'Avg Latency' and 'Throughput' summary tiles all claim to describe the selected time window but are actually computed over only the newest 500 traces. At a modest 9+ traces/min over a 1-hour window (or any longer window), the numbers are silently wrong — older buckets in the chart read as zero traffic. The activeagents app's Api::TracesController is a verbatim copy with the same behavior, and the server-rendered console index similarly hard-limits to 50 rows with no paging despite its controller doc claiming 'List view with filtering and pagination'..recent.limit(limit), no offset, response lacks any total/truncated field); actionagent/frontend/components/dashboard/TracesView.jsx:118 (fetch sends only minutes+agent), :53-87 buildThroughputData buckets the returned rows, :513-522 summary tiles sum those buckets. Mirror: activeagents app/controllers/api/traces_controller.rb:14,26-27. Console: actionagent/app/controllers/action_agent/traces_controller.rb:7 ('filtering and pagination') vs :73traces.limit(params[:limit] || 50)— no pagination anywhere.Engine TracesView dark branch: 'Tools' view button renders nothing and the time-window selector is missing
actionagent/frontend/components/dashboard/TracesView.jsx:544· severity: minor · kind: bug · repo:activeagentviewMode === 'tools'render block — only the light branch renders the tool-usage table. In dark mode (the default for OS-dark users), clicking Tools leaves the content area under the throughput chart empty with no explanation. The dark branch also never renders TimeWindowSelector (only the light branch does, line 949), so dark-mode users cannot change the traces time window from this page. Unlike the app copy, the engine's dark branch does share TraceCard/TraceDetail, so this is limited to the tools block and window selector.['timeline', 'agents', 'actions', 'tools', 'spans']inside theif (darkMode)return (:527); grep forviewMode ===shows dark-branch render blocks only for 'agents' (:768), 'actions' (:817), 'spans' (:900), 'timeline' (:903) — 'tools' renders only at :1211 in the light return;TimeWindowSelectorappears only at :949 (light). actionagent/frontend/contexts/ThemeContext.jsx defaults to prefers-color-scheme, so this is the default experience for OS-dark users.Server-rendered traces console depends on three external CDNs, defeating its stated purpose as the no-bundle fallback
actionagent/app/views/layouts/action_agent/application.html.erb:7· severity: minor · kind: dx · repo:activeagent<script src="https://cdn.tailwindcss.com">, unpkg turbo 7.3.0, unpkg stimulus 3.2.2), :20-30 (the 'traces' Stimulus controller powering row expansion), :33-55 (auto-refresh); actionagent/config/routes.rb:10-12 ('useful when the bundle can't run'); actionagent/app/views/action_agent/traces/index.html.erb:69-71 rows are inert without that Stimulus controller.(or a 3-line inline onclick that toggles the detail row's hidden class) plus an always-visible plain link from each row to traces#show; replace the Turbo-based auto-refresh with or a dependency-free setInterval + location.reload. Prefer inline over the asset pipeline, since the host may lack propshaft/sprockets (ground truth Any plans to support tools? #5).
TelemetryTrace#tool_usage reads only tool.input.args/tool.output.result, missing the ruby_llm adapter's tool.arguments/tool.result keys
actionagent/app/models/action_agent/telemetry_trace.rb:196· severity: minor · kind: drift · repo:activeagenttool.arguments || tool.input.argsandtool.result || tool.output.result(trace_interaction_serializer.rb:144,149) — but ActionAgent::TelemetryTrace#tool_usage still reads only the framework's keys:arguments: attributes["tool.input.args"],result: attributes["tool.output.result"](telemetry_trace.rb:196-197). tool_usage feeds ToolDiscovery (tool_discovery.rb:177-190), where usage[:arguments] becomes the Tools view's sample_arguments and usage[:error]/duration feed per-tool stats. For any traffic ingested from the ruby_llm adapter with capture_bodies enabled, the Tools inventory therefore shows no sample arguments/results even though the data is in the stored spans — while the Interactions view shows it fine. The model is the side that is behind; the serializer's dual-key fallback is the fix to port.Verification
Each finding above was produced by a dedicated per-feature review agent, then confirmed by an independent adversarial verifier (all rated high-confidence; zero rejected in this set). File:line citations are against the current
main/HEAD of each repo; many were reproduced live against a booted dashboard.