{"workflow":{"id":13848,"name":"Production AI Playbook: Human Oversight (Exercise 2)","views":108,"recentViews":1,"totalViews":108,"createdAt":"2026-03-03T22:12:57.172Z","description":"Gate high-risk AI actions behind human approval. This template shows how to prevent an AI agent from executing sensitive operations (like sending contracts) without a human signing off first.\n\n**What you'll do**\n- Ask the AI agent to send a contract to a customer.\n- See the agent pause and present the intended action for review in the chat.\n- Approve or decline the action and watch the workflow respond accordingly.\n\n**What you'll learn**\n- How HITL (Human-in-the-Loop) for Tool Calls works in n8n\n- How to add a human review gate between an AI Agent and its tools\n- How the agent displays its intended action and waits for approval before executing\n- How to selectively gate high-risk tools while letting low-risk tools run freely\n\n**Why it matters**\nAI agents with tool access can take real-world actions. One wrong API call, one incorrect email, and you have a problem. This pattern ensures humans stay in control of the actions that matter while letting safe operations run automatically.\n\nThis template is a learning companion to the Production AI Playbook, a series that explores strategies, shares best practices, and provides practical examples for building reliable AI systems in n8n.  \n\n[Link to blog](https://go.n8n.io/PAP-HO-Blog)\n","workflow":{"meta":{"instanceId":"da13b80f35ed9d16adbf337111fadd798f3c80e989940f27089cab3947e57699","templateCredsSetupCompleted":true},"nodes":[{"id":"43844688-ff29-481f-a544-f8dc3d3fd602","name":"When chat message received","type":"@n8n/n8n-nodes-langchain.chatTrigger","position":[0,0],"webhookId":"dff6442e-8e15-46a1-826f-fac11188a6e5","parameters":{"options":{"responseMode":"responseNodes","allowFileUploads":false}},"typeVersion":1.4},{"id":"4b5965d9-3fdf-4ca6-81e6-21225f457798","name":"AI Agent","type":"@n8n/n8n-nodes-langchain.agent","position":[288,0],"parameters":{"options":{"systemMessage":"You are a sales pipeline assistant. You help manage deals by looking up CRM records, updating deal stages, and sending contracts to prospects. When the user provides deal details (deal ID, email, prospect name), use the Send Contract tool to send the contract. Use the Update CRM tool to update deal stages. Always use the available tools to take action."}},"typeVersion":3.1},{"id":"b944a6ca-38ba-4bbf-9903-03c2ff9e799b","name":"OpenRouter Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatOpenRouter","position":[224,224],"parameters":{"options":{}},"credentials":{"openRouterApi":{"id":"m9IRh1pT1eHIdKoX","name":"OpenRouter account 2"}},"typeVersion":1},{"id":"1def7515-5f42-451d-a207-f4c7a18a92f6","name":"Review: Send Contract","type":"@n8n/n8n-nodes-langchain.chatHitlTool","position":[480,224],"webhookId":"2e2897c0-ac6a-4483-b2c9-a1d5454676b5","parameters":{"options":{},"approvalOptions":{"values":{"approvalType":"double"}}},"typeVersion":1.2},{"id":"0248f52c-1bbf-4de0-b2c8-55ddc1d67df5","name":"Send Contract","type":"@n8n/n8n-nodes-langchain.toolCode","position":[480,432],"parameters":{"jsCode":"// Simulate sending a contract to a prospect\nconst data = JSON.parse(query);\nreturn `Contract sent to ${data.prospectEmail} for deal ${data.dealId}`;","description":"Sends a contract to a prospect. Input should be a JSON string with dealId and prospectEmail fields."},"typeVersion":1.3},{"id":"542612dc-099f-4a2c-b627-fd9bbb12a444","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-624,-224],"parameters":{"width":512,"height":816,"content":"## Sales Pipeline Agent with Tool Call Approval Gates\n\n### How it works\n1. **Chat Trigger** receives a request to send a contract (e.g., \"Send the Enterprise contract to john@acmecorp.com for deal 4521\").\n2. **AI Agent** processes the request and decides to call the Send Contract tool.\n3. **Human Review gate** intercepts the tool call before execution. The chat displays the intended action with Approve/Decline buttons.\n4. If approved, the **Send Contract** tool executes. If declined, the agent is notified and responds accordingly.\n\n### Setup\n- Connect your **LLM credentials** (e.g., OpenRouter, OpenAI) to the Chat Model node\n- Review the **Send Contract** code node to customize the contract-sending logic for your system\n- The Human Review step is configured via the \"+\" connector between the AI Agent and the Send Contract tool\n\n### Customization\n- Add more tools to the agent -- only gate high-risk tools (contract sends, payments) while leaving low-risk tools (data lookups) autonomous\n- Swap the Chat-based review for Slack or Email by changing the HITL integration\n\nThis template is a learning companion to the Production AI Playbook, a  series that explores strategies, shares best practices, and provides practical examples for building reliable AI systems in n8n.  \n\n[Link to blog](https://go.n8n.io/PAP-HO-Blog)\n"},"typeVersion":1}],"pinData":{},"connections":{"Send Contract":{"ai_tool":[[{"node":"Review: Send Contract","type":"ai_tool","index":0}]]},"OpenRouter Chat Model":{"ai_languageModel":[[{"node":"AI Agent","type":"ai_languageModel","index":0}]]},"Review: Send Contract":{"ai_tool":[[{"node":"AI Agent","type":"ai_tool","index":0}]]},"When chat message received":{"main":[[{"node":"AI Agent","type":"main","index":0}]]}}},"lastUpdatedBy":29,"workflowInfo":{"nodeCount":6,"nodeTypes":{"n8n-nodes-base.stickyNote":{"count":1},"@n8n/n8n-nodes-langchain.agent":{"count":1},"@n8n/n8n-nodes-langchain.toolCode":{"count":1},"@n8n/n8n-nodes-langchain.chatTrigger":{"count":1},"@n8n/n8n-nodes-langchain.chatHitlTool":{"count":1},"@n8n/n8n-nodes-langchain.lmChatOpenRouter":{"count":1}}},"status":"published","readyToDemo":null,"user":{"name":"Elvis Sarvia","username":"elvissaravia","bio":"","verified":true,"links":[],"avatar":"https://gravatar.com/avatar/ea69c5850ff18c010244a46216d72964c80a8d752fafefe2be114bdf6d05ae8a?r=pg&d=retro&size=200"},"nodes":[{"id":565,"icon":"fa:sticky-note","name":"n8n-nodes-base.stickyNote","codex":{"data":{"alias":["Comments","Notes","Sticky"],"categories":["Core Nodes"],"nodeVersion":"1.0","codexVersion":"1.0","subcategories":{"Core Nodes":["Helpers"]}}},"group":"[\"input\"]","defaults":{"name":"Sticky Note","color":"#FFD233"},"iconData":{"icon":"sticky-note","type":"icon"},"displayName":"Sticky Note","typeVersion":1,"nodeCategories":[{"id":9,"name":"Core Nodes"}]},{"id":1119,"icon":"fa:robot","name":"@n8n/n8n-nodes-langchain.agent","codex":{"data":{"alias":["LangChain","Chat","Conversational","Plan and Execute","ReAct","Tools"],"resources":{"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.agent/"}]},"categories":["AI","Langchain"],"subcategories":{"AI":["Agents","Root Nodes"]}}},"group":"[\"transform\"]","defaults":{"name":"AI Agent","color":"#404040"},"iconData":{"icon":"robot","type":"icon"},"displayName":"AI Agent","typeVersion":3,"nodeCategories":[{"id":25,"name":"AI"},{"id":26,"name":"Langchain"}]},{"id":1197,"icon":"fa:code","name":"@n8n/n8n-nodes-langchain.toolCode","codex":{"data":{"resources":{"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.toolcode/"}]},"categories":["AI","Langchain"],"subcategories":{"AI":["Tools"],"Tools":["Recommended Tools"]}}},"group":"[\"transform\"]","defaults":{"name":"Code Tool"},"iconData":{"icon":"code","type":"icon"},"displayName":"Code Tool","typeVersion":1,"nodeCategories":[{"id":25,"name":"AI"},{"id":26,"name":"Langchain"}]},{"id":1247,"icon":"fa:comments","name":"@n8n/n8n-nodes-langchain.chatTrigger","codex":{"data":{"resources":{"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-langchain.chattrigger/"}]},"categories":["Core Nodes","Langchain"]}},"group":"[\"trigger\"]","defaults":{"name":"When chat message received"},"iconData":{"icon":"comments","type":"icon"},"displayName":"Chat Trigger","typeVersion":1,"nodeCategories":[{"id":9,"name":"Core Nodes"},{"id":26,"name":"Langchain"}]},{"id":1281,"icon":"file:openrouter.svg","name":"@n8n/n8n-nodes-langchain.lmChatOpenRouter","codex":{"data":{"resources":{"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.lmchatopenrouter/"}]},"categories":["AI","Langchain"],"subcategories":{"AI":["Language Models","Root Nodes"],"Language Models":["Chat Models (Recommended)"]}}},"group":"[\"transform\"]","defaults":{"name":"OpenRouter Chat Model"},"iconData":{"type":"file","fileBuffer":"data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjOTRBM0I4IiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCIgdmlld0JveD0iMCAwIDI0IDI0IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjx0aXRsZT5PcGVuUm91dGVyPC90aXRsZT48cGF0aCBkPSJNMTYuODA0IDEuOTU3bDcuMjIgNC4xMDV2LjA4N0wxNi43MyAxMC4yMWwuMDE3LTIuMTE3LS44MjEtLjAzYy0xLjA1OS0uMDI4LTEuNjExLjAwMi0yLjI2OC4xMS0xLjA2NC4xNzUtMi4wMzguNTc3LTMuMTQ3IDEuMzUyTDguMzQ1IDExLjAzYy0uMjg0LjE5NS0uNDk1LjMzNi0uNjguNDU1bC0uNTE1LjMyMi0uMzk3LjIzNC4zODUuMjMuNTMuMzM4Yy40NzYuMzE0IDEuMTcuNzk2IDIuNzAxIDEuODY2IDEuMTEuNzc1IDIuMDgzIDEuMTc3IDMuMTQ3IDEuMzUybC4zLjA0NWMuNjk0LjA5MSAxLjM3NS4wOTQgMi44MjUuMDMzbC4wMjItMi4xNTkgNy4yMiA0LjEwNXYuMDg3TDE2LjU4OSAyMmwuMDE0LTEuODYyLS42MzUuMDIyYy0xLjM4Ni4wNDItMi4xMzcuMDAyLTMuMTM4LS4xNjItMS42OTQtLjI4LTMuMjYtLjkyNi00Ljg4MS0yLjA1OWwtMi4xNTgtMS41YTIxLjk5NyAyMS45OTcgMCAwMC0uNzU1LS40OThsLS40NjctLjI4YTU1LjkyNyA1NS45MjcgMCAwMC0uNzYtLjQzQzIuOTA4IDE0LjczLjU2MyAxNC4xMTYgMCAxNC4xMTZWOS44ODhsLjE0LjAwNGMuNTY0LS4wMDcgMi45MS0uNjIyIDMuODA5LTEuMTI0bDEuMDE2LS41OC40MzgtLjI3NGMuNDI4LS4yOCAxLjA3Mi0uNzI2IDIuNjg2LTEuODUzIDEuNjIxLTEuMTMzIDMuMTg2LTEuNzggNC44ODEtMi4wNTkgMS4xNTItLjE5IDEuOTc0LS4yMTMgMy44MTQtLjEzOGwuMDItMS45MDd6Ij48L3BhdGg+PC9zdmc+Cg=="},"displayName":"OpenRouter Chat Model","typeVersion":1,"nodeCategories":[{"id":25,"name":"AI"},{"id":26,"name":"Langchain"}]}],"categories":[{"id":39,"name":"CRM"},{"id":47,"name":"AI Chatbot"}],"image":[]}}