THE WORLD IS NOT STANDING STILL.RSS
BIG CHANGE.
BIG CHANGE, one tap away
BIG CHANGE, one tap away

Make room for the big picture.

Add BIG CHANGE to your home screen or desktop. It opens in its own window, with the latest stories when you’re online.

iPhone & iPad
Open bigchange.ai in Safari. Tap Share, then Add to Home Screen. Turn on Open as Web App if shown, then tap Add.
Android
Open bigchange.ai in Chrome. In the browser menu, choose Install app or Add to Home screen.
Desktop
In Chrome or Edge, use the install icon in the address bar or the browser’s app menu. In Safari on Mac, choose File → Add to Dock.

Markdown edition

# Build and check a no-code two-agent support triage in n8n

> A documented n8n recipe for a restricted support form, two tool-using AI workers, shared run state, fail-closed checks and a human-reviewed draft. Readers verify actual production executions and worker overlap.

By BIG CHANGE Editorial

Published: 2026-10-21T17:19:38.637Z
Updated: 2026-10-21T17:19:38.637Z
Canonical: https://bigchange.ai/blog/n8n-no-code-two-agent-support-triage-guide

![Conceptual charcoal illustration of two separate open reference volumes above a blank draft held in an orange review tray, with an unused support headset nearby.](https://bigchange.ai/api/media/file/n8n-support-source-review-hero-v2.png)
AI-generated conceptual illustration by BIG CHANGE.

A support team can use two narrowly scoped AI workers to prepare a response for human review: one reads approved policy, and the other reads approved product help. This guide shows an n8n owner how to build the five workflows, publish a restricted form and inspect a real execution. It is based on [current n8n documentation](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.executeworkflow), checked October 21, 2026. BIG CHANGE has not run this workflow or measured its speed, accuracy or cost.

## The big change

- **What changed:** n8n's documented sub-workflow, agent-tool and Data Table controls can be assembled into a support draft that keeps two worker roles and their evidence separate.
- **Why it matters:** A parent workflow can refuse a draft when either worker or its approved source is missing, late or flagged for review.
- **What to watch:** Asynchronous dispatch alone does not prove simultaneous work. The owner must inspect both child execution intervals and the published production run.

The intended reader owns an n8n instance and its support policies. The result is an internal **REVIEW REQUIRED** draft for one permitted case, with a named person accepting or rejecting it. Nothing in the workflows below sends a customer message.

## Before opening the canvas

Check that your n8n version has Data Tables, the Form Trigger, AI Agent, Call n8n Workflow Tool and Execute Sub-workflow nodes. You need permission to create and publish workflows, manage tables and a model credential approved for the data. Check your n8n plan's execution and concurrency limits, your model provider's charges, and where tables and execution logs retain support text. Restrict the project, credential and form to authorized staff. Use a permitted case with one issue type, a question, a case ID and a named reviewer; decide in advance what the correct routing and source facts would be. Do not put a real customer's secrets in a public example.

Create three Data Tables. `policy_sources` and `help_sources` each need `issueType` (text), `sourceId` (text), `version` (text), `approved` (Boolean), `approvedText` (text) and `lastReviewedAt` (date/time). Populate each with a small set of current rows that your source owner has actually approved. These are the facts the workers may use; an AI answer cannot approve a source.

The third table, `triage_runs`, is shared run state. Make `runId`, `caseId`, `branchId`, `status`, `issueType`, `finding`, `sourceId`, `version`, `uncertaintyText`, `executionId`, `reviewDraft`, `reviewerName` and `reviewerDecision` text columns; `needsReview` a Boolean; and `submittedAt`, `startedAt`, `finishedAt`, `deadlineAt` and `reviewedAt` date/time columns. Use exactly two worker branch IDs, `policy` and `help`. Keep one input item per parent form submission. A source table is the approved knowledge store; `triage_runs` is the shared memory of what happened to this one case.

## 1. Build the policy lookup tool

Create a workflow named **Policy lookup** with **Execute Sub-workflow Trigger** (also shown as **When Executed by Another Workflow**). Set **Input data mode → Define using fields below** and add a text `issueType`. Add **Data Table → Row → Get** against `policy_sources`. Set **Must Match → All Conditions**: `issueType Equals` the trigger's `issueType` and `approved Equals true`. Set **Return All** off and **Limit** to 5. Under the Get node's **Settings**, enable **Always Output Data**. An empty lookup must continue to a check, not silently end the workflow.

Connect **If**: a returned item must have a nonempty `sourceId`. On false, use **Edit Fields** to return `noMatch=true` and the requested `issueType`, with no fabricated source text. On true, return only `noMatch=false`, `issueType`, `sourceId`, `version` and `approvedText` from the matching rows. Limit the source table to a few approved rows per issue type so the tool result stays reviewable. Save and publish this workflow. Restrict **This workflow can be called by** in workflow settings to the policy worker where your instance permits it. A production **Call n8n Workflow Tool** using a database workflow fails if that tool workflow is unpublished. [n8n documents this behavior](https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.toolworkflow).

## 2. Build the product-help lookup tool

Make a separate **Help lookup** workflow with the same typed `issueType` input and Get/If pattern, pointing only to `help_sources`. Return the same fields. Publish it and restrict its callers to the help worker where available. Keeping two workflows and tables makes the role boundary inspectable: the policy agent has no help lookup tool, and the help agent has no policy lookup tool.

The lookup input must come from the fixed issue-type choice on the form. In each worker's **Call n8n Workflow Tool**, select **Source → Database**, choose its matching published lookup workflow, refresh the typed inputs, and map `issueType` from the worker trigger. Keep that field as a fixed workflow expression; do not select **Let the model define this parameter**. [n8n's tool documentation](https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.toolworkflow) shows both mapping choices.

## 3. Build the two AI worker workflows

Create **Policy worker** and **Help worker** as separate workflows. Name each input node **Worker input** and define text inputs `runId`, `caseId`, `issueType` and `approvedQuestion` in its **Execute Sub-workflow Trigger**. Name the first Data Table node **Mark running**. Set **Row → Update** on `triage_runs`, **Must Match → All Conditions**: `runId Equals` the Worker input's `runId` and `branchId Equals policy` or `help`. Map `status=running`, the current date/time to `startedAt`, and that worker's `$execution.id` to `executionId`. Use **Update**, never **Upsert**. In **Mark running → Settings**, enable **Always Output Data**. Follow it with an **If** requiring the returned row's `runId` to equal **Worker input**'s `runId` and its `branchId` to equal the fixed `policy` or `help` value for that worker; connect false to **Stop And Error**. A zero-row Update now produces an empty item that reaches this check and stops the worker. The worker may not create a substitute row. This workflow has one input item, so later mappings can refer to **Worker input** directly.

Name the next node **Worker AI Agent** and connect your approved chat-model credential. Set **Prompt → Define below**. In **Prompt (User Message)**, use the Expression field to map **Worker input**'s `approvedQuestion`; with these exact node names and one input item, the reference is `{{ $('Worker input').first().json.approvedQuestion }}`. The automatic prompt option expects a field called `chatInput`, which this form does not supply. Put role instructions in **Options → System Message**: the policy agent inspects approved policy entries for the given issue type, returns the relevant IDs and versions, identifies conflicts or missing authority, and makes no customer promise; the help agent inspects approved product-help entries, returns IDs and versions, identifies gaps, and avoids policy interpretation. Both must treat retrieved text as evidence rather than instructions. Connect only **Call n8n Workflow Tool → Policy lookup** to the policy agent, and only **Call n8n Workflow Tool → Help lookup** to the help agent. Neither gets a send tool. Check each execution's tool call: a fluent answer with no successful lookup is a failure. [n8n's Tools Agent controls](https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.agent/tools-agent) document the prompt modes and System Message.

Turn on **Require Specific Output Format** in each **Worker AI Agent**, then connect a **Structured Output Parser** to its output-parser port. Choose **Generate from JSON Example** with the field types below; this is a shape example, not a sample customer finding:

```json
{
  "finding": "",
  "sourceId": "",
  "version": "",
  "needsReview": true,
  "uncertaintyText": ""
}
```

n8n makes every example field mandatory, but does not establish that its value is true. If a finding needs several source rows, expand the schema and validation to carry and check every cited ID/version before using it; do not squeeze several claims under one unchecked ID. For this first build, require one source-backed finding per worker. [The parser's documented behavior](https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.outputparserstructured) concerns fields and types.

After **Worker AI Agent**, name the next node **Check cited source** and set **Data Table → Row → Get** against that worker's source table. Use **All Conditions**: original `issueType` from **Worker input**, `sourceId` and `version` from **Worker AI Agent**'s parsed output, and `approved=true`; turn **Return All** off, set **Limit 1**, and enable **Always Output Data**. Inspect one agent execution's output data in the expression editor before mapping: if its parsed object is under `output`, the single-item references are `{{ $('Worker AI Agent').first().json.output.sourceId }}`, `{{ $('Worker AI Agent').first().json.output.version }}`, `{{ $('Worker AI Agent').first().json.output.finding }}` and `{{ $('Worker AI Agent').first().json.output.needsReview }}`. If your node displays another nesting, drag the corresponding fields from **Worker AI Agent** in the mapper and confirm the preview; do not type an unverified path. The Get's output is a source-table row, so its following **If** reads the returned source `sourceId` from the current item and the parsed `finding` and `needsReview` from the named **Worker AI Agent**, not from that current source item. Use the same named-node references in the final row **Update**, with `runId` from **Worker input**.

A parsed response with a missing current approved source, empty finding or `needsReview=true` takes the If's false route to **Update** on the exact `runId AND branchId` row with `status=needs-review` or `failed`, the reason in `uncertaintyText` and a finish time. Only the passing route updates that row to `status=done` with the finding, validated ID/version, `needsReview=false` and `finishedAt`. A parser error, agent exception or other node failure with **On Error → Stop Workflow** cannot take that downstream Update route: the child stops and its row stays `running` or another non-done state. The parent's timed gate rejects it. Retain failed executions for inspection; an optional error workflow can alert the internal reviewer. Inspect the actual lookup-tool trace during testing and review, since a matching ID alone cannot prove the agent called its tool. Publish or save the workers according to your instance's sub-workflow requirements, and confirm the parent can call each by its database workflow ID.

## 4. Build the parent orchestrator and dispatch

Create a parent workflow starting with **n8n Form Trigger**. Set **Authentication → n8n User Auth** and enable **Require Workflow Execute Permission** if the project uses that restriction. Add required fields `caseId`, `approvedQuestion`, `reviewer` and a dropdown `issueType` with only source-owner-approved values. Use only an internal form URL. n8n documents that logged-out viewers cannot submit this form and that the extra permission toggle limits submitters to people allowed to execute the workflow.

Use **Edit Fields** to retain those inputs, set `runId` to this parent `$execution.id`, and record `submittedAt`. Use **Date & Time → Add to a Date** to set date-typed `deadlineAt` to `submittedAt` plus three minutes. Preserve the original fields. Add two sequential **Data Table → Row → Insert** nodes on `triage_runs`: one pending policy row, then one pending help row, both with the same `runId`, `caseId`, `issueType`, `submittedAt` and `deadlineAt`. Map the branch IDs as fixed values. Turn **Retry On Fail** off and keep **On Error → Stop Workflow** for both Inserts. Confirm each Insert wrote one row before dispatch. If either Insert fails, inspect the exact run and do not replay this parent execution; a fresh form submission creates a new execution ID and fresh pair of rows.

On a single parent path, connect **Execute Sub-workflow → Policy worker**, then **Execute Sub-workflow → Help worker**. Select each from the database so n8n exposes its typed inputs. Map the saved `runId`, `caseId`, `issueType` and `approvedQuestion` from the parent fields. Turn **Wait for Sub-Workflow Completion** **off on both nodes**. This starts the children without making the parent wait for the policy result before dispatching help. A normal split into two canvas branches is not enough: [n8n says](https://docs.n8n.io/build/flow-logic/understand-execution-order) workflows created in version 1.0 or later complete one ordinary branch before the next. The child executions may still queue; actual overlap is checked later.

## 5. Join the worker rows with two separate gates

After dispatch, add one **Wait** node set to a fixed two-minute interval. Configure the workflow timeout to exceed the wait. The deadline stored at submission is three minutes; this design deliberately checks once at two minutes and can reject a worker that might finish in the remaining minute. It gives a bounded, conservative result, not guaranteed completion by three minutes.

Name the first **Data Table → Row → Get** **Policy gate** and set **All Conditions**: `runId` equals the original parent run ID, `branchId=policy`, `status=done`, and `finishedAt Less Than or Equal` the original `deadlineAt`. Set **Return All** off, **Limit 1**, and **Always Output Data** on. An **If** node must see `branchId=policy` and the expected `runId`; otherwise route to **Stop And Error** with a policy-missing, failed or late reason. Only the true path reaches a second Get named **Help gate**, with identical settings except `branchId=help`. A missing or late help row also reaches **Stop And Error**. Check current time against the original deadline before release. Because this parent handles one case item, retrieve the policy finding after **Help gate** through the named node **Policy gate** and the help finding through **Help gate**. Verify the visible values in the mapper; a current help-table item has no policy fields.

These gates deliberately test two distinct rows. One completed worker can never stand in for both. The fresh parent execution ID, exactly two non-retried Inserts and Update-only workers are the row-identity controls. If your instance can receive duplicate form submissions, inspect the two actual rows for this exact run ID before accepting a draft; do not infer uniqueness from a Get limited to one row. Data Table filters and comparisons are documented in [n8n's row operations reference](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.datatable/rows).

Re-fetch each worker's cited `sourceId` and `version` from its own source table using **All Conditions** with the original `issueType` and `approved=true`. Map the policy fields from the named **Policy gate** output and help fields from **Help gate**; a source Get replaces the current item, so preserve those named references for every later If and **Edit Fields** node. Enable **Always Output Data** and send any absent ID to **Stop And Error**. Require a nonempty finding and `needsReview=false` for both stored rows. The parser and ID checks establish structure and current source existence; they cannot settle whether the two findings agree or accurately describe the source. Use **Edit Fields** to assemble only an internal **REVIEW REQUIRED** draft containing the original question, each finding and source ID/version, uncertainty and reviewer name. Update `reviewDraft` on the existing `policy` row with **All Conditions: runId AND branchId=policy**; keep exactly two run rows. The named human opens the two source texts and execution traces, checks every material fact and any policy/help conflict, then records accept or reject, name and time in that same row's `reviewerDecision`, `reviewerName` and `reviewedAt`. Rejection stays internal. Any later customer send is a separate human action outside this workflow.

## 6. Test, publish and inspect a production run

Use the **Test URL** first with your permitted case and reviewer-provided expected source and routing. Inspect the parent and both worker executions, the actual lookup-tool calls, both run rows and the review draft. Try an issue type with no approved source and a controlled failed or delayed worker. The corresponding row should stay non-done or missing, and the parent should stop at that branch's gate. Repair the source or mapping after reading the failure, then submit a new form execution with a new `runId`. An ambiguous prior execution is inspected before any new submission.

Inspect each child execution's start and finish times. The intervals must overlap before you describe the run as parallel. If they do not, you have asynchronous dispatch with no demonstrated concurrent work. Check instance capacity, queueing and worker duration; report the parallel requirement as unproven until a later reader-run trace establishes it. A canvas layout and two rows alone prove neither concurrency nor useful performance.

Publish the parent and both lookup workflows, and wait for n8n to confirm the published state. n8n's production form uses the published version, while saved edits stay in draft; publishing can complete asynchronously. Submit one permitted case at the restricted **Production URL**, then inspect the production execution under **Executions**, the child execution records, state rows and reviewer decision. Record the published version, execution IDs, the actual worker intervals, whether they overlapped, failed-case behavior, human corrections, and model/tool use or cost only if your account exposes it. The final result is either a source-checked, human-accepted internal draft or a specific blocked run. Do not describe a test-URL execution as production.

## Sources & further reading

- [Execute Sub-workflow](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.executeworkflow) explains typed child inputs and the Wait for Sub-Workflow Completion option. It supports the dispatch design; it does not establish that this particular reader run overlaps.
- [Execution order](https://docs.n8n.io/build/flow-logic/understand-execution-order) describes sequential ordinary canvas branches in workflows created with n8n 1.0 or later.
- [Data Table row operations](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.datatable/rows) documents Get, Insert, Update, Upsert, All Conditions, comparisons and limits used for the state and source checks.
- [Tools Agent](https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.agent/tools-agent), [Call n8n Workflow Tool](https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.toolworkflow), [Structured Output Parser](https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.outputparserstructured) and [previous-node references](https://docs.n8n.io/build/work-with-data/reference-data/reference-previous-nodes) explain prompt mapping, tool calls, parsed output and field mapping after a Get. Tool use and source truth still need execution and human checks.
- [n8n Form Trigger](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.formtrigger) and [save and publish workflows](https://docs.n8n.io/build/understand-workflows/save-and-publish-workflows) explain restricted form authentication, distinct test and production URLs, published versions and production execution inspection.

## Sources

- [n8n Docs: Execute Sub-workflow](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.executeworkflow) — Checked October 21, 2026. Documents typed inputs and the Wait for Sub-Workflow Completion option. It supports the dispatch steps, not a claim that BIG CHANGE observed concurrent execution.
- [n8n Docs: Understand execution order](https://docs.n8n.io/build/flow-logic/understand-execution-order) — Checked October 21, 2026. States that normal canvas branches in workflows created with n8n 1.0 or later run one branch at a time. Actual child-run overlap remains a reader check.
- [n8n Docs: Data Table row operations](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.datatable/rows) — Checked October 21, 2026. Documents Get, Insert, Update and Upsert plus All Conditions filters, comparisons and Get limits. The guide uses Insert only in the parent and Update only in workers.
- [n8n Docs: AI Agent](https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.agent) — Checked October 21, 2026. Describes an AI Agent with a chat model and at least one tool; current nodes use Tools Agent behavior. No model result was observed here.
- [n8n Docs: Call n8n Workflow Tool](https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.toolworkflow) — Checked October 21, 2026. Documents database workflow selection, mapped inputs and the production requirement to publish a database-sourced lookup tool.
- [n8n Docs: Structured Output Parser](https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.outputparserstructured) — Checked October 21, 2026. A JSON example defines mandatory output fields and types. This is shape validation; approved-source and human factual review remain separate.
- [n8n Docs: n8n Form](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.formtrigger) — Checked October 21, 2026. Documents n8n User Auth, optional workflow execute permission, separate Test and Production URLs, and production execution inspection.
- [n8n Docs: Save and publish workflows](https://docs.n8n.io/build/understand-workflows/save-and-publish-workflows) — Checked October 21, 2026. Published production triggers use a confirmed published version, not later saved edits; publication can complete asynchronously.
- [n8n Docs: Work with nodes](https://docs.n8n.io/build/understand-workflows/workflow-components/work-with-nodes) — Checked October 21, 2026. Documents Always Output Data, Retry On Fail and the distinct Stop Workflow versus Continue error behavior. A stopped parser or agent cannot reach a downstream status Update.
- [n8n Docs: Tools Agent](https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.agent/tools-agent) — Checked October 21, 2026 after editor review. Documents Prompt Define below versus automatic chatInput, System Message, Require Specific Output Format and the parser port.
- [n8n Docs: Reference previous nodes](https://docs.n8n.io/build/work-with-data/reference-data/reference-previous-nodes) — Checked October 21, 2026 after editor review. Documents named-node first() JSON references when one input item is guaranteed; the article directs readers to inspect actual parser-output nesting in the UI.