diff --git a/internal/http/summoner.go b/internal/http/summoner.go index e633900e..299fb04d 100644 --- a/internal/http/summoner.go +++ b/internal/http/summoner.go @@ -104,7 +104,7 @@ func (s *AgentSummoner) SummonAgent(agentID uuid.UUID, tenantID uuid.UUID, provi if !isRetryableError(err) { slog.Warn("summoning: single-call failed (non-retryable)", "agent", agentID, "error", err) s.emitEvent(agentID, tenantID, SummonEventFailed, "", err.Error()) - s.setAgentStatus(context.Background(), agentID, store.AgentStatusSummonFailed) + s.setAgentStatus(context.Background(), tenantID, agentID, store.AgentStatusSummonFailed) return } @@ -127,7 +127,7 @@ func (s *AgentSummoner) SummonAgent(agentID uuid.UUID, tenantID uuid.UUID, provi if soulErr != nil { slog.Warn("summoning: SOUL.md generation failed", "agent", agentID, "error", soulErr) s.emitEvent(agentID, tenantID, SummonEventFailed, "", soulErr.Error()) - s.setAgentStatus(context.Background(), agentID, store.AgentStatusSummonFailed) + s.setAgentStatus(context.Background(), tenantID, agentID, store.AgentStatusSummonFailed) return } soulContent = soulFiles[bootstrap.SoulFile] @@ -155,7 +155,7 @@ func (s *AgentSummoner) SummonAgent(agentID uuid.UUID, tenantID uuid.UUID, provi if idErr != nil { slog.Warn("summoning: IDENTITY.md generation failed", "agent", agentID, "error", idErr) s.emitEvent(agentID, tenantID, SummonEventFailed, "", idErr.Error()) - s.setAgentStatus(context.Background(), agentID, store.AgentStatusSummonFailed) + s.setAgentStatus(context.Background(), tenantID, agentID, store.AgentStatusSummonFailed) return } identityContent = idFiles[bootstrap.IdentityFile] @@ -198,7 +198,7 @@ func (s *AgentSummoner) finishSummon(ctx context.Context, agentID, tenantID uuid slog.Warn("summoning: failed to save agent metadata", "agent", agentID, "error", err) } } - s.setAgentStatus(ctx, agentID, store.AgentStatusActive) + s.setAgentStatus(ctx, tenantID, agentID, store.AgentStatusActive) s.emitEvent(agentID, tenantID, SummonEventCompleted, "", "") slog.Info("summoning: completed", "agent", agentID) } diff --git a/internal/http/summoner_regenerate.go b/internal/http/summoner_regenerate.go index 9f182dcc..2475387a 100644 --- a/internal/http/summoner_regenerate.go +++ b/internal/http/summoner_regenerate.go @@ -33,7 +33,7 @@ func (s *AgentSummoner) RegenerateAgent(agentID uuid.UUID, tenantID uuid.UUID, p if err != nil { slog.Warn("summoning: failed to read existing files", "agent", agentID, "error", err) s.emitEvent(agentID, tenantID, SummonEventFailed, "", err.Error()) - s.setAgentStatus(context.Background(), agentID, store.AgentStatusSummonFailed) + s.setAgentStatus(context.Background(), tenantID, agentID, store.AgentStatusSummonFailed) return } @@ -44,7 +44,7 @@ func (s *AgentSummoner) RegenerateAgent(agentID uuid.UUID, tenantID uuid.UUID, p slog.Warn("summoning: regeneration failed", "agent", agentID, "error", err) s.emitEvent(agentID, tenantID, SummonEventFailed, "", err.Error()) // Use fresh context — the original may have timed out, but we still need to update status. - s.setAgentStatus(context.Background(), agentID, store.AgentStatusSummonFailed) + s.setAgentStatus(context.Background(), tenantID, agentID, store.AgentStatusSummonFailed) return } @@ -64,7 +64,7 @@ func (s *AgentSummoner) RegenerateAgent(agentID uuid.UUID, tenantID uuid.UUID, p } } - s.setAgentStatus(ctx, agentID, store.AgentStatusActive) + s.setAgentStatus(ctx, tenantID, agentID, store.AgentStatusActive) s.emitEvent(agentID, tenantID, SummonEventCompleted, "", "") slog.Info("summoning: regeneration completed", "agent", agentID, "files", len(files)) @@ -191,7 +191,15 @@ func (s *AgentSummoner) ensureUserPredefined(ctx context.Context, agentID uuid.U } } -func (s *AgentSummoner) setAgentStatus(ctx context.Context, agentID uuid.UUID, status string) { +func (s *AgentSummoner) setAgentStatus(ctx context.Context, tenantID, agentID uuid.UUID, status string) { + // Summoning frequently calls this after a timeout/cancel path with context.Background(). + // Re-attach tenant scope so AgentStore.Update targets the right tenant row. + if store.TenantIDFromContext(ctx) == uuid.Nil && !store.IsCrossTenant(ctx) { + if tenantID == uuid.Nil { + tenantID = store.MasterTenantID + } + ctx = store.WithTenantID(ctx, tenantID) + } if err := s.agents.Update(ctx, agentID, map[string]any{"status": status}); err != nil { slog.Warn("summoning: failed to update agent status", "agent", agentID, "status", status, "error", err) }