on main help sign in
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.

commit3cd88ac8902c1ce421d9a2b32ae0ef7b9578d35e authorKieran Klukas <kieran@dunkirk.sh> dateThu 28 May 2026, 15:31 (5 months ago) parentd87a632
1 file changed+25−12
internal/agent/coordinator.go+25−12
internal/agent/coordinator.go+25−12
@@ -1170,18 +1170,31 @@ func (c *coordinator) runSubAgent(ctx context.Context, params subAgentParams) (f
11701170 }
11711171
11721172 // Run the agent
1173− result, err := params.Agent.Run(ctx, SessionAgentCall{
1174− SessionID: session.ID,
1175− Prompt: params.Prompt,
1176− MaxOutputTokens: maxTokens,
1177− ProviderOptions: getProviderOptions(model, providerCfg),
1178− Temperature: model.ModelCfg.Temperature,
1179− TopP: model.ModelCfg.TopP,
1180− TopK: model.ModelCfg.TopK,
1181− FrequencyPenalty: model.ModelCfg.FrequencyPenalty,
1182− PresencePenalty: model.ModelCfg.PresencePenalty,
1183− NonInteractive: true,
1184− })
1173+ run := func() (*fantasy.AgentResult, error) {
1174+ return params.Agent.Run(ctx, SessionAgentCall{
1175+ SessionID: session.ID,
1176+ Prompt: params.Prompt,
1177+ MaxOutputTokens: maxTokens,
1178+ ProviderOptions: getProviderOptions(model, providerCfg),
1179+ Temperature: model.ModelCfg.Temperature,
1180+ TopP: model.ModelCfg.TopP,
1181+ TopK: model.ModelCfg.TopK,
1182+ FrequencyPenalty: model.ModelCfg.FrequencyPenalty,
1183+ PresencePenalty: model.ModelCfg.PresencePenalty,
1184+ NonInteractive: true,
1185+ })
1186+ }
1187+ result, err := run()
1188+ if err != nil && c.isUnauthorized(err) {
1189+ if retryErr := c.retryAfterUnauthorized(ctx, providerCfg); retryErr == nil {
1190+ result, err = run()
1191+ } else if c.notify != nil && model.ModelCfg.Provider == hyper.Name {
1192+ c.notify.Publish(pubsub.CreatedEvent, notify.Notification{
1193+ Type: notify.TypeReAuthenticate,
1194+ ProviderID: model.ModelCfg.Provider,
1195+ })
1196+ }
1197+ }
11851198 if err != nil {
11861199 return fantasy.NewTextErrorResponse(fmt.Sprintf("Failed to generate response: %s", err)), nil
11871200 }