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

  1. Add a `provider` input transform to the aiagent module's value (e.g. {"type":"aiagent","provider":{...}} with a valid provider config).
  2. Or set an `agent` path on the module linking it to an existing saved agent in the workspace.
  3. 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

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


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/07aa7367bd85e31d. Report an issue: GitHub.