From e521dfd5c73df8ba092f72f4276493153eae5fb2 Mon Sep 17 00:00:00 2001 From: Riqwan Thamir Date: Sat, 26 Sep 2026 01:32:07 +0200 Subject: [PATCH] toolmode part two --- ...nt-ambiguous-alert-response-clarifies.json | 4 - .../intent-role-shaped-scheduled-analyst.json | 4 - .../instance-ai/skills/agent-builder/SKILL.md | 10 +- .../skills/intent-recognition/SKILL.md | 477 ------------------ .../instance-ai/src/agent/instance-agent.ts | 3 +- .../instance-ai/src/agent/system-prompt.ts | 34 +- .../skills/__tests__/runtime-skills.test.ts | 2 +- .../instance-ai/src/skills/runtime-skills.ts | 2 +- .../src/tools/__tests__/index.test.ts | 2 +- .../@n8n/instance-ai/src/tools/tool-ids.ts | 2 +- .../@n8n/instance-ai/src/tools/tool-modes.ts | 5 +- 11 files changed, 45 insertions(+), 500 deletions(-) delete mode 100644 packages/@n8n/instance-ai/skills/intent-recognition/SKILL.md diff --git a/packages/@n8n/instance-ai/evaluations/data/discovery/intent-ambiguous-alert-response-clarifies.json b/packages/@n8n/instance-ai/evaluations/data/discovery/intent-ambiguous-alert-response-clarifies.json index ad1006618cc..5c5a4e61c5d 100644 --- a/packages/@n8n/instance-ai/evaluations/data/discovery/intent-ambiguous-alert-response-clarifies.json +++ b/packages/@n8n/instance-ai/evaluations/data/discovery/intent-ambiguous-alert-response-clarifies.json @@ -3,10 +3,6 @@ "userMessage": "I need to ingest a cybersecurity alert, analyze it, and take actions depending on the finding.", "expectedToolInvocations": { "allOfToolCalls": [ - { - "toolName": "load_skill", - "argsContainAny": ["intent-recognition"] - }, { "toolName": "ask-user", "argsContainAny": [ diff --git a/packages/@n8n/instance-ai/evaluations/data/discovery/intent-role-shaped-scheduled-analyst.json b/packages/@n8n/instance-ai/evaluations/data/discovery/intent-role-shaped-scheduled-analyst.json index 3fafc89dc53..119427c4386 100644 --- a/packages/@n8n/instance-ai/evaluations/data/discovery/intent-role-shaped-scheduled-analyst.json +++ b/packages/@n8n/instance-ai/evaluations/data/discovery/intent-role-shaped-scheduled-analyst.json @@ -3,10 +3,6 @@ "userMessage": "Set up a daily market analyst. It should research market changes, decide which developments matter, and send me a briefing each morning.", "expectedToolInvocations": { "allOfToolCalls": [ - { - "toolName": "load_skill", - "argsContainAny": ["intent-recognition"] - }, { "toolName": "load_skill", "argsContainAny": ["agent-builder"] diff --git a/packages/@n8n/instance-ai/skills/agent-builder/SKILL.md b/packages/@n8n/instance-ai/skills/agent-builder/SKILL.md index aa149a036d3..7144619c11e 100644 --- a/packages/@n8n/instance-ai/skills/agent-builder/SKILL.md +++ b/packages/@n8n/instance-ai/skills/agent-builder/SKILL.md @@ -5,8 +5,7 @@ description: >- request after any required orchestrator-owned prerequisites are ready. Agent Builder owns Agent setup and implementation questions. Governs prerequisite creation, faithful handoff, targeting, testing, and publishing. Use directly - for routine Agent follow-ups; rerun intent-recognition only when the requested - artifact is no longer clear. + for routine Agent follow-ups. shared_references: - credential-setup-with-computer-use recommended_tools: @@ -19,10 +18,9 @@ recommended_tools: ## Routing -Use this skill after `intent-recognition` chooses an agent-anchored design, or -when the conversation already targets an Agent and the user is continuing that -build. Do not rerun intent recognition for routine Agent edits or extensions. -Use `build-agent` only for Agent artifacts. +Use this skill when a request calls for an n8n Agent, or when the conversation +already targets an Agent and the user is continuing that build. Use +`build-agent` only for Agent artifacts. For a new Agent request, make the first `build-agent` call with a faithful copy of the request as soon as any required orchestrator-owned prerequisites are diff --git a/packages/@n8n/instance-ai/skills/intent-recognition/SKILL.md b/packages/@n8n/instance-ai/skills/intent-recognition/SKILL.md deleted file mode 100644 index 9f0ec7818af..00000000000 --- a/packages/@n8n/instance-ai/skills/intent-recognition/SKILL.md +++ /dev/null @@ -1,477 +0,0 @@ ---- -name: intent-recognition -description: >- - Classifies automation requests using two decisions: anchor (which primitive - owns the top-level control flow — workflow-anchored, agent-anchored, - needs-clarification, or out-of-scope) and embeds_other (whether the other - primitive appears embedded inside — an agent step inside a workflow, or a - workflow invoked as an agent tool). Must be used whenever the current turn - requires choosing or reconsidering the intent of an automation request, - including compound requests, independent automations introduced mid-build, - one-off questions or reports that need external systems you cannot query - directly, and requests that need clarification before an anchor can be - chosen. An explicit Agent request routes to agent-builder before ask-user. - Do not load for routine edits or extensions when the conversation already - targets a workflow or Agent. ---- - -# Intent recognition - -## Purpose - -Use this skill when an automation request still needs to be classified before -designing or building it, or when a new turn may require reconsidering the -current artifact. Do not load it again for a routine edit or extension when the -conversation already targets a workflow or Agent, unless the user introduces -an independent automation or the new request carries its own anchor signal. -The deciding question is not a single "workflow or agent" label — it is two -questions: who owns the top-level control flow, and does the other primitive -show up inside that flow. - -If the user asked to build, route on the result: workflow-builder for -workflow-anchored (a bounded LLM step is an AI node in the graph; an embedded -agent is an AI Agent step inside it), an agent-oriented design for -agent-anchored (a tool-use loop), `ask-user` for needs-clarification, or answer -directly for out-of-scope. - -## Inputs - -- The user's request or scenario prompt. -- Whether the user is mid-build on an existing workflow or agent in this - conversation — incremental requests default to extending that primitive. -- Whether the editor/canvas context the conversation opened from shows an - existing **agent** or an existing **workflow** (or both). An existing agent - in context that the user asks to change is an agent-anchored request — see - Context continuity and Existing-agent modification. -- Any explicit constraints about determinism, auditability, latency, cost, - compliance, reusability, or allowed tools. -- If the user did not explicitly select an Agent and the request is - underspecified on an anchor-deciding axis, ask for the missing detail instead - of guessing. An explicit Agent request already decides the anchor. Leave - missing setup and implementation details to the Agent Builder. - -## Decisions - -Two orthogonal decisions per request, or per part for compound requests: - -**1. Anchor** — which primitive owns the top-level control flow: - -- **workflow-anchored**: the outer shell is a workflow graph. May include LLM - steps as bounded transformers (classify, extract, summarize, score, a - single decision feeding fixed branches). -- **agent-anchored**: an agent owns the flow; the LLM decides the next step - at runtime or owns an ongoing role that requires judgment. n8n Agents are not - chat-only: besides chat sessions, they run recurring objectives on a cron - schedule (**tasks**) and keep memory across sessions and runs — so recurring - or scheduled duties do not disqualify this anchor. -- **needs-clarification**: the request is under-specified on an - anchor-deciding axis. -- **out-of-scope**: not a build intent at all. Covers meta or product - questions (e.g. asking what the assistant is capable of building) and - one-off content tasks with no trigger, no persistence, and no reuse intent - (summarize, translate, or draft something once) — answer or do these - directly instead of building an automation. This bucket only applies when - you can actually do the task directly: a one-off question or report that - needs external systems you have no ad-hoc access to (a private issue - tracker, wiki, or CRM) is not out-of-scope — classify it, and when - answering requires judgment-driven navigation of those systems it is - agent-anchored (see Signals). Requests to operate on existing resources - (running or triggering a workflow the user already has, debugging a failed - execution, listing or managing workflows or agents, querying data) are not - classified by this skill at all — route them through their normal paths. - Follow the system prompt's "Existing Resources" section before reading - "trigger my X" as a build. Finally, a one-off task with a concrete - external *effect* (export/copy data somewhere once, a migration, a - backfill) is **workflow-anchored**, not out-of-scope — the workflow is - just the vehicle. Classify it by shape (bounded data already in hand, - imperative ask, no trigger/schedule/reuse vocabulary) — users rarely say - "one-off" explicitly. Load the `one-off-operations` skill before building - and pass `executionIntent: "one-off"` to `build-workflow`; the completion - criterion is then a live run with read-back instead of simulated - verification. - -**2. Embeds other** — whether the other primitive appears inside the anchor: - -- workflow-anchored + `true`: an agent embedded as a workflow step (e.g. a - scheduled pipeline whose middle step is open-ended investigation). -- agent-anchored + `true`: workflows invoked as tools of the agent; see Agent - tool shape to distinguish them from direct tools. -- `n/a` for needs-clarification and out-of-scope. - -**Migration from the old taxonomy**: old **hybrid** → workflow-anchored, -`embeds_other: false`. Old **single AI task** → out-of-scope when it is a -one-off request (do the task directly); workflow-anchored with one LLM step -only when the user wants a persistent, triggerable automation. Old -**ambiguous** → needs-clarification. Old **workflow** and **agent** map -directly onto the matching anchor value. - -## Agent tool shape - -After choosing an agent-anchored design, decide whether each capability should -be a direct agent tool or a workflow tool: - -- **Direct agent tools are the default.** One node-backed capability or multiple - independent node tools stay on the Agent build path with - `embeds_other: false`. -- Use a **workflow tool** only when one agent tool call must run an ordered - multi-node procedure, or when the user explicitly needs that workflow - reusable, manually callable, or usable outside the agent. Build the workflow - first, pass it to `build-agent` via `workflowContext`, and set - `embeds_other: true`. - -Count the nodes required inside one tool invocation, not the total number of -tools on the agent. For example, looking up and inserting Data Table rows are -two direct node tools; an atomic lookup-transform-write procedure is one -workflow tool. - -After choosing an agent-anchored design, load `agent-builder` before calling -`build-agent`. It owns prerequisite creation and the handoff to the delegated -builder. - -## Decision Steps - -0. If the user is mid-build on an existing workflow or agent, apply context - continuity (see Signals) before anything else — an incremental request - normally extends the current primitive. -1. **Explicit artifact requests.** "Build me an Agent/assistant that…" selects - an Agent artifact and decides the anchor. Do not ask the user to reconsider - that choice during intent recognition. Do not silently substitute a workflow, - even when it could implement the same behavior. You may explain a simpler - workflow alternative, but switch only after the user chooses it. Route - missing setup and implementation choices to Agent Builder. The immediate - next routing action is to load `agent-builder`. Do not call `ask-user` - between classification and that handoff. Forward the request without - selecting services, tools, topics, schedules, or other implementation - details. Agent Builder owns those questions. An explicit - workflow request normally selects a workflow. If its required interaction is - unambiguously Agent-shaped, such as ongoing open-ended chat, explain why an - Agent fits and say that you are deviating from the named workflow. The - false-friends rule applies to task descriptions, not to an explicit Agent - request. -2. If the request is not a build intent — a meta or product question, or a - one-off content task with no trigger or reuse — classify **out-of-scope** - and answer or do it directly. -3. Split the request into parts only if it contains multiple independent - automations with separate lifecycles (unrelated triggers, audiences, or - cadences). Markers like numbering or "and separately" are a giveaway but - are not required — a single plain sentence can contain two automations. - Do not split a single automation that merely enumerates many tools or - steps. Run steps 4-9 on each part. -4. Test the agent signals. If any one holds, classify **agent-anchored**. -5. Before selecting a workflow, verify that the request supplies or clearly - entails every workflow condition. Do not invent a fixed sequence, decision - policy, or bounded LLM task from a generic outcome. If a missing - anchor-defining detail could make the work judgment-driven, classify - **needs-clarification** and ask only for that detail. -6. Otherwise, test the workflow conditions. If all of them hold, classify - **workflow-anchored**. -7. Decide `embeds_other` in both directions: does an agent step appear inside - this workflow, or does this agent invoke workflows as tools? -8. **Degenerate-shell check.** If a workflow-anchored design reduces to a - trigger plus a single open-ended agent step that does all the work — no - deterministic steps earning the shell — the anchor is wrong: reclassify - **agent-anchored** and build an n8n Agent (an on-demand duty becomes the - agent's chat use; a scheduled duty becomes a task on the agent). Re-run - this check while building: when fixed nodes prove unusable and the work - migrates into one embedded agent step, stop and re-anchor instead of - finishing the degenerate workflow. -9. If both anchors are genuinely defensible, apply the growth tiebreaker: - prefer whichever primitive scales with likely complexity growth — usually - agent-anchored when novel situations, longer horizons, or learning are - implied. The tiebreaker applies only to genuine ties: when a bounded - workflow reading fully satisfies the request, prefer it. If it is a real - toss-up, say so and name both readings instead of feigning certainty. - The workflow preference applies to task-shaped requests; it never - overrides an explicitly requested agent artifact (step 1). - -## Signals - -**Agent-anchored** (any one is enough): - -- Reasoning dominates the flow: investigate, decide, act, iterate. -- Persistent delegated role: the user gives an analyst, coordinator, - receptionist, researcher, or similar role continuing responsibility for a - changing domain. The role must require judgment such as choosing what - matters, selecting tools, following up, or adapting actions. A role noun by - itself is not enough. -- On-demand question or report that requires judgment-driven navigation of - external systems (which items matter, how they map to goals) and cannot be - answered directly with your own tools — the user is in effect already - chatting with the automation they need. The artifact is an agent with those - tools that can be asked again anytime, not a manually triggered workflow. -- Multi-session or long-running: coordination across days, tracked open - threads, daily check-ins. -- Proactive or recurring on its own: wakes on a heartbeat or a scheduled - task, checks state, and decides what to do about it each run. The judgment - per run is the signal, not the cadence — a schedule alone is anchor-neutral - (see Scheduled judgment work). -- Self-improving or skill accretion is first-class: learns from feedback - over time, gets better at the task. -- Chat or session-based interaction. A workflow with a Chat Trigger is not - a substitute — this signal holds unless the chat merely triggers a fixed - pipeline (see Gotchas). -- Cross-session memory. - -**Workflow-anchored** (all must hold): - -- Structure is a graph of enumerable steps. -- Any LLM use is a bounded transformer: fixed-label classify, extract, - summarize, or a single decision. -- Trigger and actions are deterministic. A cron schedule satisfies this but - never decides the anchor by itself — agents run scheduled tasks too; what - must be deterministic is the body of each run. -- Reproducibility or auditability is served by the same graph running every - time. - -**Scheduled judgment work** (recurring cadence + open-ended body): both -primitives can own it — a workflow shell with an embedded agent step, or an -agent with a scheduled task. Default to an Agent task when the open-ended duty -is the whole outcome and the workflow shell would only trigger the duty and -deliver its result. Use a workflow shell when its deterministic collection, -gating, transformation, branching, or delivery steps are independently -meaningful and the agent owns only one bounded stage. Choose an Agent when the -duty belongs to a persistent role, needs memory across runs, supports user -interaction, or has other duties. An explicit Agent request remains binding. -A recurring duty added to an agent mid-build is always a task on that agent, -never a spawned workflow. - -**Embeds-other signals**: - -- Workflow with an embedded agent: a step in an otherwise fixed pipeline is - open-ended ("figure out why", "investigate", "decide what to do about it") - while the trigger and surrounding steps stay deterministic. -- The embedding is often implicit — the request never says "agent". Ask of - each step: could a fixed-instruction transform do it (enumerable labels, - one bounded rewrite), or does doing it well require gathering and weighing - context that differs per item, then producing a judgment? A nightly job - that drafts a tailored renewal pitch for each account from its usage - history embeds an agent; a nightly job that condenses each ticket into a - two-sentence summary does not. -- For an agent with workflow tools, apply Agent tool shape. - -**Context continuity** (step 0): inside a workflow build, a request to insert -a scoring step stays a bounded LLM step, not a new agent. Inside an agent -build, a request to post an update on completion is a new tool on that -agent, not a spawned workflow — and a recurring duty ("also send me a Monday -summary") is a scheduled task on that agent, not a new scheduled workflow. -Only cross into the other primitive when the -incremental request itself carries its own anchor signal — and even then, -prefer asking before switching paradigm if it isn't clearly load-bearing. - -**Existing-agent modification**: context continuity extends to an agent the -user did not build in this conversation but opened in the editor. When the -editor/canvas context shows an existing agent and the user asks to change, -add, or remove its configuration or capabilities (instructions, model, -tools, skills, tasks, channels, memory, sub-agents), classify -**agent-anchored** and route to `build-agent` targeting that agent. Do not -route to `workflow-builder`, and do not treat the request as a workflow -change even when a workflow is also in context, unless the user explicitly -names the workflow as the target. A capability the agent cannot have is -still an agent-anchored request — handle it per Unsupported capabilities -below, do not reclassify it as a workflow. - -**Mixed agent + workflow context**: when both an agent and a workflow are in -context and the request is ambiguous about which one the user wants to -change, classify **needs-clarification** and ask which target — do not -assume the workflow. Once the user names the target, follow context -continuity for that primitive. - -**Unsupported capabilities**: when the user names a specific channel or -capability for an agent (e.g. "WhatsApp", "Teams"), call -`list-agent-capabilities` before classifying. If the named channel is -absent, it is unsupported for agents — do not classify the request as a -workflow substitute, do not improvise workflow nodes to fake the channel, -and do not claim it can be configured. Explain that it is unavailable for -agents, offer the supported alternatives the tool returned (with their -`capabilities`), and only build a workflow if the user explicitly chooses -that path after the limitation is stated. This is an agent-anchored request -that the agent cannot fully satisfy, not a workflow-anchored one. - -**Clarify triggers**: rule-based vs judgment-based (what defines "important" -or "urgent"?), scope/autonomy (act on its own vs draft for review), -interaction mode (one-shot vs chat). Clarify when the missing answer changes -the anchor. When the request supplies enough evidence and both designs remain -valid, apply the growth tiebreaker instead of asking a theoretical preference. - -**False friends — not signals by themselves**: - -- Surface vocabulary: "agent", "assistant", "bot", "workflow", "automate" - in a *task description* carries no weight — classify the shape, not the - words. A persistent delegated role combines the role with ongoing judgment, - so it is a real Agent signal. An explicit artifact request ("build me an - agent that…") is binding; see Decision Step 1. -- Step count and tool count: long linear pipelines and high tool counts are - not agentic. Seven deterministic steps with zero branches is still a - workflow. - -## Examples - -- "Every day at 6pm, pull today's Shopify order count and post it to a - Discord channel." -> **workflow-anchored**, `embeds_other: false`: fixed - schedule, source, and destination. -- "When a new Jira issue is created, classify it as bug/feature/question and - route it to the matching Discord channel." -> **workflow-anchored**, - `embeds_other: false`: bounded classification feeding fixed routing (would - have been **hybrid** under the old taxonomy). -- "Every night, gather the day's failed background jobs, dig into the logs - and recent deploys to work out why each one failed, and post a write-up to - a Notion page." -> **workflow-anchored**, `embeds_other: true`: schedule - and destination are fixed; "work out why" is open-ended investigation, best - run as an embedded agent step. -- "Give me a chat window where I can ask about our expense-reporting rules - and get answers pulled from the finance handbook." -> **agent-anchored**, - `embeds_other: false`: chat interaction, the LLM decides what to look up - each turn. -- "Build an ops agent that can check server health, restart services via our - runbook, and file a Jira ticket if it can't resolve things — the restart - and ticket-filing should also be triggerable manually elsewhere." -> - **agent-anchored**, `embeds_other: true`: explicitly reusable actions are - workflows the agent calls as tools. -- "Have an agent keep an eye on our AWS spend throughout the day and flag me - before we blow through budget, without me asking it to check." -> - **agent-anchored**, `embeds_other: false`: proactive, heartbeat-driven, - no fixed check schedule. -- "Build an agent that drafts replies to Notion comment threads and sharpens - its sense of our tone the more we correct it." -> **agent-anchored**, - `embeds_other: false`: skill accretion from feedback is first-class. -- "Put an agent in charge of coordinating our office relocation — track - vendors, follow up with each team lead, and send reminders through our - existing reminder workflow when a task stalls." -> **agent-anchored**, - `embeds_other: true`: long-running coordination invoking a workflow tool. -- "Every night, fetch the day's new GitHub stars and send me a digest." -> - **workflow-anchored**, `embeds_other: false`: fixed schedule, source, - transform, and delivery, with no Agent artifact or judgment requirement. -- "Build me an agent that fetches new GitHub stars each night and sends me a - digest." -> **agent-anchored**, `embeds_other: false`: the user selected an - Agent, and the recurring duty is a scheduled task on it. A workflow can be - offered as an alternative, but it cannot silently replace the requested - artifact. -- "Set up a daily market analyst. It should research market changes, decide - which developments matter, and send me a briefing each morning." -> - **agent-anchored**, `embeds_other: false`: the analyst owns a persistent, - judgment-driven role; the morning cadence is a task on that Agent. -- "Spin up a lightweight workflow that talks to shoppers on our storefront - and handles their product questions." -> **agent-anchored**: chat-based - Q&A means the LLM owns turn-by-turn control despite the word "workflow" — - a false friend in the other direction. -- "Build me an agent that answers customer questions from our docs." -> - **agent-anchored**, `embeds_other: false`: explicit agent artifact - request plus chat-shaped open-ended Q&A. The deliverable is an n8n Agent - — not a workflow with a Chat Trigger and an AI Agent node. -- "Give me a chat box where I paste a company name and it runs our - enrichment steps and replies with the result." -> **workflow-anchored**, - `embeds_other: false`: chat is merely the manual trigger for a fixed - graph — the one case where a Chat Trigger workflow is the right build. -- "Post every new Airtable record to a Discord channel, and separately set up - an agent that handles customer refund requests end-to-end." -> two parts, - joined only by topic, not data or trigger: "Airtable-to-Discord posting" - (**workflow-anchored**, `embeds_other: false`) and "refund-handling agent" - (**agent-anchored**, `embeds_other: true`). -- "Transcribe my sales calls and chase the deals that go quiet." -> two - parts despite the plain single sentence: transcription is a bounded - per-call pipeline (**workflow-anchored**, `embeds_other: false`), while - chasing stalled deals is an ongoing judgment-driven automation with its - own lifecycle (**agent-anchored**). -- "Set up a research helper capable of searching the web, querying our - internal wiki, pulling numbers from Google Analytics, and drafting a slide - deck that summarizes the findings." -> one part, **agent-anchored**, - `embeds_other: true`: many tools but one lifecycle — do not split on tool - count. -- "Tell me how the platform team is progressing against their cycle goals — - current status is in our issue tracker, the goals are on our internal - wiki." -> **agent-anchored**, `embeds_other: false`: an on-demand judgment - report over external systems you cannot query directly. The artifact is an - agent with tracker and wiki tools the user can ask again anytime — not a - manual-trigger workflow whose only real step is an embedded agent with - those same tools. If the user later wants it every Friday, that becomes a - scheduled task on the same agent, not a conversion to a workflow. -- "Tell me when something important happens with our shipments." -> - **needs-clarification**: "important" is undefined; ask whether concrete - rules exist or this needs judgment-based triage. -- "Ingest each cybersecurity alert, analyze it, and take actions depending on - the finding." -> **needs-clarification**: ask whether fixed rules select the - actions or whether an investigator must choose and adapt them. -- "Build me an agent my team can @mention on WhatsApp to triage customer - messages." -> **agent-anchored** (explicit agent artifact + chat - interaction), but call `list-agent-capabilities` first: WhatsApp is absent, - so do not build. Explain WhatsApp is unsupported for agents, offer the - supported chat channels the tool returned, with their - `capabilities`, and ask which to use — or whether the user wants a - workflow path instead. Do not improvise a workflow with a WhatsApp node - and do not claim the channel is configured. -- (An existing agent is open in the editor.) "Make it also file a Linear - ticket when it can't resolve an issue." -> **agent-anchored**: the open - agent is the target; route to `build-agent` targeting that agent to add the - capability. Do not start a workflow build, even though a workflow could - also file a ticket — the user asked to change the agent. -- (Both an agent and a workflow are open.) "Add a daily summary of new - signups to the data warehouse." -> **needs-clarification**: ask whether - the summary belongs to the agent (a scheduled task on it) or the workflow - (a new branch in the graph); do not assume the workflow. - -## Gotchas - -- Do not label a request agent-anchored just because it is long, multi-step, - or mentions AI. -- Do not label classify-then-route as agent-anchored unless the model - repeatedly decides the next action after observing prior results. -- Do not force vague prompts into an anchor; ask when an anchor-deciding - axis is missing. -- Never default `embeds_other` to `false` without checking both directions: - an agent step hiding inside a workflow, and a workflow acting as an - agent's tool. -- Never split a compound request on tool or step enumeration alone — split - only on separate lifecycles. -- Unnecessary agency adds latency, cost, and compounding error risk — do not - reach for an agent when a bounded workflow fully satisfies a task-shaped - request. This is not a license to override an explicit agent request. -- Unnecessary workflow shells hide Agent intent. Do not wrap an open-ended - delegated duty in a workflow when the shell only supplies a schedule and a - destination. -- Never satisfy an **agent-anchored** classification with a workflow - containing a Chat Trigger + AI Agent node. Agent-anchored requests - produce an n8n Agent artifact via the agent build path; the AI Agent - *node* exists only for `embeds_other: true` steps inside a genuinely - workflow-anchored pipeline. A Chat Trigger workflow is correct only when - chat is merely the manual trigger for a fixed graph. -- Never improvise a workflow substitute for an unsupported agent channel or - capability. When the user names a channel not in `list-agent-capabilities`, - explain the limitation and offer supported alternatives — do not add - workflow nodes that fake the channel or silently translate the request - into a workflow change. -- Do not demote an explicitly requested agent to an embedded AI Agent step - inside a workflow — workflow-anchored with `embeds_other: true` is for - agent steps inside a pipeline the user described as a pipeline. -- A workflow whose only real step is one embedded agent doing all the work - is an agent wearing a workflow costume — the mirror image of the Chat - Trigger gotcha above. Apply the degenerate-shell check (step 8) and - re-anchor instead of shipping trigger + AI Agent node. -- Do not treat a cron schedule as a workflow signal by itself — agents run - scheduled tasks. Classify by the body of each run, and when a one-off - question can't be answered directly, do not fall back to "build a workflow - or do it yourself": an agent with the right tools is usually the missing - option. -- Do not use an agent when progress cannot be verified: if the path cannot - be scripted and the result cannot be checked, the design is not ready. -- Respect the current build context: an incremental request stays on the - active primitive unless it carries its own anchor signal. -- Keep n8n framing clear: agents operate inside workflow guardrails; they do - not replace the workflow engine. - -## Output Format - -Return a concise classification and reason: - -```text -Anchor: workflow-anchored | agent-anchored | needs-clarification | out-of-scope -Embeds other: true | false | n/a -Reason: -Next step: -``` - -For build requests, do not expose this format unless the user asks for -classification. Instead, proceed according to the selected next step. When -the user asks for classification in a specific format, such as a JSON block, -follow that format and map the vocabulary accordingly (workflow-anchored, -agent-anchored, needs-clarification, out-of-scope, and their equivalents). -For compound requests, output one classification block per part. diff --git a/packages/@n8n/instance-ai/src/agent/instance-agent.ts b/packages/@n8n/instance-ai/src/agent/instance-agent.ts index 17e6211c920..456468acedb 100644 --- a/packages/@n8n/instance-ai/src/agent/instance-agent.ts +++ b/packages/@n8n/instance-ai/src/agent/instance-agent.ts @@ -22,7 +22,7 @@ import { getActiveOrchestratorDomainToolNames, } from '../tools'; import { createToolsFromLocalMcpServer } from '../tools/filesystem/create-tools-from-mcp-server'; -import { ALWAYS_LOADED_TOOL_NAMES } from '../tools/tool-ids'; +import { ALWAYS_LOADED_TOOL_NAMES, ORCHESTRATION_TOOL_IDS } from '../tools/tool-ids'; import { createToolModesConfig } from '../tools/tool-modes'; import { isSetupPanelEnabled } from '../tools/workflows/setup-items'; import { @@ -208,6 +208,7 @@ export async function createInstanceAgent( conversationHistoryEnabled: Boolean(context.conversationHistoryService), preferenceSavingEnabled: Boolean(context.aiPreferenceService), setupPanelEnabled: isSetupPanelEnabled(context), + agentBuildingEnabled: allOrchestratorTools.has(ORCHESTRATION_TOOL_IDS.BUILD_AGENT), workspaceRoot: orchestrationContext?.workspace && orchestrationContext.workspaceRoot ? orchestrationContext.workspaceRoot diff --git a/packages/@n8n/instance-ai/src/agent/system-prompt.ts b/packages/@n8n/instance-ai/src/agent/system-prompt.ts index 9a579ab1ffb..4e1adec2181 100644 --- a/packages/@n8n/instance-ai/src/agent/system-prompt.ts +++ b/packages/@n8n/instance-ai/src/agent/system-prompt.ts @@ -21,6 +21,8 @@ interface SystemPromptOptions { preferenceSavingEnabled?: boolean; /** Setup panel v2 flag: `workflows(action="setup")` announces instead of opening a card. */ setupPanelEnabled?: boolean; + /** `build-agent` is registered, so a new automation can be a workflow or an n8n Agent. */ + agentBuildingEnabled?: boolean; } export function getDateTimeSection(timeZone?: string): string { @@ -102,7 +104,7 @@ If the user asks to create in, move to, or use a credential from another project * delegate is present, so naming it here would point at a tool the model cannot call * on instances without the agents module — and it is list-only regardless * (`build-agent` owns create and edit). The existing-agent path is already claimed - * by the intent-recognition and agent-builder skills. Data tables are absent for the + * by the Workflow or Agent section and the agent-builder skill. Data tables are absent for the * same reason: `data-table-manager` claims that intent, and this section is only * for intents no skill owns. * @@ -121,6 +123,35 @@ Before treating a request as a build, check whether it refers to a workflow the Changing a workflow's nodes, parameters, or name is a build, but match the existing workflow first. A request for something genuinely new goes straight to the build path.`; } +/** + * Always-on rather than a skill: the model must choose the artifact before it + * knows which builder skill to load, so a catalog entry is read too late or not + * at all. Rendered only when `build-agent` is registered; without it every build + * is a workflow and there is nothing to choose. Instance-wide, so the two + * variants never fragment the prompt cache within one instance. + * + * Channel support, direct vs workflow tools, and one-off execution details are + * deliberately absent: `agent-builder` and `workflow-builder` own them. + */ +function getWorkflowOrAgentSection(agentBuildingEnabled?: boolean): string { + if (!agentBuildingEnabled) return ''; + return `## Workflow or Agent + +Before you build something new, decide whether it is a workflow or an n8n Agent. Skip this for routine edits to the workflow or Agent that the conversation already targets. + +- **An explicit request wins.** "Build me an Agent" means an Agent: load \`agent-builder\` immediately. Do not ask setup questions first, and do not substitute a workflow. You may mention a simpler workflow, but switch only if the user chooses it. "Build me a workflow" means a workflow, unless the interaction is ongoing open-ended chat; then explain why an Agent fits. +- **Otherwise, classify by shape, not by words.** "Agent", "bot", "workflow", or "automate" in a task description decides nothing. +- **Build an Agent if any one of these holds:** the model must investigate, decide, and iterate; a persistent role needs judgment (an analyst who decides what matters); the interaction is chat or session-based; the work needs memory or coordination across sessions; a recurring job decides what to do on each run; the work improves from feedback; or an on-demand question or report needs judgment over systems you cannot query yourself. +- **Build a workflow only if all of these hold:** the steps can be listed, every LLM step is bounded (classify, extract, summarize, one decision), and each run follows the same path. Long pipelines and many tools are still workflows. +- **A schedule decides nothing.** Agents run scheduled tasks. Judge what each run does. +- **An open-ended step inside a fixed pipeline** ("work out why each job failed") is an AI Agent node inside a workflow. +- **Do not disguise an Agent as a workflow.** If a workflow is only a trigger plus one AI Agent node that does all the work, build an Agent. Never answer an Agent request with a Chat Trigger and AI Agent node workflow. A Chat Trigger workflow is correct only when chat just starts a fixed pipeline. +- **Stay on the current build.** A new step, tool, or recurring duty ("also send me a Monday summary") extends what you are building. On an Agent, a recurring duty is a scheduled task. An Agent open in the editor is the target for changes to it. If an Agent and a workflow are both in context and the target is unclear, ask. +- **Split a request only when its parts have separate lifecycles** (unrelated triggers, audiences, or cadences). Never split on tool or step count. +- **Ask only when the answer changes the choice:** fixed rules or judgment ("what counts as important?"), act alone or draft for review, one-shot or chat. When both remain valid, prefer the workflow if it fully does the job. Otherwise, build the Agent. +- **Some requests are not builds.** Answer product questions and one-off writing tasks (summarize, translate, draft) directly. A one-off job with an external effect (export, migration, backfill) is a one-off workflow.`; +} + function getConversationRecallSection(): string { return `## Past Conversations @@ -187,6 +218,7 @@ export function getSystemPrompt(options: SystemPromptOptions = {}): string { conversationHistoryEnabled, preferenceSavingEnabled, setupPanelEnabled, + agentBuildingEnabled, } = options; return `You are the n8n Instance Agent, an AI assistant embedded in an n8n instance. Understand the user's request and use the skills in the catalog to achieve it. Learn a loaded skill in depth before you continue, and load more skills whenever the conversation needs them. Tool descriptions state any load-before-call gates (\`load_skill\` / \`load_tool\`). diff --git a/packages/@n8n/instance-ai/src/skills/__tests__/runtime-skills.test.ts b/packages/@n8n/instance-ai/src/skills/__tests__/runtime-skills.test.ts index d4d7408179f..3000207453f 100644 --- a/packages/@n8n/instance-ai/src/skills/__tests__/runtime-skills.test.ts +++ b/packages/@n8n/instance-ai/src/skills/__tests__/runtime-skills.test.ts @@ -11,7 +11,7 @@ import { import { CONFIG_EVALS_SKILL_ID, disabledInstanceAiSkillIds } from '../skill-gates'; const ORIGINAL_ENABLED_MODULES = process.env.N8N_ENABLED_MODULES; -const AGENTS_MODULE_SKILL_IDS = ['agent-builder', 'intent-recognition'] as const; +const AGENTS_MODULE_SKILL_IDS = ['agent-builder'] as const; describe('Instance AI runtime skills', () => { afterEach(() => { diff --git a/packages/@n8n/instance-ai/src/skills/runtime-skills.ts b/packages/@n8n/instance-ai/src/skills/runtime-skills.ts index 16c7aa7f1f4..5ef7cc353ff 100644 --- a/packages/@n8n/instance-ai/src/skills/runtime-skills.ts +++ b/packages/@n8n/instance-ai/src/skills/runtime-skills.ts @@ -14,7 +14,7 @@ import { import { composeSkillVariants } from '../prompts/skill-variants'; export const INSTANCE_AI_SKILLS_DIR = resolve(__dirname, '..', '..', 'skills'); -const AGENTS_MODULE_RUNTIME_SKILLS = new Set(['agent-builder', 'intent-recognition']); +const AGENTS_MODULE_RUNTIME_SKILLS = new Set(['agent-builder']); let cachedRuntimeSkillSource: RuntimeSkillSource | undefined; const cachedProfiles = new Map>(); diff --git a/packages/@n8n/instance-ai/src/tools/__tests__/index.test.ts b/packages/@n8n/instance-ai/src/tools/__tests__/index.test.ts index a9f480ebc92..2e1b86be3c1 100644 --- a/packages/@n8n/instance-ai/src/tools/__tests__/index.test.ts +++ b/packages/@n8n/instance-ai/src/tools/__tests__/index.test.ts @@ -242,7 +242,7 @@ describe('domain tool construction', () => { it('pairs list-agent-capabilities with build-agent in the always-loaded set', () => { // Both are gated on the agents feature flag at module load time, so they // must always be in or out together — the orchestrator needs to check - // support during intent recognition on the same footing as build-agent. + // support before it chooses a workflow or Agent, on the same footing as build-agent. expect(ALWAYS_LOADED_TOOL_NAMES.has('list-agent-capabilities')).toBe( ALWAYS_LOADED_TOOL_NAMES.has('build-agent'), ); diff --git a/packages/@n8n/instance-ai/src/tools/tool-ids.ts b/packages/@n8n/instance-ai/src/tools/tool-ids.ts index 2d215380476..95e9a295846 100644 --- a/packages/@n8n/instance-ai/src/tools/tool-ids.ts +++ b/packages/@n8n/instance-ai/src/tools/tool-ids.ts @@ -90,7 +90,7 @@ export const ALWAYS_LOADED_TOOL_NAMES = new Set([ // on every agent build. ...(isAgentFeatureEnabled() ? [ORCHESTRATION_TOOL_IDS.BUILD_AGENT] : []), // Paired with build-agent: the model must be able to check supported agent - // channels/capabilities during intent recognition — before committing to a + // channels/capabilities while it chooses a workflow or Agent — before committing to a // path — so an unsupported channel (e.g. WhatsApp) is explained rather than // improvised as a workflow. Deferring it costs a search_tools + load_tool // round-trip and lets the model fall back to workflow assumptions first. diff --git a/packages/@n8n/instance-ai/src/tools/tool-modes.ts b/packages/@n8n/instance-ai/src/tools/tool-modes.ts index de700f5a2a7..ab45582f768 100644 --- a/packages/@n8n/instance-ai/src/tools/tool-modes.ts +++ b/packages/@n8n/instance-ai/src/tools/tool-modes.ts @@ -45,8 +45,6 @@ export const INSTANCE_AI_TOOL_MODES = { DOMAIN_TOOL_IDS.N8N_DOCS, DOMAIN_TOOL_IDS.CONVERSATION_HISTORY, DOMAIN_TOOL_IDS.MCP_SERVERS, - // The default mode must be able to tell an agent request from a workflow request. - ORCHESTRATION_TOOL_IDS.LIST_AGENT_CAPABILITIES, ...WEB_TOOLS, ], }, @@ -66,7 +64,8 @@ export const INSTANCE_AI_TOOL_MODES = { tools: [DOMAIN_TOOL_IDS.DATA_TABLES, DOMAIN_TOOL_IDS.N8N_DOCS], }, agents: { - description: 'Create, edit, or inspect n8n Agents.', + description: + 'Create, edit, or inspect n8n Agents, or check which chat channels and capabilities Agents support.', tools: [ ORCHESTRATION_TOOL_IDS.BUILD_AGENT, DOMAIN_TOOL_IDS.AGENTS,