From 563b8e25726bbf352573018d5edbb2a1c9844f88 Mon Sep 17 00:00:00 2001 From: Hoang Snowy Date: Thu, 22 Oct 2026 23:33:55 +0700 Subject: [PATCH] feat(insights): the Autopilot Orchestrator's decisions are recorded too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Each decision's LLM call is stored as an Orchestrator run, so Insights shows what orchestration itself costs (≈ API on a member's computer) next to Coding / Reviewer / Testing / Discovery. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_018WAdQ7Rm24xss5QDSvXtJB --- .../Services/Orchestration/ProjectOrchestrator.Agent.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/AgentOs.Web/Services/Orchestration/ProjectOrchestrator.Agent.cs b/src/AgentOs.Web/Services/Orchestration/ProjectOrchestrator.Agent.cs index f99d7bf..c3e3c23 100644 --- a/src/AgentOs.Web/Services/Orchestration/ProjectOrchestrator.Agent.cs +++ b/src/AgentOs.Web/Services/Orchestration/ProjectOrchestrator.Agent.cs @@ -63,7 +63,14 @@ private async Task> DecideAsync(WorkspaceEntity b Snapshot(tickets, planTickets, planTasks, sessions), moves.Select(m => new OrchestratorMove(m.Id, KindOf(m.Action), IssueOf(m.Action), m.Action.Why)).ToList(), stuck, freeSlots, recent); - var decision = await sp.GetRequiredService().DecideAsync(brief, ct).ConfigureAwait(false); + // Metrics first: the decision's LLM call is an agent run in Insights like every other agent's. + OrchestratorDecision decision; + var decidedAt = DateTimeOffset.UtcNow; + using (var calls = AgentOs.Domain.Llm.LlmCallScope.Begin()) + { + decision = await sp.GetRequiredService().DecideAsync(brief, ct).ConfigureAwait(false); + await tasks.SaveAgentRunAsync(tenant, member, "Orchestrator", $"Orchestrator · {board.Name}", decidedAt, calls.Calls).ConfigureAwait(false); + } if (!decision.Ran) { if (_agentDown.TryAdd(board.Id, true))