Use this skill for workflow engineering. Use the n8n-manager skill for instance, auth, runtime, tunnel, project-default, credential infrastructure, or workflow presentation work.
n8nac-config.json, AGENTS.md, .agents/skills, and the workflow sync folder.{{N8NAC_CMD}} update-ai from the context root, then read AGENTS.md. update-ai is designed to create or refresh the n8n-as-code block without destroying existing user or agent instructions.n8nac command and n8n-manager command listed in AGENTS.md. Those context-root commands override the portable examples in this skill.{{N8NAC_CMD}} workspace ..., {{N8NAC_CMD}} list, pull, push, validate, test, and update-ai command from the context root unless the user explicitly gives another context root.AGENTS.md is bootstrap context only, not a source of configuration truth.AGENTS.md.{{N8NAC_CMD}} workspace status --json
workflowDir for workflow files. Do not reconstruct it from syncFolder, instanceIdentifier, or projectName.n8nac-config.json by hand. Use {{N8NAC_CMD}} workspace ... commands.cd to the context root.{{N8NAC_CMD}} update-ai, then read AGENTS.md.{{N8NAC_CMD}} workspace status --json.{{N8N_MANAGER_CMD}} instances list.{{N8NAC_CMD}} workspace pin-instance --instance-id <id>
{{N8NAC_CMD}} workspace set-sync-folder workflows
{{N8NAC_CMD}} workspace set-project --project-id <id> --project-name <name>
For self-hosted n8n instances where the projects API is unavailable or returns 401/403, do not keep retrying project discovery. Use the standard personal project override unless the user gave another project:
{{N8NAC_CMD}} workspace set-project --project-id personal --project-name Personal
{{N8NAC_CMD}} update-ai after changing context-root overrides when the facade does not do it automatically.list to inspect workflow IDs, file paths, and sync status.{{N8NAC_CMD}} list
{{N8NAC_CMD}} pull <workflowId>
{{N8NAC_CMD}} push <path-to-workflow.workflow.ts> --verify
push requires the full workflow file path, either absolute or context-root-relative. Do not pass a bare filename.workflowDir returned by workspace status --json, then confirm it with {{N8NAC_CMD}} list --local.pull and conflict resolution operate on a single workflow ID.list is the lightweight command that covers all workflows at once.If push or pull reports a conflict, stop and inspect the conflict. Use explicit resolution commands only after choosing the intended direction:
{{N8NAC_CMD}} resolve <workflowId> --mode keep-current
{{N8NAC_CMD}} resolve <workflowId> --mode keep-incoming
keep-current force-pushes the local version.keep-incoming force-pulls the remote version.Never guess n8n node parameters.
{{N8NAC_SKILLS_CMD}} examples search "<workflow pattern>"
{{N8NAC_SKILLS_CMD}} search "<node or capability>"
{{N8NAC_SKILLS_CMD}} node-info <nodeName>
{{N8NAC_SKILLS_CMD}} validate <workflow.workflow.ts>
type and valid typeVersion values from node-info.typeVersion returned by schema output.node-info output before writing values.Use these commands instead of guessing:
{{N8NAC_SKILLS_CMD}} search "<node or capability>"
{{N8NAC_SKILLS_CMD}} node-info <nodeName>
{{N8NAC_SKILLS_CMD}} node-schema <nodeName>
{{N8NAC_SKILLS_CMD}} docs "<topic>"
{{N8NAC_SKILLS_CMD}} guides "<topic>"
{{N8NAC_SKILLS_CMD}} examples search "<workflow pattern>"
{{N8NAC_SKILLS_CMD}} examples info <id>
{{N8NAC_SKILLS_CMD}} examples download <id>
examples search when the user asks for a common automation pattern.{{N8NAC_CMD}} <subcommand> --help; do not invent flags.@n8n-as-code/transformer.source.out(0).to(target.in(0))..uses(), never .out().to().ai_tool and ai_document connections are arrays: ai_tool: [this.Tool.output].ai_languageModel: this.Model.output.node-info for connection-dependent boolean flags before declaring .uses() connections.Every .workflow.ts file starts with a <workflow-map> block. Read that map first, locate the property name you need, then read only the relevant class section.
import { workflow, node, links } from '@n8n-as-code/transformer';
@workflow({
name: 'Workflow Name',
active: false
})
export class MyWorkflow {
@node({
name: 'Descriptive Name',
type: '/* exact type from node-info */',
version: 4,
position: [250, 300]
})
MyNode = {
/* parameters from node-info */
};
@node({
name: 'Next Node',
type: '/* exact type from node-info */',
version: 3,
position: [520, 300]
})
NextNode = {};
@links()
defineRouting() {
this.MyNode.out(0).to(this.NextNode.in(0));
}
}
{{ $json.fieldName }}.{{ $('Node Name').item.json.field }}.$node["Name"].json.field unless you are preserving an existing workflow and have a reason.value1 is the expression being evaluated and value2 is the literal comparison value.Get Customers, Send Slack Alert, or Normalize Payload.Node1, HTTP Request, or Code when a more specific name is available.Use the <workflow-map> block as the index before loading large workflow files.
// <workflow-map>
// Workflow : My Workflow
// Nodes : 12 | Connections: 14
//
// NODE INDEX
// Property name Node type (short) Flags
// ScheduleTrigger scheduleTrigger
// AgentGenerateApplication agent [AI] [creds]
// OpenaiChatModel lmChatOpenAi [creds] [ai_languageModel]
// Memory memoryBufferWindow [ai_memory]
// GithubCheckBranchRef httpRequest [onError->out(1)]
//
// ROUTING MAP
// ScheduleTrigger
// -> Configuration
// -> BuildProfileSources -> LoopOverProfileSources
//
// AI CONNECTIONS
// AgentGenerateApplication.uses({ ai_languageModel: OpenaiChatModel, ai_memory: Memory })
// </workflow-map>
Navigation rule:
<workflow-map> first.AI sub-nodes are not regular data-flow nodes.
@links()
defineRouting() {
this.ChatTrigger.out(0).to(this.AiAgent.in(0));
this.AiAgent.uses({
ai_languageModel: this.OpenaiModel.output,
ai_memory: this.Memory.output,
ai_outputParser: this.OutputParser.output,
ai_tool: [this.SearchTool.output],
});
}
.uses() for language models, memory, tools, parsers, embeddings, vector stores, retrievers, and other AI sub-nodes..out().to().ai_tool and ai_document must be arrays.node-info before declaring .uses()..out().to().ai_tool: this.Tool.output instead of ai_tool: [this.Tool.output].value1 and value2.formFieldsUi.fieldItems when the current schema expects formFields: { values: [...] }.push.After pushing:
{{N8NAC_CMD}} verify <workflowId>
{{N8NAC_CMD}} test-plan <workflowId> --json
For webhook, chat, or form workflows, prefer the production test sequence:
{{N8NAC_CMD}} workflow activate <workflowId>
{{N8NAC_CMD}} test <workflowId> --prod
presentWorkflowResult is the standard way to show a workflow to the user. It is part of the workflow authoring loop, even though the command lives in n8n-manager.
Run it whenever one of these is true:
{{N8N_MANAGER_CMD}} presentWorkflowResult --workflow-id <workflowId> --workspace-root <contextRoot>
Rules:
url returned by presentWorkflowResult as the user-facing URL.{{N8NAC_CMD}} list first and select the matching workflow.presentWorkflowResult fails, report the backend diagnostic and then provide the best direct n8n URL only as a fallback.For webhook, chat, or form workflows:
test-plan to inspect trigger type, endpoint, and suggested payload.--prod by default.{{N8NAC_CMD}} push <path-to-workflow.workflow.ts> --verify
{{N8NAC_CMD}} test-plan <workflowId> --json
{{N8NAC_CMD}} workflow activate <workflowId>
{{N8NAC_CMD}} test <workflowId> --prod
Use bare {{N8NAC_CMD}} test <workflowId> only when a test URL was intentionally armed in the n8n editor.
For GET/HEAD webhooks that read from $json.query, prefer:
{{N8NAC_CMD}} test <workflowId> --query '{"key":"value"}' --prod
If a webhook returns success but the workflow behavior is wrong, inspect executions instead of guessing:
{{N8NAC_CMD}} execution list --workflow-id <workflowId> --limit 5 --json
{{N8NAC_CMD}} execution get <executionId> --include-data --json
When a workflow is blocked by missing credentials, resolve the credential gap without rewriting unrelated workflow logic.
{{N8NAC_CMD}} workflow credential-required <workflowId> --json
{{N8NAC_CMD}} credential schema <type>
{{N8NAC_CMD}} credential list --json
{{N8NAC_CMD}} credential create --type <type> --name <name> --file cred.json --json
{{N8NAC_CMD}} workflow activate <workflowId>
workflow credential-required exits non-zero when at least one credential is missing. Treat that as a signal to act, not as a workflow-code failure.credential schema to discover required fields.--file for credential creation. Do not pass secrets inline in shell arguments.For most workflow tasks:
workspace status --json.workflowDir from the backend response.list..workflow.ts file.--verify.presentWorkflowResult.presentWorkflowResult instead of composing a URL manually.n8n-manager for instance/auth/runtime and n8nac workspace ... for context-root overrides.