The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "AA Factory 01 - Plan Blueprint",
"nodes": [
{
"parameters": {},
"id": "86bc9e39-061a-4b9b-8c1d-730ddeaa16dd",
"name": "Sub-workflow Input",
"type": "n8n-nodes-base.executeWorkflowTrigger",
"typeVersion": 1,
"position": [
0,
0
]
},
{
"parameters": {
"jsCode": "const input = $json ?? {};\nconst now = new Date().toISOString();\nconst obs = input.observability ?? {};\nconst trace = Array.isArray(obs.trace) ? [...obs.trace] : [];\nconst startedAt = obs.stage_started_at ?? obs.started_at ?? now;\nconst durationMs = Math.max(0, Date.parse(now) - Date.parse(startedAt));\nconst event = {\n timestamp: now,\n correlation_id: obs.correlation_id ?? input.correlation_id ?? null,\n workflow: $workflow.name,\n execution_id: $execution.id,\n stage: 'configuration-planning',\n status: 'started',\n duration_ms: durationMs,\n ...({}),\n};\ntrace.push(event);\nconsole.log(JSON.stringify({event:'autonomous_agent_workflow_stage', ...event}));\nreturn [{json:{...input, observability:{...obs, stage_started_at:now, trace}, last_event:event}}];"
},
"id": "fe879870-c6b2-4103-9b9b-78f6a88781da",
"name": "Start Planning Trace",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
224,
0
]
},
{
"parameters": {
"task": "=You are the configuration architect for an Autonomous Agent Platform integrated with n8n. Convert the developer request below into one deployable configuration blueprint. Return exactly one JSON object containing model_policy, model_capability, execution, and optional tool at the root level. Do not wrap the result in an output property. Do not use Markdown or code fences. Select a suitable model policy and purpose; define strict JSON Schemas for the model capability and final execution. Every schema must be a complete JSON Schema object using type, properties, required, and additionalProperties where applicable; do not return a bare property map. For model capabilities use agent=model-agent and agent_version=1.0.0. Use a timeout_seconds value of at least 300 for generated model capabilities. Only when a new external/custom tool is actually required, define one custom MCP server, MCP tool registration, and matching tool capability. Prefer existing immutable core tools such as web-search, page-extract, ocr, workspace-list, workspace-read, workspace-write, and http-request instead of creating duplicates. workspace-write and python-execute are approval-sensitive. The tool registry itself is read-only, so custom tools must be represented as MCP registrations. Ensure all resource names are lowercase kebab-case, model_purpose is included in allowed_purposes, and the final execution allowed capabilities can be derived from the generated capability names. Developer request and defaults: {{ JSON.stringify($json) }}",
"contextInputMode": "json",
"contextJson": "={{ JSON.stringify({source:'n8n-workflow-factory', developerRequest:$json.request.developer_request, defaults:$json.defaults}) }}",
"includeDesiredOutput": true,
"desiredOutputSchema": "={\"type\":\"object\",\"additionalProperties\":false,\"required\":[\"model_policy\",\"model_capability\",\"execution\"],\"properties\":{\"model_policy\":{\"type\":\"object\",\"additionalProperties\":false,\"required\":[\"name\",\"model\",\"provider\",\"input_modalities\",\"maximum_input_characters\",\"maximum_output_tokens\",\"maximum_cost_units\",\"allowed_purposes\"],\"properties\":{\"name\":{\"type\":\"string\"},\"model\":{\"type\":\"string\"},\"provider\":{\"type\":\"string\",\"enum\":[\"ollama\"]},\"input_modalities\":{\"type\":\"array\",\"items\":{\"type\":\"string\",\"enum\":[\"text\",\"image\"]},\"minItems\":1},\"maximum_input_characters\":{\"type\":\"integer\",\"minimum\":1,\"maximum\":500000},\"maximum_output_tokens\":{\"type\":\"integer\",\"minimum\":1,\"maximum\":32768},\"maximum_cost_units\":{\"type\":\"integer\",\"minimum\":1,\"maximum\":1000000},\"allowed_purposes\":{\"type\":\"array\",\"items\":{\"type\":\"string\"},\"minItems\":1}}},\"model_capability\":{\"type\":\"object\",\"additionalProperties\":false,\"required\":[\"name\",\"description\",\"agent\",\"agent_version\",\"model_purpose\",\"input_modalities\",\"input_schema\",\"output_schema\",\"timeout_seconds\",\"maximum_concurrency\"],\"properties\":{\"name\":{\"type\":\"string\"},\"description\":{\"type\":\"string\"},\"agent\":{\"type\":\"string\"},\"agent_version\":{\"type\":\"string\"},\"model_purpose\":{\"type\":\"string\"},\"input_modalities\":{\"type\":\"array\",\"items\":{\"type\":\"string\",\"enum\":[\"text\",\"image\"]}},\"input_schema\":{\"type\":\"object\"},\"output_schema\":{\"type\":\"object\"},\"timeout_seconds\":{\"type\":\"integer\"},\"maximum_concurrency\":{\"type\":\"integer\"}}},\"tool\":{\"type\":[\"object\",\"null\"],\"additionalProperties\":false,\"required\":[\"server\",\"registration\",\"capability\"],\"properties\":{\"server\":{\"type\":\"object\",\"required\":[\"name\",\"base_url\"],\"properties\":{\"name\":{\"type\":\"string\"},\"base_url\":{\"type\":\"string\"},\"timeout_seconds\":{\"type\":\"integer\"},\"maximum_result_bytes\":{\"type\":\"integer\"}}},\"registration\":{\"type\":\"object\",\"required\":[\"name\",\"remote_tool_name\",\"description\",\"input_schema\",\"output_schema\",\"side_effect\",\"approval_required\"],\"properties\":{\"name\":{\"type\":\"string\"},\"remote_tool_name\":{\"type\":\"string\"},\"description\":{\"type\":\"string\"},\"adapter_type\":{\"type\":\"string\"},\"adapter_config\":{\"type\":\"object\"},\"input_schema\":{\"type\":\"object\"},\"output_schema\":{\"type\":\"object\"},\"side_effect\":{\"type\":\"string\"},\"approval_required\":{\"type\":\"boolean\"},\"timeout_seconds\":{\"type\":\"integer\"},\"maximum_result_bytes\":{\"type\":\"integer\"}}},\"capability\":{\"type\":\"object\",\"required\":[\"name\",\"description\",\"agent\",\"agent_version\",\"input_schema\",\"output_schema\",\"side_effect\",\"approval_required\"],\"properties\":{\"name\":{\"type\":\"string\"},\"description\":{\"type\":\"string\"},\"agent\":{\"type\":\"string\"},\"agent_version\":{\"type\":\"string\"},\"input_schema\":{\"type\":\"object\"},\"output_schema\":{\"type\":\"object\"},\"side_effect\":{\"type\":\"string\"},\"approval_required\":{\"type\":\"boolean\"},\"timeout_seconds\":{\"type\":\"integer\"},\"maximum_concurrency\":{\"type\":\"integer\"}}}}},\"execution\":{\"type\":\"object\",\"additionalProperties\":false,\"required\":[\"task\",\"context\",\"input_schema\",\"output_schema\",\"mode\",\"maximum_agent_calls\",\"maximum_tool_calls\"],\"properties\":{\"task\":{\"type\":\"string\"},\"context\":{\"type\":\"object\"},\"input_schema\":{\"type\":\"object\"},\"output_schema\":{\"type\":\"object\"},\"mode\":{\"type\":\"string\",\"enum\":[\"advisory\",\"supervised\",\"autonomous\"]},\"maximum_agent_calls\":{\"type\":\"integer\"},\"maximum_tool_calls\":{\"type\":\"integer\"},\"require_approval_for\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}}}}}}",
"desiredOutputMediaType": "application/json",
"includeConstraints": true,
"deadlineSeconds": 600,
"maximumAgentCalls": 4,
"maximumToolCalls": 0,
"allowedCapabilities": "task-understanding,dynamic-planning,structured-generation,result-evaluation,response-composition",
"metadataInputMode": "json",
"metadataJson": "={{ JSON.stringify({workflow:'autonomous-agent-workflow-factory', phase:'configuration-planning'}) }}",
"idempotencyKeyMode": "automatic",
"waitUntilComplete": true
},
"id": "1fab96b6-b9f6-446c-ab28-07cb230944ac",
"name": "Architect Configuration Blueprint",
"type": "n8n-nodes-autonomous-agent.autonomousAgentExecution",
"typeVersion": 1,
"position": [
464,
0
],
"credentials": {
"autonomousAgentApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "function parseMaybe(value) {\n if (typeof value !== 'string') {\n return value;\n }\n\n const trimmed = value.trim();\n\n if (!trimmed) {\n return value;\n }\n\n try {\n return JSON.parse(trimmed);\n } catch {\n return value;\n }\n}\n\nfunction isPlainObject(value) {\n return Boolean(\n value &&\n typeof value === 'object' &&\n !Array.isArray(value)\n );\n}\n\nfunction toFiniteNumber(value, fallback) {\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : fallback;\n}\n\nfunction toPositiveInteger(value, fallback, minimum = 0) {\n const parsed = Math.trunc(toFiniteNumber(value, fallback));\n return Math.max(parsed, minimum);\n}\n\nfunction toKebab(value, fallback) {\n const source =\n typeof value === 'string' && value.trim()\n ? value\n : fallback;\n\n const normalized = String(source)\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .replace(/-{2,}/g, '-');\n\n if (!normalized) {\n throw new Error(\n `Unable to create a valid kebab-case name from ${String(source)}`\n );\n }\n\n return normalized;\n}\n\nfunction uniqueStrings(values) {\n if (!Array.isArray(values)) {\n return [];\n }\n\n return [\n ...new Set(\n values\n .filter(value => typeof value === 'string')\n .map(value => value.trim())\n .filter(Boolean)\n ),\n ];\n}\n\nfunction normalizeObjectSchema(schema, requiredByDefault = true) {\n const parsed = parseMaybe(schema);\n\n if (!isPlainObject(parsed)) {\n return {\n type: 'object',\n properties: {},\n required: [],\n additionalProperties: true,\n };\n }\n\n /*\n * Preserve complete schemas that use combinators. Converting them into a\n * property map would destroy valid oneOf/anyOf/allOf contracts.\n */\n if (\n Array.isArray(parsed.oneOf) ||\n Array.isArray(parsed.anyOf) ||\n Array.isArray(parsed.allOf)\n ) {\n return parsed;\n }\n\n const schemaType = parsed.type;\n const supportsObject =\n schemaType === 'object' ||\n (\n Array.isArray(schemaType) &&\n schemaType.includes('object')\n );\n\n if (supportsObject && isPlainObject(parsed.properties)) {\n const properties = parsed.properties;\n\n return {\n ...parsed,\n required: Array.isArray(parsed.required)\n ? uniqueStrings(parsed.required)\n : requiredByDefault\n ? Object.keys(properties)\n : [],\n additionalProperties:\n typeof parsed.additionalProperties === 'boolean' ||\n isPlainObject(parsed.additionalProperties)\n ? parsed.additionalProperties\n : false,\n };\n }\n\n /*\n * An explicitly typed non-object schema must not be converted into an\n * object schema.\n */\n if (\n typeof schemaType === 'string' &&\n schemaType !== 'object'\n ) {\n return parsed;\n }\n\n if (\n Array.isArray(schemaType) &&\n !schemaType.includes('object')\n ) {\n return parsed;\n }\n\n /*\n * Support legacy bare property maps while excluding JSON Schema metadata.\n */\n const metaKeys = new Set([\n '$schema',\n '$id',\n '$ref',\n '$comment',\n 'title',\n 'description',\n 'type',\n 'properties',\n 'required',\n 'additionalProperties',\n 'definitions',\n '$defs',\n 'allOf',\n 'anyOf',\n 'oneOf',\n 'not',\n 'if',\n 'then',\n 'else',\n 'dependentSchemas',\n 'dependentRequired',\n 'patternProperties',\n 'propertyNames',\n 'unevaluatedProperties',\n 'examples',\n 'default',\n ]);\n\n const propertyEntries = Object.entries(parsed)\n .filter(([key]) => !metaKeys.has(key));\n\n if (propertyEntries.length === 0) {\n return {\n type: 'object',\n properties: {},\n required: [],\n additionalProperties: true,\n };\n }\n\n const properties = Object.fromEntries(propertyEntries);\n\n return {\n type: 'object',\n properties,\n required: requiredByDefault\n ? Object.keys(properties)\n : [],\n additionalProperties: false,\n };\n}\n\nfunction isBlueprint(value) {\n return Boolean(\n isPlainObject(value) &&\n isPlainObject(value.model_policy) &&\n isPlainObject(value.model_capability) &&\n isPlainObject(value.execution)\n );\n}\n\nfunction unwrapKnownEnvelope(value) {\n let current = parseMaybe(value);\n const visited = new Set();\n\n for (let depth = 0; depth < 12; depth += 1) {\n current = parseMaybe(current);\n\n if (isBlueprint(current)) {\n return current;\n }\n\n if (!isPlainObject(current)) {\n return null;\n }\n\n /*\n * Prevent loops if an object is referenced from more than one envelope.\n */\n if (visited.has(current)) {\n return null;\n }\n\n visited.add(current);\n\n const wrappers = [\n 'answer',\n 'output',\n 'result',\n 'structured_output',\n 'response',\n 'data',\n 'blueprint',\n 'value',\n ];\n\n let next;\n\n for (const wrapper of wrappers) {\n if (current[wrapper] !== undefined) {\n const candidate = parseMaybe(current[wrapper]);\n\n if (isBlueprint(candidate)) {\n return candidate;\n }\n\n if (\n isPlainObject(candidate) ||\n typeof candidate === 'string'\n ) {\n next = candidate;\n break;\n }\n }\n }\n\n if (next === undefined) {\n return null;\n }\n\n current = next;\n }\n\n return null;\n}\n\nfunction findBlueprint(root) {\n /*\n * Check the deterministic runtime locations first.\n *\n * Current successful platform contract:\n * output.answer -> blueprint\n *\n * Older or direct contracts remain supported for backward compatibility.\n */\n const candidates = [\n root?.output?.answer,\n root?.answer,\n root?.result?.output?.answer,\n root?.result?.answer,\n root?.result?.output,\n root?.result,\n root?.output,\n root?.structured_output,\n root?.response?.output?.answer,\n root?.response?.answer,\n root?.response?.output,\n root?.response,\n root?.data?.output?.answer,\n root?.data?.answer,\n root?.data?.output,\n root?.data,\n root?.task_results?.compose?.output?.answer,\n root?.task_results?.compose?.output,\n root?.task_results?.generate?.output,\n root,\n ];\n\n for (const candidate of candidates) {\n const blueprint = unwrapKnownEnvelope(candidate);\n\n if (blueprint) {\n return blueprint;\n }\n }\n\n return null;\n}\n\nfunction assertObject(value, fieldName) {\n if (!isPlainObject(value)) {\n throw new Error(`Missing or invalid ${fieldName}`);\n }\n\n return value;\n}\n\nfunction normalizeModelPolicy(modelPolicy, modelCapability) {\n const policy = assertObject(modelPolicy, 'model_policy');\n\n policy.name = toKebab(\n policy.name,\n `${policy.model ?? 'generated-model'}-policy`\n );\n\n policy.provider =\n typeof policy.provider === 'string' && policy.provider.trim()\n ? policy.provider.trim().toLowerCase()\n : 'ollama';\n\n policy.input_modalities =\n uniqueStrings(policy.input_modalities).length > 0\n ? uniqueStrings(policy.input_modalities)\n : ['text'];\n\n policy.maximum_input_characters = toPositiveInteger(\n policy.maximum_input_characters,\n 5000,\n 1\n );\n\n policy.maximum_output_tokens = toPositiveInteger(\n policy.maximum_output_tokens,\n 4096,\n 1\n );\n\n policy.maximum_cost_units = toPositiveInteger(\n policy.maximum_cost_units,\n 100,\n 1\n );\n\n policy.allowed_purposes = uniqueStrings(\n policy.allowed_purposes\n );\n\n const modelPurpose = modelCapability.model_purpose;\n\n if (\n typeof modelPurpose === 'string' &&\n modelPurpose.trim() &&\n !policy.allowed_purposes.includes(modelPurpose.trim())\n ) {\n policy.allowed_purposes.push(modelPurpose.trim());\n }\n\n return policy;\n}\n\nfunction normalizeModelCapability(modelCapability) {\n const capability = assertObject(\n modelCapability,\n 'model_capability'\n );\n\n capability.name = toKebab(\n capability.name,\n 'generated-model-capability'\n );\n\n capability.agent = 'model-agent';\n capability.agent_version = '1.0.0';\n\n capability.model_purpose = toKebab(\n capability.model_purpose,\n capability.name\n );\n\n capability.input_modalities =\n uniqueStrings(capability.input_modalities).length > 0\n ? uniqueStrings(capability.input_modalities)\n : ['text'];\n\n capability.timeout_seconds = toPositiveInteger(\n capability.timeout_seconds,\n 300,\n 300\n );\n\n capability.maximum_concurrency = toPositiveInteger(\n capability.maximum_concurrency,\n 1,\n 1\n );\n\n capability.input_schema = normalizeObjectSchema(\n capability.input_schema,\n true\n );\n\n capability.output_schema = normalizeObjectSchema(\n capability.output_schema,\n true\n );\n\n return capability;\n}\n\nfunction normalizeTool(tool) {\n if (tool === null || tool === undefined) {\n return null;\n }\n\n if (!isPlainObject(tool)) {\n throw new Error(\n 'tool must be an object or null when provided'\n );\n }\n\n const server = assertObject(\n tool.server,\n 'tool.server'\n );\n\n const registration = assertObject(\n tool.registration,\n 'tool.registration'\n );\n\n const capability = assertObject(\n tool.capability,\n 'tool.capability'\n );\n\n server.name = toKebab(\n server.name,\n 'generated-mcp-server'\n );\n\n if (\n typeof server.base_url !== 'string' ||\n !server.base_url.trim()\n ) {\n throw new Error(\n 'tool.server.base_url must be a non-empty string'\n );\n }\n\n server.base_url = server.base_url.trim();\n\n server.timeout_seconds = toPositiveInteger(\n server.timeout_seconds,\n 300,\n 1\n );\n\n server.maximum_result_bytes = toPositiveInteger(\n server.maximum_result_bytes,\n 5 * 1024 * 1024,\n 1\n );\n\n registration.name = toKebab(\n registration.name,\n 'generated-mcp-tool'\n );\n\n registration.remote_tool_name =\n typeof registration.remote_tool_name === 'string' &&\n registration.remote_tool_name.trim()\n ? registration.remote_tool_name.trim()\n : registration.name;\n\n registration.input_schema = normalizeObjectSchema(\n registration.input_schema,\n true\n );\n\n registration.output_schema = normalizeObjectSchema(\n registration.output_schema,\n false\n );\n\n registration.timeout_seconds = toPositiveInteger(\n registration.timeout_seconds,\n server.timeout_seconds,\n 1\n );\n\n registration.maximum_result_bytes = toPositiveInteger(\n registration.maximum_result_bytes,\n server.maximum_result_bytes,\n 1\n );\n\n registration.approval_required =\n registration.approval_required === true;\n\n registration.side_effect =\n typeof registration.side_effect === 'string' &&\n registration.side_effect.trim()\n ? registration.side_effect.trim()\n : registration.approval_required\n ? 'approval-required'\n : 'external';\n\n capability.name = toKebab(\n capability.name,\n `${registration.name}-capability`\n );\n\n capability.agent = 'tool-agent';\n capability.agent_version = '1.0.0';\n\n capability.input_schema = normalizeObjectSchema(\n capability.input_schema,\n true\n );\n\n capability.output_schema = normalizeObjectSchema(\n capability.output_schema,\n false\n );\n\n capability.timeout_seconds = toPositiveInteger(\n capability.timeout_seconds,\n registration.timeout_seconds,\n 1\n );\n\n capability.maximum_concurrency = toPositiveInteger(\n capability.maximum_concurrency,\n 1,\n 1\n );\n\n /*\n * Approval cannot be weakened between the MCP registration and its\n * capability.\n */\n capability.approval_required =\n capability.approval_required === true ||\n registration.approval_required === true;\n\n registration.approval_required =\n capability.approval_required;\n\n if (capability.approval_required) {\n capability.side_effect =\n typeof capability.side_effect === 'string' &&\n capability.side_effect.trim()\n ? capability.side_effect.trim()\n : 'approval-required';\n } else {\n capability.side_effect =\n typeof capability.side_effect === 'string' &&\n capability.side_effect.trim()\n ? capability.side_effect.trim()\n : 'external';\n }\n\n return {\n server,\n registration,\n capability,\n };\n}\n\nfunction normalizeExecution(execution, tool) {\n const normalized = assertObject(\n execution,\n 'execution'\n );\n\n normalized.mode = [\n 'advisory',\n 'supervised',\n 'autonomous',\n ].includes(normalized.mode)\n ? normalized.mode\n : 'supervised';\n\n normalized.task =\n typeof normalized.task === 'string' &&\n normalized.task.trim()\n ? normalized.task.trim()\n : 'execute-generated-capability';\n\n normalized.context = isPlainObject(normalized.context)\n ? normalized.context\n : {};\n\n normalized.input_schema = normalizeObjectSchema(\n normalized.input_schema,\n true\n );\n\n normalized.output_schema = normalizeObjectSchema(\n normalized.output_schema,\n true\n );\n\n normalized.maximum_agent_calls = toPositiveInteger(\n normalized.maximum_agent_calls,\n 1,\n 1\n );\n\n normalized.maximum_tool_calls = toPositiveInteger(\n normalized.maximum_tool_calls,\n tool ? 1 : 0,\n 0\n );\n\n const requiredApprovals = uniqueStrings(\n normalized.require_approval_for\n );\n\n if (\n tool?.registration?.approval_required &&\n !requiredApprovals.includes(tool.registration.name)\n ) {\n requiredApprovals.push(tool.registration.name);\n }\n\n normalized.require_approval_for = requiredApprovals;\n\n return normalized;\n}\n\n\nconst source = $json;\n\nconst blueprint = findBlueprint(source);\n\nif (!blueprint) {\n throw new Error(\n [\n 'Planner completed without a recognizable configuration blueprint.',\n 'Expected model_policy, model_capability, and execution either directly,',\n 'under output.answer, under a known transport envelope, or in task_results.',\n ].join(' ')\n );\n}\n\nconst normalizedBlueprint = {\n ...blueprint,\n};\n\nnormalizedBlueprint.model_capability =\n normalizeModelCapability(\n normalizedBlueprint.model_capability\n );\n\nnormalizedBlueprint.model_policy =\n normalizeModelPolicy(\n normalizedBlueprint.model_policy,\n normalizedBlueprint.model_capability\n );\n\nnormalizedBlueprint.tool =\n normalizeTool(normalizedBlueprint.tool);\n\nnormalizedBlueprint.execution =\n normalizeExecution(\n normalizedBlueprint.execution,\n normalizedBlueprint.tool\n );\n\n/*\n * These fields are deployment metadata derived from the normalized resource\n * names. Keep them at the blueprint root so later n8n nodes can construct the\n * final execution request without reparsing nested resources.\n */\nnormalizedBlueprint.allowed_capabilities = [\n normalizedBlueprint.model_capability.name,\n ...(\n normalizedBlueprint.tool\n ? [normalizedBlueprint.tool.capability.name]\n : []\n ),\n];\n\nnormalizedBlueprint.allowed_tools =\n normalizedBlueprint.tool\n ? [normalizedBlueprint.tool.registration.name]\n : [];\n\n/*\n * Omit tool rather than forwarding undefined. Preserve explicit null only\n * when downstream nodes expect the schema's nullable tool property.\n */\nif (!normalizedBlueprint.tool) {\n normalizedBlueprint.tool = null;\n}\n\nconst plannerExecutionId =\n source.execution_id ??\n source.id ??\n source.execution?.id ??\n source.output?.execution_id ??\n null;\n\nreturn [\n {\n json: {\n blueprint: normalizedBlueprint,\n plannerExecutionId,\n },\n },\n];\n"
},
"id": "012162be-5d96-4e35-9552-62442ba2d496",
"name": "Normalize and Validate Blueprint",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
704,
0
]
},
{
"parameters": {
"jsCode": "const normalized = $json;\nconst parent = $('Sub-workflow Input').item.json;\nconst now = new Date().toISOString();\nconst obs = parent.observability ?? {};\nconst trace = Array.isArray(obs.trace) ? [...obs.trace] : [];\nconst startedAt = obs.stage_started_at ?? obs.started_at ?? now;\nconst event = {timestamp:now,correlation_id:obs.correlation_id,workflow:$workflow.name,execution_id:$execution.id,stage:'configuration-planning',status:'completed',duration_ms:Math.max(0,Date.parse(now)-Date.parse(startedAt)),model:normalized.blueprint?.model_policy?.model ?? null,capability:normalized.blueprint?.model_capability?.name ?? null,custom_tool_required:Boolean(normalized.blueprint?.tool)};\ntrace.push(event); console.log(JSON.stringify({event:'autonomous_agent_workflow_stage',...event}));\nreturn [{json:{...parent,...normalized,observability:{...obs,stage_started_at:now,trace},last_event:event}}];"
},
"id": "6cdedd58-1043-4479-aa26-6dd2bc1d2fef",
"name": "Complete Planning Trace",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
944,
0
]
}
],
"connections": {
"Sub-workflow Input": {
"main": [
[
{
"node": "Start Planning Trace",
"type": "main",
"index": 0
}
]
]
},
"Start Planning Trace": {
"main": [
[
{
"node": "Architect Configuration Blueprint",
"type": "main",
"index": 0
}
]
]
},
"Architect Configuration Blueprint": {
"main": [
[
{
"node": "Normalize and Validate Blueprint",
"type": "main",
"index": 0
}
]
]
},
"Normalize and Validate Blueprint": {
"main": [
[
{
"node": "Complete Planning Trace",
"type": "main",
"index": 0
}
]
]
}
},
"active": true,
"settings": {
"executionOrder": "v1",
"binaryMode": "separate",
"availableInMCP": false
},
"versionId": "78100362-96fe-4851-b9c5-4ed1ba35ae6a",
"nodeGroups": [],
"id": "OADovygyoqfcjlpd",
"tags": [
{
"name": "factory",
"id": "RafL6i7R2YphAkeq",
"updatedAt": "2026-07-26T11:35:57.670Z",
"createdAt": "2026-07-26T11:35:57.670Z"
}
]
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
autonomousAgentApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
AA Factory 01 - Plan Blueprint. Uses executeWorkflowTrigger, n8n-nodes-autonomous-agent. Event-driven trigger; 5 nodes.
Source: https://github.com/MustiSquare/n8n-with-autonomous-agent-platform-demo/blob/main/workflows/00-agent-execution-factory/01-plan-blueprint.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
AA Factory 02 - Ensure Model Ready. Uses executeWorkflowTrigger, n8n-nodes-autonomous-agent. Event-driven trigger; 15 nodes.
AA Factory 03 - Provision Resources. Uses executeWorkflowTrigger, n8n-nodes-autonomous-agent. Event-driven trigger; 9 nodes.
AA Factory 04 - Create Target Execution. Uses executeWorkflowTrigger, n8n-nodes-autonomous-agent. Event-driven trigger; 4 nodes.
Autonomous Agent - Incident Response - Create Capability - incident-root-cause-analysis. Uses executeWorkflowTrigger, n8n-nodes-autonomous-agent. Event-driven trigger; 2 nodes.
Autonomous Agent - Incident Response - Create Capability - production-remediation-plan. Uses executeWorkflowTrigger, n8n-nodes-autonomous-agent. Event-driven trigger; 2 nodes.