Context
Follow-up to #1295. AI Native DevCon notes surfaced the need for an agent-work dashboard that can answer whether task runs are getting cheaper, shorter, more reliable, and more knowledge-aware across many attempts.
Signed diary decision: 74c7948b-f2e0-4d06-8a95-6a3eebfd3472.
Prior related decision: 4bbf1174-f924-4462-8b0a-88ddfb9f27c0 established explicit task cohorts before semantic clustering.
Decision Summary
Keep product analytics in MoltNet rather than querying an OTel backend as the dashboard's source of truth. OTel remains valuable for traces/logs/runtime drilldown, but dashboard success-rate and cohort analytics need to join against MoltNet-owned concepts: tasks, attempts, messages, outputs, judgments, tags, teams, diary/pack provenance, and permissions.
Avoid duplicating canonical fields:
tasks owns task identity, type, title/tags, team/diary/correlation, and task status.
task_attempts owns lifecycle state, final status, output/error, timing, executor fingerprints, and reported usage tokens/model/provider/toolCalls.
task_messages owns the raw observed event stream.
- New derived data should only summarize activity inferred from
task_messages.
Proposal
Add a derived per-attempt activity summary table named task_attempt_activity_stats.
The table is a cache/read model, not a source of truth. It should be recomputable from task_messages and should not copy fields already owned by tasks or task_attempts.
Candidate v1 columns:
task_id
attempt_n
computed_at
source_last_seq
message_count
turn_count
tool_call_count
failed_tool_call_count
knowledge_tool_call_count
entry_search_count
entry_get_count
pack_get_count
Primary key: (task_id, attempt_n).
Compute this row when an attempt reaches a terminal state. Dashboard aggregate queries should join tasks, task_attempts, and task_attempt_activity_stats with bounded filters such as team and date range.
Metric Semantics
Do not expose one global success-rate definition. Support layered definitions:
- accepted-output rate: terminal tasks with
acceptedAttemptN present
- first-attempt accepted rate
- judged success rate where a downstream judge exists
- retry recovery rate
- cost/turn/tool-call medians per cohort
Task type should remain a filter, not the primary grouping assumption. freeform may become the dominant task shape, so cohorts should primarily use tags/search/correlation/executor/model and inferred activity categories.
Acceptance Criteria
Out of Scope For First Slice
- Querying Axiom/Datadog/Prometheus as the product dashboard backend.
- Currency pricing tables;
task_attempts.usage token counts are enough for v1.
- A broad
task_attempt_analytics view unless repeated query fragments justify it.
- Precomputing every dashboard aggregate by day/tag/model before real dashboard usage proves the need.
- Semantic clustering or embeddings for cohort discovery.
Related
Context
Follow-up to #1295. AI Native DevCon notes surfaced the need for an agent-work dashboard that can answer whether task runs are getting cheaper, shorter, more reliable, and more knowledge-aware across many attempts.
Signed diary decision:
74c7948b-f2e0-4d06-8a95-6a3eebfd3472.Prior related decision:
4bbf1174-f924-4462-8b0a-88ddfb9f27c0established explicit task cohorts before semantic clustering.Decision Summary
Keep product analytics in MoltNet rather than querying an OTel backend as the dashboard's source of truth. OTel remains valuable for traces/logs/runtime drilldown, but dashboard success-rate and cohort analytics need to join against MoltNet-owned concepts: tasks, attempts, messages, outputs, judgments, tags, teams, diary/pack provenance, and permissions.
Avoid duplicating canonical fields:
tasksowns task identity, type, title/tags, team/diary/correlation, and task status.task_attemptsowns lifecycle state, final status, output/error, timing, executor fingerprints, and reportedusagetokens/model/provider/toolCalls.task_messagesowns the raw observed event stream.task_messages.Proposal
Add a derived per-attempt activity summary table named
task_attempt_activity_stats.The table is a cache/read model, not a source of truth. It should be recomputable from
task_messagesand should not copy fields already owned bytasksortask_attempts.Candidate v1 columns:
task_idattempt_ncomputed_atsource_last_seqmessage_countturn_counttool_call_countfailed_tool_call_countknowledge_tool_call_countentry_search_countentry_get_countpack_get_countPrimary key:
(task_id, attempt_n).Compute this row when an attempt reaches a terminal state. Dashboard aggregate queries should join
tasks,task_attempts, andtask_attempt_activity_statswith bounded filters such as team and date range.Metric Semantics
Do not expose one global success-rate definition. Support layered definitions:
acceptedAttemptNpresentTask type should remain a filter, not the primary grouping assumption.
freeformmay become the dominant task shape, so cohorts should primarily use tags/search/correlation/executor/model and inferred activity categories.Acceptance Criteria
task_attempt_activity_statsschema + migration.task_messages; no duplicated task metadata, attempt status, timing, token usage, model, or provider.source_last_seqandcomputed_at.task_messagespayloads.tasks.tagsif tag cohort filtering needs it.task_messagesdirectly.Out of Scope For First Slice
task_attempts.usagetoken counts are enough for v1.task_attempt_analyticsview unless repeated query fragments justify it.Related