Build a Compliance Triage Workflow
Build an AI-assisted n8n workflow with human review and an audit trail.
Introduction
30 Second Summary
An unusual request can sound harmless until it mentions shared passwords, money transfers, or sensitive records. Someone still needs a clear way to decide which cases can move quickly and which ones need another pair of eyes.
In this project, you will build a browser-based compliance triage workflow with n8n and the Gemini API. It grounds each assessment in a stored policy rule while deterministic routing controls the path and keeps sensitive decisions with a human reviewer.
What You'll Build
You will submit a synthetic request in your browser, watch the workflow classify it as LOW or HIGH, review sensitive cases yourself, and inspect the final decision in an audit table.
By the end of this project, you'll have:
- A browser-based intake form where you submit synthetic compliance cases and send them into your local workflow.
- A policy-grounded AI assessment that compares each request with a stored rule before explaining its risk level.
- Human-controlled routing that completes LOW cases automatically. HIGH cases pause for your approval or rejection before the final outcome is stored in an audit table.
- Secret Mission: Add a REVIEW tier that sends ambiguous cases to human approval instead of allowing automatic approval.
Are there any prerequisites?
You need a Windows computer with internet access plus a Google account. The project guides you through every local tool and credential setup while keeping the workflow on free tiers.
Before We Start
Before any tools enter the picture, commit to the control boundary that keeps this workflow human-controlled. AI will assess synthetic compliance exception requests against stored policy. A human reviewer will approve or reject every HIGH-risk outcome.
Set Up n8n and Gemini
Your control boundary is clear. The model can assess a synthetic request, while a human owns every HIGH-risk decision.
This step gives that design a local home on your Windows computer. Node.js provides the runtime for n8n Community Edition.
A Gemini API credential lets later workflow nodes call the model without placing the key inside the workflow.
In this step, get ready to:
- Install Node.js v24.21.0 on Windows.
- Run n8n Community Edition 2.41.6 from PowerShell.
- Store a Free Tier Gemini API key in an n8n credential.
Install Node.js 24.21.0 LTS
n8n 2.41.6 requires Node.js 24.0.0 or newer. You will use the pinned v24.21.0 LTS release so your environment matches this project.
Windows PowerShell gives you a quick way to check whether the required runtime is already available.
- Press the Windows key to open Windows search.
- Type PowerShell into the search field.
- Press Enter to open PowerShell.
- Check the installed Node.js version by running this command:
node --version
What does this command check?
The node --version command asks the active Node.js installation to print its version. The result determines which setup path you need.
✔️ I see version 24.21.0
Your Node.js runtime matches the project. PowerShell is ready to install the pinned n8n release.
- Continue to the n8n installation below.
ⓧ I see an older version
Your current Node.js version is below the project requirement. The Windows installer uses a multi-step wizard and may request permission to update your computer.
- Open the official Node.js download page.
- Download the Windows installer for Node.js v24.21.0 LTS.
- Run the downloaded installer from your Downloads folder.
- Complete the setup wizard with its default selections.
- Press the Windows key to open Windows search.
- Type PowerShell into the search field.
- Press Enter to open a new PowerShell window.
- Confirm the updated version by running this command:
node --version
What should I see?
PowerShell should print v24.21.0. A new PowerShell window ensures Windows can find the updated installation.
ⓧ Command not found
Node.js is not installed yet. The Windows installer uses a multi-step wizard and may request permission to make changes to your computer.
- Open the official Node.js download page.
- Download the Windows installer for Node.js v24.21.0 LTS.
- Run the downloaded installer from your Downloads folder.
- Complete the setup wizard with its default selections.
- Press the Windows key to open Windows search.
- Type PowerShell into the search field.
- Press Enter to open a new PowerShell window.
- Confirm the installation by running this command:
node --version
What should I see?
PowerShell should print v24.21.0. This confirms that Node.js is installed and available to later commands.
Install and start n8n
The npm installation gives you a quick local n8n environment for development and testing. This setup is designed for learning on your computer.
Why use the npm installation?
The npm route keeps this Windows setup focused on workflow controls. It avoids adding container software before you build your first workflow.
n8n Community Edition remains free without a paid license key. Keep this installation local because npm-based n8n setups are intended for development and testing.
- Install n8n Community Edition 2.41.6 globally by running this command:
npm install -g n8n@2.41.6
What does this command install?
The -g option makes the n8n command available from PowerShell. The @2.41.6 suffix pins the project to the tested n8n release.
This installation can take several minutes while npm downloads n8n and its dependencies. A stream of package messages means PowerShell is still working.
Good progress. The pinned n8n command is now available on your computer.
Did the n8n installation fail?
- Confirm that the Node.js check prints v24.21.0.
- Open a new PowerShell window if the Node.js installer finished while the current window was open.
- Run the n8n installation command again after confirming the Node.js version.
Still stuck? Help me diagnose my n8n installation error. You can also search the n8n community for the message shown in PowerShell.
Starting n8n launches a local service that serves the workflow editor to your browser. PowerShell must remain open while you use the editor.
Before you start n8n, do you expect the editor to remain available if its PowerShell process stops?
- Start the local n8n service by running this command:
n8n start
What happens when n8n starts?
n8n starts a local web server at http://localhost:5678. The command keeps control of the PowerShell window until you stop it with Ctrl+C.
n8n stores its local state in the .n8n folder under your Windows user profile. Its default database uses SQLite.
- Keep the PowerShell window running.
- Open the local editor at http://localhost:5678.
- Complete the first-run owner setup if n8n displays it.
- Skip any optional paid-plan activation.
You should see the n8n editor load in your browser. This confirms that the local service is running from PowerShell.
That is the local environment live. Your workflows can now run on your own computer.
Does the local editor stay unavailable?
- Confirm that the PowerShell window running n8n is still open.
- Check that PowerShell has finished starting the local service before opening the address.
- Run n8n start in a new PowerShell window if the previous process stopped.
Still stuck? Help me troubleshoot my local n8n editor. You can also compare the symptoms with posts in the n8n community.
Create the Gemini credential
Google AI Studio issues the API key that authenticates Gemini requests. n8n stores the key as a credential so later nodes can use it without exposing it on the workflow canvas.
This setup stays on the Free Tier, so you do not need to enable billing. Free Tier content may be used to improve Google products.
Keep project data synthetic
Use invented policies and synthetic compliance cases throughout this project. Never submit client data, employee data, real credentials, or regulated records.
Treat the Gemini API key like a password. Keep it out of screenshots and messages.
- Open the Google AI Studio API key page.
- Sign in with your Google account.
- Accept the terms if Google AI Studio shows a first-run prompt.
- Confirm that the selected project remains on the Free Tier.
- Select Create API Key.
- Copy the newly generated API key.
Your new key is ready to store in n8n. Keep the key private because it authenticates requests made through your Gemini account.
- Switch back to the n8n editor from earlier.
- Select Create in the side menu.
- Select Credential.
- Search for Google Gemini(PaLM) credentials.
- Select the Google Gemini(PaLM) credential type.
- Paste the copied key into the API Key field.
- Confirm that API Host URL contains https://generativelanguage.googleapis.com.
- Select Save.
n8n saves the credential and tests the connection automatically. You should see the credential remain saved without a connection error.
You have connected the model without weakening the control boundary. Gemini can assess future cases, while your workflow still owns the routing.
Is the Gemini credential failing to save?
- Copy the API key again from Google AI Studio if the original value was incomplete.
- Confirm that the API Host URL is exactly https://generativelanguage.googleapis.com.
- Confirm that the Gemini project remains active on the Free Tier.
Still stuck? Help me diagnose my Google Gemini(PaLM) credential.
Before the final check, do you expect the saved credential to remain available while the PowerShell process keeps n8n running?
- Return to the PowerShell window from earlier.
- Confirm that the n8n process is still running.
- Return to the browser tab at http://localhost:5678.
- Open the Credentials list from the n8n editor.
- Select the saved Google Gemini(PaLM) credential.
You should see the editor respond and the saved credential show https://generativelanguage.googleapis.com while the API key remains concealed. This proves that the local runtime and model authentication are ready.
Your local n8n editor is running with a saved Gemini credential. Next, you will build the intake form and stored policy source that ground each assessment.
Build the Intake and Policy Lookup
Your local n8n editor is running. Your Gemini credential is ready for a later step.
An AI model needs the submitted request plus an explicit policy source. A browser form captures the request.
A stored policy lookup supplies the rule. This keeps the model from inventing the standard it should apply.
In this step, get ready to:
- Create the policy_rules table.
- Create the empty triage_audit table.
- Build the intake form with a matching policy lookup.
Create the policy lookup table
A data table stores structured rows inside n8n. The policy_rules table becomes the workflow's explicit source for compliance rules.
- Switch back to the n8n editor from earlier.
- Select the Data tables tab in your project.
- Click the split button in the top-right corner.
- Select Create Data table.
- Enter policy_rules as the table name.
- Select From scratch.
You should see the table editor for policy_rules.
- Create a String column named category using the table editor's column controls.
- Create a String column named policy_text using the same controls.
You should see category beside policy_text in the table header.
- Add one row to the table.
- Enter General in the category cell.
- Enter Requests involving money transfers, credential sharing, bypassing controls, or changes to regulated records require human review. Routine informational requests may be auto-approved. in the policy_text cell.
You've got the first control point in place. The future assessment now has a fixed rule to read.
Why Store the Policy Separately?
The table gives the workflow a visible source for model grounding. Every assessment can be tied to the exact rule retrieved for that request.
A reviewer can inspect the stored rule without editing the model prompt. The control stays visible outside the model.
Can't See the Policy Row?
- Check that both columns use the String type.
- Check that the category is spelled exactly as General.
- Confirm that the policy text appears in the same row as the category.
Still stuck? Help me check why my n8n policy_rules table is missing its General row.
Create the empty audit table
An audit table preserves the inputs plus the outcome of each case. You create its empty structure now so every later decision has a fixed destination.
- Return to the Data tables tab from earlier.
- Click the split button in the top-right corner.
- Select Create Data table.
- Enter triage_audit as the table name.
- Select From scratch.
You should see an empty table editor for triage_audit.
- Create a String column named case_id.
- Create a String column named request_text.
You should see the two case input columns in the table header.
- Create a String column named risk_level.
- Create a String column named reason.
You should now see four audit columns in the table header.
- Create a String column named decision.
Your triage_audit table should show five headers with no rows. That empty state is correct for this stage.
You now have a clean destination for every later decision.
Build and test the intake workflow
A Form Trigger turns each submitted field into workflow data. The Data Table node uses the submitted category to retrieve the matching policy row.
- Create a new workflow from the n8n workflows area.
- Add a Form Trigger as the first node.
You should see the Form Trigger as the starting node on the workflow canvas.
- Set Form Title to Compliance Exception Intake.
- Configure a required Text field named case_id with the label Case ID.
- Select Execute Step to load the first form preview.
- Enter CASE-PREVIEW in Case ID.
- Submit the preview form.
The generated page displays the Compliance Exception Intake title with a required Case ID field. Your workflow now has a working browser entry point.
- Return to the Form Trigger configuration in the editor.
- Configure a required Text field named request_text with the label Request Text.
- Configure the category dropdown as General under the label Category.
- Select Execute Step to load the complete form preview.
- Enter CASE-PREVIEW in Case ID.
- Enter Where can I find the travel policy? in Request Text.
- Select General from Category.
- Submit the preview form.
The form now captures all three inputs. The submitted values also give the editor sample data for the lookup mapping.
- Return to the Form Trigger configuration in the editor.
- Set Respond When to Workflow Finishes.
- Add a Data Table node after the Form Trigger.
You should see the Data Table node connected to the Form Trigger on the canvas.
- Select Row for Resource.
- Select Get for Operation.
The node should now display controls for choosing a data table and defining conditions.
- Select policy_rules as the data table.
- Click Add Condition.
A condition row should appear beneath the table selection.
- Select category for Column.
- Select Equals for Condition.
The lookup condition now compares the stored category column with an incoming value.
- Map category from the Form Trigger into Value using the input mapper.
Before you run the whole workflow, which row should the General selection retrieve?
- Select Execute Workflow.
- Enter CASE-001 in Case ID.
- Enter Where can I find the staff directory? in Request Text.
- Select General from Category.
- Submit the test form.
- Return to the workflow editor.
- Select the Data Table node to inspect its output panel.
You'll see one output item with category set to General.
Its policy_text is Requests involving money transfers, credential sharing, bypassing controls, or changes to regulated records require human review. Routine informational requests may be auto-approved..
That's the intake layer working. A submitted category now retrieves the exact policy row that governs the request.
No Policy Row in the Output?
- Check that the Data Table node reads from policy_rules.
- Check that the condition uses the category column with Equals.
- Confirm that the input mapper pulls category from the Form Trigger.
Still stuck? Help me troubleshoot why my n8n Data Table node does not return the General policy row.
Your intake form now supplies a synthetic case plus its matching stored policy. Next, you'll send both pieces into the first AI assessment.
Generate the First AI Assessment
Your intake workflow now pairs each synthetic case with the matching policy rule. That policy must reach the model alongside the request before the assessment can reflect your controls.
A Basic LLM Chain keeps the reasoning path focused on one defined task. This step produces your first visible risk assessment as free-form text.
In this step, get ready to:
- Ground a Basic LLM Chain with the submitted request plus the stored policy.
- Connect Gemini through the saved model credential.
- Test a synthetic credential-sharing case through the AI chain.
Build the grounded prompt
The chain needs the submitted request plus the stored policy. Together, those inputs keep the assessment tied to your workflow data.
- Switch back to the Compliance Exception Intake workflow from earlier.
- Add a Basic LLM Chain node to the right of the Data Table node.
You should see the new chain node on the workflow canvas.
- Connect the Data Table output to the Basic LLM Chain input.
A connection line should now carry the matching policy row into the chain.
- Select the Basic LLM Chain node.
- Set Prompt to Define below.
The Prompt (User Message) field should now be available for your mapped inputs.
- Use the input mapper in Prompt (User Message) to drag request_text from the Form Trigger.
You should see the mapped request_text value inside the prompt field.
- Use the input mapper to drag policy_text from the Data Table result into the same prompt field.
The Prompt (User Message) field should now contain both mapped values.
Why use a chain here?
An AI agent can choose tools or actions autonomously. This workflow follows one defined path from policy lookup to assessment.
n8n recommends a separate LLM chain when structured parsing needs consistent results. The chain keeps the model's role limited to interpretation.
The mapped inputs provide the evidence. A System chat message defines the model's role plus its approval boundary.
- Under Chat Messages (if Using a Chat Model) add a System chat message.
- Paste this exact instruction into the message field:
You are a compliance triage assistant. Compare the synthetic request with the supplied policy. Assess it as LOW or HIGH, explain the reason, and recommend the next action. Do not make the final approval decision.
What does this instruction control?
- The first sentence gives the model a narrow compliance triage role.
- The assessment instruction asks for a risk label plus policy-based reasoning.
- The final sentence preserves the human approval boundary.
- Confirm the complete instruction remains visible in the System message field.
Missing one of the mapped fields?
- Confirm Prompt is set to Define below.
- Reopen the input mapper to select request_text from the Form Trigger.
- Reopen the input mapper to select policy_text from the Data Table result.
Still stuck? Help me map the form request and stored policy into my Basic LLM Chain.
Connect the Gemini model
The chain determines what the model assesses. The Google Gemini Chat Model supplies the model that produces the response.
- Add a Google Gemini Chat Model through the chain's Model connector.
You should see the model node linked to the chain through its separate Model connection.
- Select the saved Google Gemini(PaLM) credential in the model node.
- Select models/gemini-2.5-flash as the model.
The model node should now show your saved credential plus models/gemini-2.5-flash.
Gemini model not connecting?
- Confirm the Google Gemini Chat Model is attached to the chain's Model connector.
- Confirm the saved Google Gemini(PaLM) credential is selected in the model node.
- Confirm the model value is models/gemini-2.5-flash.
Need help? Help me check why my Google Gemini Chat Model is not connected to my Basic LLM Chain.
✔️ My AI chain is ready
Your policy lookup now feeds a grounded prompt into the connected Gemini model.
ⓧ I'd like to double check the workflow
- The Form Trigger is titled Compliance Exception Intake.
- The Data Table node retrieves the matching row from policy_rules.
- The Basic LLM Chain follows the policy lookup.
- The Prompt (User Message) field maps request_text plus policy_text.
- The System chat message assigns risk as LOW or HIGH without making the final approval decision.
- The Google Gemini Chat Model uses models/gemini-2.5-flash through the saved Google Gemini(PaLM) credential.
- The chain currently returns free-form text.
Run a credential-sharing case
This case deliberately crosses two parts of the stored policy. It proposes credential sharing plus a change to a regulated record.
Use synthetic data only
The test request mentions credential sharing. Keep every name plus every login fictional.
Gemini Free Tier content may be used to improve Google products. Synthetic data keeps real people plus real systems out of the test.
- Select Execute Workflow in the n8n editor.
The test form should open in your browser.
- Enter CASE-003 in the case_id field.
- Enter Share a manager login with a vendor so the vendor can edit a regulated record. in the request_text field.
Both required fields should now contain fictional test data.
- Select General from the category dropdown.
Before you submit, do you expect the model to classify this request as LOW or HIGH?
- Submit the test form.
- Return to the n8n editor tab after the execution finishes.
- Select the Basic LLM Chain node to inspect its output.
You should see a free-form assessment that identifies the request as HIGH risk. Its reasoning should refer to credential sharing plus changes to regulated records.
The recommended action should call for human review. The response should stop short of approving or rejecting the case.
No assessment in the chain output?
- Confirm the PowerShell window running n8n is still active.
- Confirm the Google Gemini Chat Model remains attached to the chain's Model connector.
- Confirm the prompt still includes both mapped fields.
Need a hand? Help me diagnose why my Basic LLM Chain produced no Gemini assessment.
Your model now evaluates a synthetic request against stored policy. Next, you'll test whether its readable response gives deterministic routing a dependable field.
Watch Free-Form AI Break the Router
Your n8n workflow can now ask Gemini to assess a synthetic request against the stored policy. The answer is readable to a person.
Safe deterministic routing needs a dependable field that the workflow can compare. In this step, you will test whether the free-form response supplies that control point.
In this step, get ready to:
- Add a Switch node after the Basic LLM Chain.
- Configure named risk routes plus a fallback.
- Prove that the free-form assessment reaches UNMATCHED.
Add a LOW rule to the Switch
A Switch node routes each incoming item by comparing a field against defined values. This creates a workflow-controlled decision point.
- Switch back to the Compliance Exception Intake workflow in the n8n editor.
- Select the add-node control on the connection after the Basic LLM Chain.
- Search for Switch.
- Select the Switch node.
- Set Mode to Rules.
You should see the rule editor inside the Switch node. The Basic LLM Chain should connect directly to it.
- Set the first rule's data type to String.
- Enter {{$json.risk_level}} in the first rule's left value field.
- Set the first rule to test equality.
- Enter LOW in the first rule's right value field.
- Use Rename Output to name the first output LOW.
The Switch now displays a named LOW output. This route only receives items whose incoming risk_level field equals LOW.
What does the expression read?
The $json part refers to the current item entering the Switch. The risk_level part identifies the top-level field that the rule expects to compare.
Add HIGH and fallback routes
The second named route handles sensitive cases. A separate fallback catches every item that matches neither defined value.
- Add a second routing rule.
- Set the second rule's data type to String.
- Enter {{$json.risk_level}} in the second rule's left value field.
- Set the second rule to test equality.
- Enter HIGH in the second rule's right value field.
- Use Rename Output to name the second output HIGH.
- Set Fallback Output to Extra Output.
- Name the extra output UNMATCHED.
You should now see three output connectors named LOW, HIGH, plus UNMATCHED.
Why keep an UNMATCHED route?
An UNMATCHED route catches any result outside the two accepted values. This fail-closed design prevents an unsupported result from entering an approved path.
Run the designed failure
The router now expects a separate risk_level field. Before you execute the workflow, which output do you think receives a response that says HIGH inside a paragraph?
- Select Execute Workflow in the workflow editor.
- Enter CASE-004-HIGH in the case_id field.
- Enter Share a manager login with a vendor so the vendor can edit a regulated record. in the request_text field.
- Select General from the category dropdown.
- Submit the form.
- Select the Basic LLM Chain node in the completed execution.
You should see a free-form assessment that identifies the request as HIGH. Its reasoning should refer to credential sharing or changes to regulated records.
- Select the Switch node in the completed execution.
You will see the item reach UNMATCHED. The LOW output stays empty.
The HIGH output also stays empty. You have exposed the exact control gap that free-form model output creates.
Why did the router miss HIGH?
The model embedded HIGH inside a free-form text value. The Switch checks for a separate top-level risk_level field.
Neither named rule can match a field that the incoming item does not contain. The UNMATCHED fallback safely catches the item.
Did a named route receive the item?
- Open the Basic LLM Chain output to confirm the response remains one free-form text value.
- Open each Switch rule to confirm its left value references {{$json.risk_level}}.
- Check that the route values use the exact uppercase strings LOW plus HIGH.
Still stuck? Help me check why my n8n Switch did not send a free-form assessment to UNMATCHED.
You proved that readable model prose cannot serve as a dependable routing contract. Next, you will give the assessment a stable structure so the workflow can enforce its control boundary.
Add Structured Routing, Human Approval, and an Audit Trail
The last run proved that Gemini can explain a risky request. The n8n Switch still sent that explanation to UNMATCHED because the result lacked a dependable field.
A structured output contract gives the Switch a validated risk_level value for deterministic routing.
Human-in-the-loop review keeps sensitive decisions outside the model's control. Audit logging preserves the assessment beside the final decision.
In this step, get ready to:
- Constrain Gemini to a validated LOW or HIGH response.
- Route LOW cases automatically while pausing HIGH cases for a reviewer.
- Record both final decisions in triage_audit.
Lock the model into a structured contract
JSON Schema defines the exact fields that a valid assessment must contain. The parser uses this contract to turn the model response into fields that other nodes can read.
- Return to the Basic LLM Chain node in the workflow from earlier.
- Turn on Require Specific Output Format.
You should now see an Output Parser connector beneath the chain.
- Add a Structured Output Parser through the Output Parser connector.
- Set the parser mode to Define using JSON Schema.
The parser configuration now shows an editor for the schema that controls the model response.
- Replace the schema editor's contents with this schema:
{
"type": "object",
"properties": {
"risk_level": {
"type": "string",
"enum": ["LOW", "HIGH"]
},
"reason": {
"type": "string"
},
"recommended_action": {
"type": "string"
}
},
"required": ["risk_level", "reason", "recommended_action"],
"additionalProperties": false
}
What does this schema control?
- The risk_level enum limits valid risk labels to LOW or HIGH.
- The required list makes every assessment include the risk level.
- The same list requires a reason plus a recommended action.
- The additionalProperties setting blocks unexpected fields from entering the routing contract.
- Close the Structured Output Parser configuration.
- Switch back to the Basic LLM Chain node.
- Confirm that the parser remains attached to the Output Parser connector.
The chain now has a visible parser connection. This connection applies the schema to every new assessment.
- Return to the Switch node from the previous step.
- Replace its comparison input with the parsed risk_level field through the input mapper.
Keep the existing LOW output. Keep the existing HIGH output plus the UNMATCHED fallback.
Before you test the change, which Switch output do you expect the credential-sharing request to reach now?
- Select Execute Workflow.
- Enter CASE-HIGH-001 in the case_id field.
- Enter Share a manager login with a vendor so the vendor can edit a regulated record. in the request_text field.
The category remains set to General.
- Submit the synthetic case through the test form.
You should see parsed risk_level, reason, and recommended_action fields in the chain output. The Switch should send the item through HIGH instead of UNMATCHED.
That fixes the routing gap. The workflow now receives a field that deterministic logic can evaluate.
Still reaching UNMATCHED?
- Check that Require Specific Output Format remains enabled on the Basic LLM Chain.
- Check that the Structured Output Parser is connected to the chain's Output Parser connector.
- Remap the Switch input from the parsed risk_level field if the rule still points at the old free-form output.
Still stuck? Help me trace why my structured n8n result still reaches UNMATCHED.
Build the human and automatic branches
The validated label decides which path may continue. A HIGH case must collect a human decision before reaching the audit table.
- Connect the Switch's HIGH output to a new n8n Form node.
- Add the parsed risk_level to the form's visible page content through the input mapper.
The form preview should now display the model's risk level for the reviewer.
- Add the parsed reason to the visible page content through the input mapper.
- Add a dropdown field named review_decision.
The review page now presents the evidence beside a field for the human decision.
- Set the dropdown choices to APPROVE or REJECT.
- Make the review_decision field required.
The reviewer cannot continue without choosing one of the two permitted decisions.
- Connect the review form to a new Data Table node.
- Set Resource to Row.
The node now exposes operations that work with individual table rows.
- Set Operation to Insert.
- Select triage_audit as the destination table.
You should now see the five columns from triage_audit available for mapping.
- Set Mapping Column Mode to Map Each Column Manually.
Manual mapping gives you direct control over every value written to the audit record.
- Map case_id from the Compliance Exception Intake form.
- Map request_text from the Compliance Exception Intake form.
The audit row now preserves the original synthetic case beside its submitted identifier.
- Map risk_level from the parsed Basic LLM Chain output.
- Map reason from the parsed Basic LLM Chain output.
The same row now links the model's classification to its explanation.
- Map decision from the review form's review_decision field.
The final audit value comes from the reviewer. The model never supplies this field.
- Connect the HIGH branch's audit node to another n8n Form node.
- Configure that form as a completion screen.
The HIGH path now has a complete control loop from model assessment to human review to persistent audit record.
Before you run the HIGH path, where do you expect the browser to pause before the audit row is written?
- Select Execute Workflow.
- Enter CASE-HIGH-002 in the case_id field.
- Enter Share a manager login with a vendor so the vendor can edit a regulated record. in the request_text field.
The category remains set to General.
- Submit the synthetic HIGH case.
The browser should open the human review form. You should see the parsed HIGH risk plus the model's reason.
- Select REJECT from the review_decision dropdown.
- Submit the review form.
You should reach the HIGH branch's completion screen. This confirms that the reviewer controlled the final decision.
Review page missing the model result?
- Check that the review form connects directly to the Switch's HIGH output.
- Remap risk_level from the parsed chain output if the risk is blank.
- Remap reason from the parsed chain output if the explanation is blank.
Need help? Help me debug the missing values on my HIGH review form.
Why can LOW continue automatically?
The stored policy permits routine informational requests to complete automatically. The workflow assigns the fixed decision AUTO_APPROVED only after the validated parser returns LOW.
The Switch owns this decision path. Gemini only supplies the constrained assessment.
- Return to the workflow canvas from the HIGH test.
- Connect the Switch's LOW output to a new Data Table node.
- Set Resource to Row.
The LOW branch now has its own table node for writing a mutually exclusive audit row.
- Set Operation to Insert.
- Select triage_audit as the destination table.
The node should display the same five audit columns used by the HIGH branch.
- Set Mapping Column Mode to Map Each Column Manually.
The manual column fields are now ready for the automatic path's values.
- Map case_id from the Compliance Exception Intake form.
- Map request_text from the Compliance Exception Intake form.
The LOW audit row now includes the submitted case details.
- Map risk_level from the parsed Basic LLM Chain output.
- Map reason from the parsed Basic LLM Chain output.
The automatic path now records the validated classification beside the model's explanation.
- Set the decision value to the fixed string AUTO_APPROVED.
The fixed value makes the source of the final decision visible in the audit table.
- Connect the LOW branch's audit node to another n8n Form node.
- Configure that form as a completion screen.
The LOW branch can now write its automatic decision before showing the browser confirmation.
Before you test the routine request, do you expect a review page or a direct completion page?
- Select Execute Workflow.
- Enter CASE-LOW-001 in the case_id field.
- Enter Send me the public training schedule for next month. in the request_text field.
The category remains set to General.
- Submit the synthetic LOW case.
You should reach the LOW branch's completion screen without seeing the human review form. The execution should travel through the LOW Switch output.
LOW case opening the wrong path?
- Inspect the parsed risk_level to confirm the model returned LOW for the routine request.
- Check that the Switch's LOW output connects directly to the LOW audit node.
- Check that the HIGH review form has no connection from the LOW output.
Still seeing the review form? Help me trace my LOW route through the n8n workflow.
Inspect the audit record
The audit table is the evidence that assessment and authority remained separate. Each row should show what the model concluded plus who controlled the final outcome.
Before you inspect the table, which two decision values do you expect to find?
- Return to the Data tables area in the n8n editor.
- Select the triage_audit table.
You should see a HIGH row containing the submitted case details. Its risk_level should be HIGH with a final decision of REJECT.
You should also see a LOW row containing the routine request. Its risk_level should be LOW with a final decision of AUTO_APPROVED.
You have closed the control loop. Structured output now drives deterministic routes while human review protects sensitive cases.
Secret mission
Add a REVIEW Safety Tier
Add REVIEW to the model's output contract. Route ambiguous cases through the existing human review path so uncertainty can never trigger automatic approval.
Clean Up Your Resources
Clean Up Your Resources
Choose whether to keep the local workflow available, pause its running process, or remove it. This project stays at $0 because local files create no charges while your Gemini API project remains on the Free Tier.
Resources you used:
- The running local n8n Community Edition process at version 2.41.6 in Windows PowerShell.
- The global n8n Community Edition installation at version 2.41.6.
- The local .n8n user folder containing the SQLite database plus encrypted credential data.
- The Compliance Exception Intake workflow.
- The policy_rules data table.
- The triage_audit data table containing your synthetic audit records.
- The project API key created in Google AI Studio.
Keep everything running
No action is needed. Choose this option if you are still testing or demonstrating the compliance triage workflow.
- Keep the PowerShell window from earlier running so the local n8n editor stays available.
- Return to the editor at http://localhost:5678 whenever you want to submit another synthetic case.
- Keep the Gemini project on the Free Tier.
- Continue using synthetic requests plus invented policy data.
Your workflow remains ready to demonstrate. LOW cases still complete automatically while REVIEW plus HIGH cases still require a human decision.
Pause - I'll come back to this later
Shut down the running n8n process to free local memory. Your workflow data remains stored in the .n8n user folder.
- Return to the PowerShell window running n8n.
- Press Ctrl+C to stop the local process.
- Confirm that PowerShell returns to its normal prompt.
That's the pause complete. Your workflow, encrypted credential, data tables, plus execution history remain available for your return.
- Restart your local n8n service later by running this command:
n8n start
What does this command do?
The n8n start command launches your existing local n8n instance from the data stored in .n8n.
- Return to the browser tab containing the n8n editor.
- Refresh http://localhost:5678.
You should see the editor load with the Compliance Exception Intake workflow plus both data tables still available.
Does the editor stay unavailable?
Confirm that the PowerShell window running n8n remains open. A closed window stops the local service.
If PowerShell cannot start n8n, make sure you are using the same Windows account from this project. Help me restart my local n8n 2.41.6 installation.
Delete - I don't want to use this again
Remove the project resources if you no longer need this workflow. This option permanently removes the synthetic audit trail plus your saved local configuration.
Deleting the .n8n folder is the irreversible part. Keep that folder if you want to preserve any other local n8n workflows or credentials.
Revoke the Gemini API key:
- Return to the Google AI Studio API key page.
- Locate the API key created for this project.
- Revoke the API key.
- Complete the confirmation prompt.
Delete the n8n workflow:
- Return to the n8n editor from earlier.
- Open the workflow list from the left sidebar.
- Select Compliance Exception Intake.
- Use the workflow menu to choose Delete.
- Complete the confirmation prompt.
Delete the n8n data tables:
- Select Data tables in the left sidebar.
- Open policy_rules.
- Use the table menu to choose Delete.
- Complete the confirmation prompt.
- Repeat the deletion for triage_audit.
Stop plus uninstall n8n:
- Return to the PowerShell window from earlier.
- Press Ctrl+C if the local n8n process is still running.
- Remove the global n8n installation by running this command:
npm uninstall -g n8n
What does this command remove?
The npm uninstall -g n8n command removes the globally installed n8n package.
The command leaves the .n8n user folder in place. This protects local workflows plus credentials until you deliberately delete that folder.
You should see package removal output before PowerShell returns to its normal prompt.
Does the uninstall fail?
Confirm that the n8n process has stopped before retrying the uninstall command.
If the global package remains installed, help me troubleshoot the n8n uninstall.
Remove the local n8n data:
The .n8n folder can be easy to miss because its name starts with a dot. Remove it only after confirming that you do not need its workflows, credentials, or execution history.
- Press the Windows key to open search.
- Search for File Explorer.
- Press Enter to open it.
- Navigate to your Windows user profile folder.
- Select the .n8n folder.
- Press Delete.
- Empty the Windows Recycle Bin to remove the local copy completely.
Your project resources are now removed. Node.js can remain installed for later projects.
Nice Work!
Nice Work!
Mission accomplished! Your n8n workflow now grounds Gemini assessments in stored policy.
You've learned how to:
- Build a browser-based intake workflow for synthetic compliance exception requests. Ground each assessment in the matching stored policy rule.
- Expose the free-form output gap by watching prose fall through the router. Replace that gap with a validated structured output contract for deterministic LOW or HIGH routing.
- Route sensitive cases through human review before continuation. Preserve each model reason beside its final decision in triage_audit. This creates an audit trail.
- Complete the optional Secret Mission by adding a fail-safe REVIEW tier. Ambiguous requests now enter the same human review path as HIGH cases.
Ready to quiz yourself?