From 1c7ec580570f195264d2fc7ddd6a343c1370d34c Mon Sep 17 00:00:00 2001 From: Hari Krishna Date: Thu, 12 Mar 2026 19:45:20 +0530 Subject: [PATCH 1/4] add http app --- ai.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ai.go b/ai.go index 93b665d4..ee45a847 100644 --- a/ai.go +++ b/ai.go @@ -7636,6 +7636,11 @@ func HandleAiAgentExecutionStart(execution WorkflowExecution, startNode Action, decidedApps += lowername + ", " } + + // Let's inject http. + if !strings.Contains(decidedApps, "http") { + decidedApps += "http, " + } } if len(decidedApps) > 0 { @@ -8676,6 +8681,10 @@ You are the Action Execution Agent for the Shuffle platform. You receive tools ( } } } + + if createNextActions { + return startNode, nil + } // 1. Map the response back newResult, err := json.Marshal(resultMapping) From 985eda466c8b2e6b8c69cae06b8fd5a6e17d3167 Mon Sep 17 00:00:00 2001 From: Hari Krishna Date: Thu, 12 Mar 2026 19:45:45 +0530 Subject: [PATCH 2/4] fix agent stuck loading due to timeout --- db-connector.go | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/db-connector.go b/db-connector.go index 2cad9091..35bff75f 100755 --- a/db-connector.go +++ b/db-connector.go @@ -2017,7 +2017,7 @@ func Fixexecution(ctx context.Context, workflowExecution WorkflowExecution) (Wor finishedDecisions = append(finishedDecisions, decision.RunDetails.Id) continue } else if decision.RunDetails.Status == "FAILURE" { - //finishedDecisions = append(finishedDecisions, decision.RunDetails.Id) + finishedDecisions = append(finishedDecisions, decision.RunDetails.Id) failedFound = true continue } else if decision.RunDetails.Status == "RUNNING" && decision.Action != "ask" { @@ -2030,8 +2030,11 @@ func Fixexecution(ctx context.Context, workflowExecution WorkflowExecution) (Wor mappedOutput.Decisions[decisionIndex].RunDetails.Status = "FAILURE" mappedOutput.Decisions[decisionIndex].RunDetails.CompletedAt = time.Now().Unix() mappedOutput.Decisions[decisionIndex].RunDetails.RawResponse += "\n[ERROR] Decision marked as FAILURE due to 5 minute timeout." - } + // Count this as finished + failed so recovery triggers in the same Fixexecution run + finishedDecisions = append(finishedDecisions, decision.RunDetails.Id) + failedFound = true + } } else { if decision.RunDetails.CompletedAt > 0 { if debug { @@ -2133,7 +2136,7 @@ func Fixexecution(ctx context.Context, workflowExecution WorkflowExecution) (Wor go sendAgentActionSelfRequest("SUCCESS", workflowExecution, workflowExecution.Results[resultIndex]) }() } else { - log.Printf("[INFO][%s] All decisions finished for agent action %s - but no finish action found, marking as WAITING.", workflowExecution.ExecutionId, action.ID) + log.Printf("[INFO][%s] All decisions finished for agent action %s - but no finish action found. Re-invoking agent to finalize (failedFound: %t).", workflowExecution.ExecutionId, action.ID, failedFound) mappedOutput.Status = "RUNNING" mappedOutput.CompletedAt = 0 @@ -2143,10 +2146,16 @@ func Fixexecution(ctx context.Context, workflowExecution WorkflowExecution) (Wor workflowExecution.Status = "EXECUTING" } - // To ensure the execution is actually updated + // Re-invoke the agent so the LLM can see the failure and produce a proper "finish" decision. + + capturedExec := workflowExecution + capturedAction := action go func() { - time.Sleep(1 * time.Second) - sendAgentActionSelfRequest("WAITING", workflowExecution, workflowExecution.Results[resultIndex]) + time.Sleep(2 * time.Second) + _, err := HandleAiAgentExecutionStart(capturedExec, capturedAction, true) + if err != nil { + log.Printf("[ERROR][%s] Failed re-invoking agent after decisions completed for action %s: %s", capturedExec.ExecutionId, capturedAction.ID, err) + } }() } } else if (result.Status == "" || result.Status == "WAITING") && mappedOutput.Status == "FINISHED" { From 392ca5670effc377cd6a9a8da21a6015b81e6f87 Mon Sep 17 00:00:00 2001 From: Hari Krishna Date: Thu, 12 Mar 2026 19:46:08 +0530 Subject: [PATCH 3/4] added auth injection for other internal apps as well --- shared.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/shared.go b/shared.go index 0164c500..301829f2 100644 --- a/shared.go +++ b/shared.go @@ -17760,7 +17760,15 @@ func handleAgentDecisionStreamResult(workflowExecution WorkflowExecution, action // Handle agent decisionmaking. Use the same log.Printf("[INFO][%s] With the agent being finished, we are asking it whether it would like to do anything else", workflowExecution.ExecutionId) - returnAction, err := HandleAiAgentExecutionStart(workflowExecution, actionResult.Action, true) + var originalAction Action + if foundActionResultIndex >= 0 && foundActionResultIndex < len(workflowExecution.Results) { + originalAction = workflowExecution.Results[foundActionResultIndex].Action + } else { + // Fallback in case of an issue + originalAction = actionResult.Action + } + + returnAction, err := HandleAiAgentExecutionStart(workflowExecution, originalAction, true) if err != nil { log.Printf("[ERROR][%s] Failed handling agent execution start: %s", workflowExecution.ExecutionId, err) } @@ -22079,6 +22087,14 @@ func PrepareSingleAction(ctx context.Context, user User, appId string, body []by workflowExecution.OrgId = user.ActiveOrg.Id } + formattedAppName := strings.ReplaceAll(strings.ToLower(app.Name), " ", "_") + + isInternalShuffleApp := false + switch formattedAppName { + case "shuffle_datastore", "shuffle_org_management", "shuffle_app_management", "shuffle_workflow_management": + isInternalShuffleApp = true + } + if len(app.Name) == 0 && len(action.AppName) > 0 { app.Name = action.AppName } From cff8a26d590c2ac5b8e0fee46e8be941728f0cc3 Mon Sep 17 00:00:00 2001 From: Hari Krishna Date: Wed, 1 Apr 2026 19:58:58 +0530 Subject: [PATCH 4/4] include more conditions --- ai.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ai.go b/ai.go index ee45a847..d6406f00 100644 --- a/ai.go +++ b/ai.go @@ -8629,7 +8629,7 @@ You are the Action Execution Agent for the Shuffle platform. You receive tools ( //log.Printf("[INFO] AI_AGENT_FINISH: execution_id=%s status=%s duration=%ds decisions=%d", execution.ExecutionId, agentOutput.Status, time.Now().Unix()-agentOutput.StartedAt, len(agentOutput.Decisions)) - if agentOutput.Status == "FINISHED" && agentOutput.CompletedAt > 0 && execution.Status == "EXECUTING" { + if agentOutput.Status == "FINISHED" && agentOutput.CompletedAt > 0 && execution.Status != "ABORTED" && execution.Status != "FAILURE" { duration := agentOutput.CompletedAt - agentOutput.StartedAt log.Printf("[INFO][%s] AI_AGENT_COMPLETE: org=%s duration=%ds decisions=%d llm_calls=%d total_tokens=%d status=SUCCESS", execution.ExecutionId, execution.Workflow.OrgId, duration, len(agentOutput.Decisions), agentOutput.LLMCallCount, agentOutput.TotalTokens) for resultIndex, result := range execution.Results {