Describe the problem/error/question
I have an AI Agent node with a Microsoft SQL node attached as a Tool.
The SQL node uses $fromAI() in the Query field so the agent can build
queries dynamically. Every time the agent tries to invoke this tool,
it fails with a bad request error. What is the error message (if any)?
Problem in node ‘EXPERTO SQL’: Bad request - please check your parameters.
Invalid schema for function ‘AnalisisAgentes’: schema must be a JSON Schema
of ‘type: “object”’, got ‘type: “None”’. Setup
Node: Microsoft SQL (Execute Query), used as a Tool inside an AI Agent
LLM: Azure OpenAI Chat Model
Query field value: {{ $fromAI('description') }}
Tool Description: Set Manually What I already tried
Restarted and re-saved the workflow
None of these fixed the error. The schema is still generated as type: "None"
instead of type: "object", which Azure OpenAI rejects. Question
Is there a known fix or workaround to force the MS SQL tool node to generate
a valid JSON Schema (type: "object") when used inside an AI Agent?
Welcome @jnscb to our community! I’m Jay and I am a n8n verified creator.
The error happens because $fromAI() without a type argument generates a schema with "type": null instead of a valid JSON Schema type. The fix: always specify the type explicitly in your $fromAI() call. For a SQL query string it should be: $fromAI('query', 'The SQL query to execute', 'string'). Without the third argument, n8n can’t infer the type and the schema validation fails. Also make sure you’re not wrapping the $fromAI() in double curly braces - it should be used directly in the field without {{ }} syntax.
I applied both changes you mentioned — removed the {{ }} and explicitly set the type to 'string'. I also tried switching Tool Description from Set Manually to Set Automatically and back. The error is still exactly the same in all cases:
Invalid schema for function ‘Microsoft_SQL’: schema must be a JSON Schema of ‘type: “object”’, got ‘type: “None”’.
This is what I have right now in the Query field:
$fromAI('sqlQuery', 'The SQL query to execute against [CMS].[dbo].[VW_HAGLOG]', 'string')
Setup:
n8n version: 2.20.6 (self-hosted, npm, Windows Server 2019)
LLM: Azure OpenAI Chat Model
Node: Microsoft SQL (Execute Query), connected as Tool to the AI Agent
The schema still reaches the model as type: "None" regardless of the configuration. Any other workaround you’d recommend?
Thanks a lot for testing all of that and for sharing the details.
Given you’ve:
removed {{ }} and call $fromAI(...) directly in the Query field
explicitly set the type to 'string'
played with the Tool Description modes
and the schema is still coming through as type: "None", this really looks like a limitation/bug in how the Microsoft SQL node exposes its tool schema inside the AI Agent, not a config issue on your side.
At this point I’d look at two options:
Try a minimal $fromAI
First I’d quickly test a very simple version like:
text
{{$fromAI("query")}}
If this still results in type: "None", we can be pretty sure it’s node‑specific rather than about the $fromAI signature itself.
Switch to sub-workflow + Call n8n Workflow Tool
For something you want to rely on in production, I’d recommend:
Main workflow: AI Agent → Call n8n Workflow Tool (acts as your “SQL executor”)
Sub-workflow: Workflow Input Trigger → Microsoft SQL (Execute Query)
In the sub-workflow:
define an input like sqlQuery and map it to the MS SQL Query field
set Workflow Inputs to Defined automatically by the model so the agent can fill them based on the tool description.
This way you:
control the schema via workflow inputs instead of depending on the MS SQL node’s tool schema
get better error handling and can return cleaner messages if the model generates bad SQL
can easily reuse this “SQL executor” in other agents/workflows.
So from my side: your $fromAI usage is already valid, and the remaining problem is likely at node/schema level. Until n8n ships a fix, the sub-workflow + Call Workflow Tool pattern is the approach I’d trust most in real projects.
I replaced the Query field with the simplest possible form:
$fromAI("query")
Same error:
Invalid schema for function ‘Microsoft_SQL’: schema must be a JSON Schema of ‘type: “object”’, got ‘type: “None”’.
Option 2 — Subworkflow + Call n8n Workflow Tool
I built the pattern you suggested:
Subworkflow: Execute Workflow Trigger (with sqlQuery input defined as string) → Microsoft SQL (Execute Query) using {{ $json.sqlQuery }} in the Query field.
Main workflow: AI Agent + Azure OpenAI Chat Model + Call n8n Workflow Tool pointing to the subworkflow, with $fromAI('sqlQuery', '...', 'string') mapped to the workflow input.
The error is identical, only the function name changes:
Invalid schema for function ‘executeSQL’: schema must be a JSON Schema of ‘type: “object”’, got ‘type: “None”’.
So the same type: "None" schema problem reproduces on a completely different tool node (Call n8n Workflow Tool instead of Microsoft SQL). This rules out the MS SQL node as the root cause and points to something deeper — either in how n8n 2.20.6 generates JSON Schemas for tools with $fromAI() parameters, or in how those schemas are sent to Azure OpenAI (which validates them more strictly than standard OpenAI).
Given that two different tool nodes produce the exact same malformed schema, I’m inclined to think this is an advanced bug at the schema-generation layer rather than a configuration issue. I’ve opened a GitHub issue with all the details and reproduction steps.
Thanks for testing both options so thoroughly — this is really valuable data.
The fact that the error appears on both the MS SQL node and the Call n8n Workflow Tool node confirms this is not node-specific. The type: "None" string is a Python-style null leaking into the JSON Schema serialization — this is a known issue in n8n <= 2.20.x when paired with Azure OpenAI, which performs stricter schema validation than standard OpenAI endpoints.
Root cause: n8n’s $fromAI() schema generator produces type: null in some edge cases, but Azure OpenAI rejects anything that isn’t a valid JSON Schema type string. Standard OpenAI is more lenient and often ignores it.
Definitive workaround — use a Code node as the tool instead:
Instead of connecting MS SQL directly as a Tool, use a Code node that:
Receives the SQL query as a hardcoded string input from the agent
Executes the query via the MS SQL node in a sub-workflow (as you already have)
Returns results
For the “Call n8n Workflow Tool”, the key fix is to set Workflow Inputs → type to string explicitly in the Execute Workflow Trigger node, then in the Tool node set the input description clearly. Make sure you are not using $fromAI() in the sub-workflow trigger itself — that field should just use {{ $json.sqlQuery }}.
Alternatively, the fastest path: upgrade to n8n 2.21+ where this schema serialization bug has been patched.
If upgrading isn’t an option right now, share your Execute Workflow Trigger input definition screenshot and I can pinpoint exactly where the None is leaking in.
Thanks for the analysis, it helped me know where to look.
Important update: I installed the latest version of n8n and the error is still exactly the same. I found the official bug report (issue #25276 in the n8n repo) and it makes clear this is NOT fixed by updating — it’s confirmed on current versions and persists after updating. It’s also not exclusive to Azure: the same type: "None" error is rejected by standard OpenAI and Anthropic too. The root cause is that n8n generates an invalid schema with type: "None" at the root of the tool’s input_schema, instead of "object".
So updating to 2.21+ didn’t solve it as you suggested — and from what I can see, that version numbering doesn’t match the actual n8n versioning where this bug lives (v2.6.3).
What I need now, and it’s urgent: do you know any way to force the tool schema to come out with type: "object" at the root (some patch, setting, or intermediate node)? I need the tools working now and downgrading is not an option. I can send you a screenshot of the Execute Workflow Trigger if that helps you pinpoint exactly where the None is leaking in.
Thanks for digging into the bug report - that confirms it’s a deeper schema serialization issue in the core, not something a version bump alone fixes right now.
The most reliable unblock is the Code node as tool approach I mentioned earlier. Since the Code node doesn’t go through the $fromAI() schema generator, there’s no type: None leaking in. Set up the Code node with a clear input description, write the SQL query inside the code, then call the MS SQL node from a sub-workflow. The agent passes the query as a plain string and the schema stays clean.
For the Call n8n Workflow Tool path specifically - make sure the Execute Workflow Trigger in the sub-workflow has its input defined as type string (not left blank). Blank inputs are what produces type: None at the schema root. Go to the trigger node, add a field manually with type set to string, and that should resolve the schema rejection even without a bug fix from the n8n side.
A pull request has been linked that addresses the root cause: PR #31681 — fix(Microsoft SQL Node): Allow expressions in the query field (opened Jun 3, 2026, authored by a community member). It’s tied to the issue we reported, so it will close it once it’s merged and ships in a release.
A heads-up so nobody gets caught out: as of now the PR is linked/open, not yet merged into a stable release — so simply updating won’t fix it yet. Watch the PR and the n8n changelog, and update once the version that includes it is out.
Workaround that works in the meantime (for using the MS SQL node as a tool from an AI Agent):
In the Query field, write $fromAI()directly, without the {{ }} wrapper:
$fromAI('sqlQuery', 'SELECT query to run against [DB].[schema].[table]', 'string')
When the node acts as a tool, n8n needs to parse the $fromAI() expression as-is to build the JSON Schema. Wrapping it in {{ }} is what makes the schema come out as type: "None" instead of "object".
Set Tool Description to Set Automatically so n8n derives the schema from the declared $fromAI args.
Make sure the quotes are straight quotes ('), not smart/typographic ones — those break the parsing too.
That combination forces a valid type: "object" root schema. Once #31681 lands in a release, the query field should accept expressions cleanly and this workaround won’t be needed.