{"record":{"id":"06025b6d4b751fa1","repo":"FlowiseAI/Flowise","slug":"agent-must-have-a-predecessor","errorCode":null,"errorMessage":"Agent must have a predecessor!","messagePattern":"Agent must have a predecessor!","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/components/nodes/sequentialagents/Agent/Agent.ts","lineNumber":483,"sourceCode":"    async init(nodeData: INodeData, input: string, options: ICommonObject): Promise<any> {\n        let tools = nodeData.inputs?.tools\n        tools = flatten(tools)\n        let agentSystemPrompt = nodeData.inputs?.systemMessagePrompt as string\n        agentSystemPrompt = transformBracesWithColon(agentSystemPrompt)\n        let agentHumanPrompt = nodeData.inputs?.humanMessagePrompt as string\n        agentHumanPrompt = transformBracesWithColon(agentHumanPrompt)\n        const agentLabel = nodeData.inputs?.agentName as string\n        const sequentialNodes = nodeData.inputs?.sequentialNode as ISeqAgentNode[]\n        const maxIterations = nodeData.inputs?.maxIterations as string\n        const model = nodeData.inputs?.model as BaseChatModel\n        const promptValuesStr = nodeData.inputs?.promptValues\n        const output = nodeData.outputs?.output as string\n        const approvalPrompt = nodeData.inputs?.approvalPrompt as string\n\n        if (!agentLabel) throw new Error('Agent name is required!')\n        const agentName = agentLabel.toLowerCase().replace(/\\s/g, '_').trim()\n\n        if (!sequentialNodes || !sequentialNodes.length) throw new Error('Agent must have a predecessor!')\n\n        let agentInputVariablesValues: ICommonObject = {}\n        if (promptValuesStr) {\n            try {\n                agentInputVariablesValues = typeof promptValuesStr === 'object' ? promptValuesStr : JSON.parse(promptValuesStr)\n            } catch (exception) {\n                throw new Error(\"Invalid JSON in the Agent's Prompt Input Values: \" + exception)\n            }\n        }\n        agentInputVariablesValues = handleEscapeCharacters(agentInputVariablesValues, true)\n\n        const startLLM = sequentialNodes[0].startLLM\n        const llm = model || startLLM\n        if (nodeData.inputs) nodeData.inputs.model = llm\n\n        const multiModalMessageContent = sequentialNodes[0]?.multiModalMessageContent || (await processImageMessage(llm, nodeData, options))\n        const abortControllerSignal = options.signal as AbortController\n        const agentInputVariables = uniq([...getInputVariables(agentSystemPrompt), ...getInputVariables(agentHumanPrompt)])","sourceCodeStart":465,"sourceCodeEnd":501,"githubUrl":"https://github.com/FlowiseAI/Flowise/blob/abe4a8601a058047b350c260676826e21dd14101/packages/components/nodes/sequentialagents/Agent/Agent.ts#L465-L501","documentation":"Thrown by Agent_SeqAgents.init when the `sequentialNode` input is undefined, null, or an empty array. Sequential agents run inside a LangGraph-style state graph, so every Agent must inherit `startLLM`, `multiModalMessageContent`, and `predecessorAgents` from an upstream node. Without a predecessor the agent has no LLM to bind tools to and no state to read from, so init refuses to proceed.","triggerScenarios":"Calling `Agent_SeqAgents.init(nodeData, input, options)` where `nodeData.inputs.sequentialNode` resolves to undefined or `[]`. This happens when the canvas edge from a Start/Agent/Condition node into this Agent's `sequentialNode` input anchor is missing.","commonSituations":"User dragged an Agent onto the canvas but never wired a sequential edge from a predecessor; the first node in the graph is an Agent instead of a Sequential Agents Start node; node JSON was imported/exported and the edge metadata was dropped; a predecessor node errored on init so its `ISeqAgentNode` was never pushed into `sequentialNode`.","solutions":["In the Flowise canvas, draw a sequential edge from a Start node (or another Agent/Condition/ConditionAgent) into this Agent's `sequentialNode` input anchor.","Make the first node in the sequential-agents canvas a Start node — it seeds `startLLM` and `sequentialNode` for downstream nodes.","If invoking programmatically, verify `nodeData.inputs.sequentialNode` is a non-empty array of ISeqAgentNode before calling init.","Re-open the flow and re-save after wiring so the edge is persisted in the chatflow JSON."],"exampleFix":"// before\nconst nodeData = { inputs: { agentName: 'Researcher', sequentialNode: undefined } }\nawait agent.init(nodeData, input, options) // throws [280]\n\n// after\nconst nodeData = { inputs: { agentName: 'Researcher', sequentialNode: [{ id: 'start', startLLM, ... }] } }\nawait agent.init(nodeData, input, options)","handlingStrategy":"validation","validationCode":"function validateAgentPredecessor(nodeData) {\n  const seq = nodeData?.inputs?.sequentialNode\n  if (!Array.isArray(seq) || seq.length === 0) {\n    return { ok: false, message: 'Agent must have a predecessor! Wire a sequential edge from a Start/Agent node.' }\n  }\n  if (!seq[0]?.startLLM) {\n    return { ok: false, message: 'Predecessor is missing startLLM — ensure the upstream node is a Sequential Agents Start node.' }\n  }\n  return { ok: true }\n}\n\n// before init\nconst check = validateAgentPredecessor(nodeData)\nif (!check.ok) throw new Error(check.message)","typeGuard":"function isNonEmptySeqAgentNodeArray(v): v is ISeqAgentNode[] {\n  return Array.isArray(v) && v.length > 0 && typeof v[0]?.startLLM !== 'undefined'\n}","tryCatchPattern":null,"preventionTips":["Always place a Sequential Agents Start node as the first node in the canvas so downstream nodes inherit startLLM.","After importing a flow, re-save it once the edges are visible to persist wiring metadata.","When invoking programmatically, validate `sequentialNode` length before calling init."],"tags":["sequential-agents","graph-wiring","validation","configuration"],"backgroundTag":null,"analyzedSha":"abe4a8601a058047b350c260676826e21dd14101","analyzedAt":"2026-08-12T16:04:40.823Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}