{"record":{"id":"dc8ae320e92b6cf7","repo":"n8n-io/n8n","slug":"from-ai-in-non-tool","errorCode":"FROM_AI_IN_NON_TOOL","errorMessage":"'${node.name}' uses $fromAI() which is only valid in tool nodes connected to an AI agent.","messagePattern":"'(.+?)' uses \\$fromAI\\(\\) which is only valid in tool nodes connected to an AI agent\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/@n8n/workflow-sdk/src/workflow-builder/plugins/validators/from-ai-validator.ts","lineNumber":43,"sourceCode":"\t\t_graphNode: GraphNode,\n\t\t_ctx: PluginContext,\n\t): ValidationIssue[] {\n\t\tconst issues: ValidationIssue[] = [];\n\n\t\t// $fromAI is valid in tool nodes\n\t\tif (isToolNode(node.type)) {\n\t\t\treturn issues;\n\t\t}\n\n\t\tconst params = node.config?.parameters;\n\t\tif (!params) {\n\t\t\treturn issues;\n\t\t}\n\n\t\t// Recursively search for $fromAI in all parameter values\n\t\tif (containsFromAI(params)) {\n\t\t\tissues.push({\n\t\t\t\tcode: 'FROM_AI_IN_NON_TOOL',\n\t\t\t\tmessage: `'${node.name}' uses $fromAI() which is only valid in tool nodes connected to an AI agent.`,\n\t\t\t\tseverity: 'warning',\n\t\t\t\tviolationLevel: 'major',\n\t\t\t\tnodeName: node.name,\n\t\t\t});\n\t\t}\n\n\t\treturn issues;\n\t},\n};\n","sourceCodeStart":25,"sourceCodeEnd":54,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/workflow-sdk/src/workflow-builder/plugins/validators/from-ai-validator.ts#L25-L54","documentation":"Warning-level validator issue (code FROM_AI_IN_NON_TOOL, violationLevel 'major') emitted when a non-tool node uses $fromAI() in its parameters. $fromAI() is only valid inside tool nodes connected to an AI agent, where it lets the agent supply values dynamically. Using it elsewhere has no runtime backing and will not behave as expected.","triggerScenarios":"Adding '={{ $fromAI(\"x\") }}' to a regular node (e.g. HTTP Request, Set) that is not a tool; copying a tool-only expression into a non-tool node.","commonSituations":"LLM-generated workflows that sprinkle $fromAI everywhere; misunderstanding that $fromAI requires a tool+agent context; refactoring that moved an expression out of a tool.","solutions":["Move the $fromAI() usage into a tool node that is connected to an AI agent.","If the node must be a tool, change its type to a recognized tool node (isToolNode true).","Replace $fromAI() with a concrete value or a $json expression for non-tool nodes."],"exampleFix":"// before\nhttpRequest({ url: '={{ $fromAI(\"endpoint\") }}' }) // not a tool\n// after\n// wrap as a tool connected to an agent\ntoolNode({ url: '={{ $fromAI(\"endpoint\") }}' })","handlingStrategy":"validation","validationCode":"import { isToolNode } from '@n8n/workflow-sdk';\n\nfunction containsFromAI(value: unknown): boolean {\n  return typeof value === 'string' && /\\$fromAI\\s*\\(/.test(value);\n}\nif (!isToolNode(node.type) && containsFromAI(node.config?.parameters)) {\n  // warn: $fromAI only valid in tool nodes\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use $fromAI() only inside tool nodes connected to an AI agent.","For non-tool nodes, replace $fromAI() with a concrete value or $json expression.","Run the from-AI validator on AI-heavy workflows."],"tags":["from-ai","validator","tool","ai-agent","expression"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}