From 3cd88ac8902c1ce421d9a2b32ae0ef7b9578d35e Mon Sep 17 00:00:00 2001 From: Kieran Klukas Date: Thu, 28 May 2026 15:31:00 -0400 Subject: [PATCH] fix(agent): add 401 retry and reauth notification to sub-agent runs Sub-agents (agent tool, agentic fetch) had no retry logic on 401. After moving the reauth notification from agent to coordinator, sub-agent 401s would silently fail with no recovery or user prompt. Add retry-after-unauthorized matching Run/Summarize, and publish TypeReAuthenticate if the retry also fails so the user isn't left with a dead agent and a confusing tool error. --- internal/agent/coordinator.go | 37 +++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/internal/agent/coordinator.go b/internal/agent/coordinator.go index 860db8b36cb67c43667a0f4a0dfa0a8b1d2e3992..1006fe2551f60e4b3c8b46f130296750057e5e88 100644 --- a/internal/agent/coordinator.go +++ b/internal/agent/coordinator.go @@ -1170,18 +1170,31 @@ func (c *coordinator) runSubAgent(ctx context.Context, params subAgentParams) (f } // Run the agent - result, err := params.Agent.Run(ctx, SessionAgentCall{ - SessionID: session.ID, - Prompt: params.Prompt, - MaxOutputTokens: maxTokens, - ProviderOptions: getProviderOptions(model, providerCfg), - Temperature: model.ModelCfg.Temperature, - TopP: model.ModelCfg.TopP, - TopK: model.ModelCfg.TopK, - FrequencyPenalty: model.ModelCfg.FrequencyPenalty, - PresencePenalty: model.ModelCfg.PresencePenalty, - NonInteractive: true, - }) + run := func() (*fantasy.AgentResult, error) { + return params.Agent.Run(ctx, SessionAgentCall{ + SessionID: session.ID, + Prompt: params.Prompt, + MaxOutputTokens: maxTokens, + ProviderOptions: getProviderOptions(model, providerCfg), + Temperature: model.ModelCfg.Temperature, + TopP: model.ModelCfg.TopP, + TopK: model.ModelCfg.TopK, + FrequencyPenalty: model.ModelCfg.FrequencyPenalty, + PresencePenalty: model.ModelCfg.PresencePenalty, + NonInteractive: true, + }) + } + result, err := run() + if err != nil && c.isUnauthorized(err) { + if retryErr := c.retryAfterUnauthorized(ctx, providerCfg); retryErr == nil { + result, err = run() + } else if c.notify != nil && model.ModelCfg.Provider == hyper.Name { + c.notify.Publish(pubsub.CreatedEvent, notify.Notification{ + Type: notify.TypeReAuthenticate, + ProviderID: model.ModelCfg.Provider, + }) + } + } if err != nil { return fantasy.NewTextErrorResponse(fmt.Sprintf("Failed to generate response: %s", err)), nil }