windmill-labs/windmill · error
AI agent modules ${providerless.map((id) => `"${id}"`).join(
Error message
AI agent modules ${providerless.map((id) => `"${id}"`).join(', ')} need a provider input transform, or an "agent" path linking them to a saved agent What it means
validateFlowModules in the AI copilot's editable-flow validator rejects a flow whose AiAgent step has neither a `provider` input transform nor an `agent` path to a saved agent. This is thrown because the flow schema cannot express 'provider required only when standalone' (a conditional union would break the FlowModuleValue discriminated union), so the invariant is enforced imperatively after zod parsing. It guarantees every AI agent step the LLM wrote is actually runnable.
Source
Thrown at frontend/src/lib/components/copilot/chat/flow/editableFlowJson.ts:272
const ids = collectAllFlowModuleIdsFromModules(parsedModules)
if (ids.length !== new Set(ids).size) {
throw new Error('Duplicate module IDs found in flow')
}
const reservedIds = ids.filter(
(id) => id === SPECIAL_MODULE_IDS.PREPROCESSOR || id === SPECIAL_MODULE_IDS.FAILURE
)
if (reservedIds.length > 0) {
throw new Error(
'Special modules must be provided via preprocessor_module and failure_module, not inside modules'
)
}
// Not expressible in the schema: `provider` is required only when the step is standalone, and
// making AiAgent a conditional union breaks the FlowModuleValue discriminated union it belongs to.
const providerless = collectProviderlessAgentIds(parsedModules)
if (providerless.length > 0) {
throw new Error(
`AI agent modules ${providerless
.map((id) => `"${id}"`)
.join(
', '
)} need a provider input transform, or an "agent" path linking them to a saved agent`
)
}
// An agent tool's `summary` is the name the LLM sees; the worker rejects anything outside
// `^[a-zA-Z0-9_]+$`, so a flow written with a spaced name saves but fails on every run.
const invalidToolNames = collectInvalidAgentToolNames(parsedModules)
if (invalidToolNames.length > 0) {
throw new Error(
`Invalid AI agent tool name(s): ${invalidToolNames
.map(
(t) =>
`agent "${t.agentId}" tool "${t.toolId}" is named ${JSON.stringify(t.name)} - ${t.error}`
)View on GitHub (pinned to e474e8803c)
Solutions
- Add a `provider` input transform to the aiagent module's value (e.g. {"type":"aiagent","provider":{...}} with a valid provider config).
- Or set an `agent` path on the module linking it to an existing saved agent in the workspace.
- Check the listed module id(s) in the message and fix only those steps, then retry the tool call.
Example fix
// before
{"id":"m1","value":{"type":"aiagent","tools":[]}}
// after
{"id":"m1","value":{"type":"aiagent","tools":[],"provider":{"openai":{"model":"gpt-4o"}}}} Defensive patterns
Strategy: validation
Validate before calling
function agentModulesNeedProvider(modules) {
return (modules ?? []).filter(m =>
m?.value?.type === 'aiagent' && !m.value.provider && !m.value.agent
).map(m => m.id)
}
const bad = agentModulesNeedProvider(flow.modules)
if (bad.length) throw new Error(`Agents missing provider/agent path: ${bad.join(', ')}`) Type guard
function hasAgentConfig(m) {
return m?.value?.type === 'aiagent' &&
(m.value.provider != null || typeof m.value.agent === 'string' && m.value.agent.length > 0)
} Try / catch
try {
const editable = validateEditableFlowJson(rawFlow)
// use editable
} catch (e) {
if (String(e.message).includes('need a provider input transform')) {
// surface message to the LLM so it rewrites the agent step with a provider or agent path
} else throw e
} Prevention
- Always give standalone aiagent steps a provider config when generating flow JSON
- Use an `agent` path referencing a saved agent when reusing workspace agents
- Keep a flow-JSON template that includes a provider field on every aiagent step
When it happens
Trigger: Calling the flowTools/modules copilot tools with a flow JSON containing an aiagent module whose value has no `provider` input transform and no `agent` path (e.g. the model omitted provider when generating a standalone agent step).
Common situations: An LLM generates a flow with an AI agent step but forgets the provider field; a user hand-edits flow JSON and deletes the provider transform; a template is copied with the agent path stripped.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Invalid AI agent provider configuration: ${errors.join('\n')
- Invalid AI agent tool name(s): ${invalidToolNames.map((t) =>
- Flow JSON must be an object
- Unknown top-level flow key(s): ${unknownKeys.join(', ')}. Al
- search_app requires a non-empty query.
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/07aa7367bd85e31d.
Report an issue: GitHub.