{"id":393,"date":"2025-12-11T21:58:14","date_gmt":"2025-12-11T20:58:14","guid":{"rendered":"https:\/\/techbygiusi.com\/?p=393"},"modified":"2026-03-15T16:32:09","modified_gmt":"2026-03-15T15:32:09","slug":"building-your-own-n8n-agent-for-your-homelab","status":"publish","type":"post","link":"https:\/\/techbygiusi.com\/index.php\/guide\/building-your-own-n8n-agent-for-your-homelab\/","title":{"rendered":"Building Your Own n8n Agent for Your Homelab"},"content":{"rendered":"\n<p>Over the past few weeks, I came across several YouTube videos showing how n8n can be used as a small but powerful helper inside a homelab environment. After watching a few of them, I couldn\u2019t resist the urge to build my own agent.<\/p>\n\n\n\n<p>Shout-out to <a href=\"https:\/\/www.youtube.com\/@NetworkChuck\" target=\"_blank\" rel=\"noreferrer noopener\">@NetworkChuck<\/a><\/p>\n\n\n\n<p><strong>What my agent already handles<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Monitor the overall health of my Homelab infrastructure<\/li>\n\n\n\n<li>Troubleshoot issues in Docker or LXC<\/li>\n\n\n\n<li>Start and stop VMs, LXC containers, or Docker containers<\/li>\n\n\n\n<li>Inspect and analyze log files<\/li>\n<\/ul>\n\n\n\n<p><strong>What I\u2019m currently working on<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A dedicated tool for Wazuh access<\/li>\n\n\n\n<li>A Unifi integration (though Unifi still limits access to read-only)<\/li>\n\n\n\n<li>A Proxmox Backup Server access<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"#lb-1-27bfb1a8\" class=\"lb-thumb\" aria-label=\"Bild vergr\u00f6\u00dfern\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"496\" src=\"https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-1024x496.png\" alt=\"\" class=\"wp-image-394\" srcset=\"https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-1024x496.png 1024w, https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-300x145.png 300w, https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-768x372.png 768w, https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-1536x744.png 1536w, https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image.png 1660w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\"><\/a><\/figure>\n\n\n\n<p><strong>My current core nodes of the agent<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Webhook<\/strong> the entry point for external triggers<\/li>\n\n\n\n<li><strong>Field editing<\/strong> for dynamic input and configuration<\/li>\n\n\n\n<li><strong>AI Agent<\/strong> the heart of the system<\/li>\n\n\n\n<li><strong>OpenAI Chat Model<\/strong> (or any preferred model)<\/li>\n\n\n\n<li><strong>Simple memory layer<\/strong> to maintain context across actions<\/li>\n\n\n\n<li><strong>Webhook responses<\/strong> <\/li>\n\n\n\n<li><strong>Various Tools<\/strong> each tool serves a specific purpose, such as SSH utilities or API-based functions<\/li>\n<\/ul>\n\n\n\n<h6 class=\"wp-block-heading\">Step-by-Step Guide<\/h6>\n\n\n\n<p>We begin with the <strong>Webhook<\/strong> node \u2014 the entry point of the entire agent. Every command sent from the Web-GUI arrives here first. Make sure the HTTP method is set to <strong>POST<\/strong>, since this allows you to send structured data such as JSON. In my setup, authentication is disabled because my instance is already protected behind Cloudflare. If you do not use a similar layer, enabling authentication here is strongly recommended.<br>Finally, set <strong>Respond<\/strong> to <strong>\u201cUsing \u2018Respond to Webhook\u2019 Node\u201d<\/strong>. This ensures the workflow replies only after all processing steps are complete and the final answer has been generated.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"#lb-2-fed418c3\" class=\"lb-thumb\" aria-label=\"Bild vergr\u00f6\u00dfern\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"609\" src=\"https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-1-1024x609.png\" alt=\"\" class=\"wp-image-397\" srcset=\"https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-1-1024x609.png 1024w, https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-1-300x178.png 300w, https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-1-768x457.png 768w, https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-1-1536x914.png 1536w, https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-1.png 1866w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\"><\/a><\/figure>\n\n\n\n<p>Next comes the <strong>Edit Fields<\/strong> node. Its only job is to produce a <code>sessionId<\/code> that we\u2019ll need later for the <strong>Simple Memory<\/strong> node. Create the following two fields:<\/p>\n\n\n\n<p>First field:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Name:<\/strong> <code><code>body.chatInput<\/code><\/code><\/li>\n\n\n\n<li><strong>Type:<\/strong> String<\/li>\n\n\n\n<li><strong>Value:<\/strong> <code>{{ $json.body.chatInput }}<\/code><\/li>\n<\/ul>\n\n\n\n<p>Second field:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Name:<\/strong> <code><code><code>sessionId<\/code><\/code><\/code><\/li>\n\n\n\n<li><strong>Type:<\/strong> String<\/li>\n\n\n\n<li><strong>Value:<\/strong> <code><code>randomcode<\/code><\/code><\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"#lb-3-23e71c73\" class=\"lb-thumb\" aria-label=\"Bild vergr\u00f6\u00dfern\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"404\" src=\"https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-2-1024x404.png\" alt=\"\" class=\"wp-image-398\" srcset=\"https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-2-1024x404.png 1024w, https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-2-300x118.png 300w, https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-2-768x303.png 768w, https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-2-1536x606.png 1536w, https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-2.png 1865w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\"><\/a><\/figure>\n\n\n\n<p>For the <code>sessionId<\/code>, you can simply define any random string.<\/p>\n\n\n\n<p>After that, we reach the <strong>\u201cAI Agent\u201d<\/strong> node \u2014 the heart of the system.<br>Set the <strong>Prompt (User Message)<\/strong> to:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{{ $json.body.chatInput }}<\/code><\/pre>\n\n\n\n<p>This ensures the input from the webhook is correctly forwarded to the model.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"#lb-4-fa6be1cb\" class=\"lb-thumb\" aria-label=\"Bild vergr\u00f6\u00dfern\"><img loading=\"lazy\" decoding=\"async\" width=\"856\" height=\"612\" src=\"https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-11.png\" alt=\"\" class=\"wp-image-422\" srcset=\"https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-11.png 856w, https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-11-300x214.png 300w, https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-11-768x549.png 768w\" sizes=\"auto, (max-width: 856px) 100vw, 856px\"><\/a><\/figure>\n\n\n\n<p>I also like to define a <strong>System Message<\/strong> here. This message describes the agent\u2019s personality, its responsibilities, and any rules it should follow. You will likely refine this message many times as you improve your workflow. You can even ask your chosen AI model to help write or optimize it. It often knows best how to guide itself.<br>Example System Message:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>You operate under the identity \u201cRobot\u201d, a Senior Systems Engineer overseeing diagnostics, reporting, and general observability across a tri-node Hypervisor Cluster and two standalone Docker hosts.\nYour habits follow a classical operations mindset: inspect \u2192 document \u2192 summarize \u2192 request confirmation before touching anything.\n\nProfessional Style &amp; Approach\nAnalytical, steady, and rooted in traditional infrastructure practice\nPrefers established operational routines over improvisation\nCommunicates in a calm, precise tone, always addressing Giusi\nAlways explains the why behind recommendations\nAll initial actions must be non-intrusive and limited to safe inspection.\n\nHypervisor Environment \u2014 \u201cCoreCluster-01\u201d (3 Hypervisor Nodes)\n\nYour access is provided through a CoreCluster Tool, which exposes read-only hypervisor operations.\n\nPermitted API Queries (similar to pvesh)\nList available nodes\nRetrieve cluster state &amp; membership\nEnumerate all VMs and containers per node\nQuery LXC guests assigned to each host\n\nYou never modify or alter virtual machines unless Slayer explicitly confirms.\n\nMonitoring Duties\nSystem uptime, load averages, CPU &amp; RAM pressure\nPower states of guests (VMs &amp; LXCs)\nCluster membership, quorum status, heartbeat health\nReplication and scheduled job states (read-only)\nOperations That Require Direct Authorization\nStarting, stopping, or rebooting virtual guests\nRelocating or deleting workloads\nMaking any storage changes\n\nAny instruction that modifies hypervisor state\nYour rule: diagnose first, suggest second, act only when approved.\n\nContainer Hosts \u2014 Diagnostics Only\nYou reach the two Docker environments through SSH_MainHost and SSH_MediaHost.\n\nApproved Docker Inspection Commands\n\ndocker ps -a\ndocker logs &lt;container&gt;\ndocker stats\ndocker inspect &lt;container&gt;\ndocker exec -it &lt;container&gt; \/bin\/sh (observational only)\ndocker network ls\ndocker image ls\ndocker volume ls\n\nNever terminate or delete containers, networks, images, or volumes without permission.\n\nLinux Systems \u2014 General Read-Only Diagnostics\nSystem Indicators\n\nuptime\ntop or htop\nfree -h\ndf -h\ndu -sh &lt;path&gt;\njournalctl -p err\nsystemctl status &lt;service&gt;\ndmesg --level=err,warn\n\nNetworking Tools\n\nip address\nip route\nss -tulpen\nping &lt;host&gt;\ntraceroute &lt;host&gt;\ncurl -v &lt;url&gt;\n\nDisk &amp; Performance\n\nlsblk\nsmartctl -a \/dev\/&lt;disk&gt;\niostat -x 1\n\nCommunication Rules\n\nSpeak directly to Slayer\nPresent results in a structured operational report\n\nAvoid assumptions \u2014 rely on measurements, logs, and diagnostics\nAlways offer a reasoning chain before suggesting action\n\nNever initiate changes until Giusi explicitly approves<\/code><\/pre>\n\n\n\n<p>To make the AI Agent function correctly, configure both the <strong>\u201cChat Model\u201d<\/strong> and the <strong>\u201cSimple Memory<\/strong>\u201d node. Feel free to experiment with these. Tuning them to your specific use case can dramatically improve the agent\u2019s behavior.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"#lb-5-5d1ace4a\" class=\"lb-thumb\" aria-label=\"Bild vergr\u00f6\u00dfern\"><img loading=\"lazy\" decoding=\"async\" width=\"813\" height=\"524\" src=\"https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-13.png\" alt=\"\" class=\"wp-image-424\" srcset=\"https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-13.png 813w, https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-13-300x193.png 300w, https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-13-768x495.png 768w\" sizes=\"auto, (max-width: 813px) 100vw, 813px\"><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"#lb-6-1bb11c1f\" class=\"lb-thumb\" aria-label=\"Bild vergr\u00f6\u00dfern\"><img loading=\"lazy\" decoding=\"async\" width=\"821\" height=\"385\" src=\"https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-12.png\" alt=\"\" class=\"wp-image-423\" srcset=\"https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-12.png 821w, https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-12-300x141.png 300w, https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-12-768x360.png 768w\" sizes=\"auto, (max-width: 821px) 100vw, 821px\"><\/a><\/figure>\n\n\n\n<p>Finally, we arrive at the <strong>\u201cRespond to Webhook\u201d <\/strong>node. Here, simply set <strong>Respond with<\/strong> to <strong>First Incoming Item.<\/strong> This returns whatever the AI agent produced back to the Web-GUI.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"#lb-7-17c59050\" class=\"lb-thumb\" aria-label=\"Bild vergr\u00f6\u00dfern\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"441\" src=\"https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-6-1024x441.png\" alt=\"\" class=\"wp-image-402\" srcset=\"https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-6-1024x441.png 1024w, https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-6-300x129.png 300w, https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-6-768x330.png 768w, https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-6.png 1269w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\"><\/a><\/figure>\n\n\n\n<h6 class=\"wp-block-heading\">The tools<\/h6>\n\n\n\n<p>The more tools your agent can access, the more capable it becomes. In my setup, each tool is implemented as a <strong>\u201cCall n8n Workflow\u201d<\/strong> node. These nodes act as bridges to separate subworkflows, each responsible for a specific task.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"#lb-8-0c567977\" class=\"lb-thumb\" aria-label=\"Bild vergr\u00f6\u00dfern\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"738\" src=\"https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-8-1024x738.png\" alt=\"\" class=\"wp-image-405\" srcset=\"https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-8-1024x738.png 1024w, https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-8-300x216.png 300w, https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-8-768x554.png 768w, https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-8.png 1429w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\"><\/a><\/figure>\n\n\n\n<p>You can optionally add a description, but the key part is selecting the <strong>Subworkflow<\/strong> you want to trigger. Choose the target workflow from the dropdown. To ensure the agent can freely decide how to use this tool, set <strong>command<\/strong> to <strong>\u201cDefined automatically by the model.\u201d<\/strong> This allows the model to pass along whatever input it needs for the subworkflow.<\/p>\n\n\n\n<p>Each subworkflow is intentionally simple and consists of <strong>two nodes<\/strong>. The <strong>Execute Command<\/strong> and <strong>Start <\/strong>Node.<\/p>\n\n\n\n<p><strong>Start Node<\/strong><\/p>\n\n\n\n<p>In the Start node, define the <strong>Workflow Input Schema<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Name:<\/strong> <code>command<\/code><\/li>\n\n\n\n<li><strong>Type:<\/strong> String<\/li>\n<\/ul>\n\n\n\n<p>This field receives whatever the agent decides to send as the tool\u2019s instruction.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"#lb-9-98128f45\" class=\"lb-thumb\" aria-label=\"Bild vergr\u00f6\u00dfern\"><img loading=\"lazy\" decoding=\"async\" width=\"761\" height=\"635\" src=\"https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-9.png\" alt=\"\" class=\"wp-image-406\" srcset=\"https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-9.png 761w, https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-9-300x250.png 300w\" sizes=\"auto, (max-width: 761px) 100vw, 761px\"><\/a><\/figure>\n\n\n\n<p><strong>Execute Command Node<\/strong><\/p>\n\n\n\n<p>The second node executes the command on the destination system. Select the correct credentials for the target system Set <strong>Resource<\/strong> to: <code>Command<\/code>. Set <strong>Operation<\/strong> to: <code>Execute<\/code><\/p>\n\n\n\n<p>This injects the value passed from the Start node directly into the execution step. Set the <strong>Command<\/strong> field to:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{{ $json.command }}<\/code><\/pre>\n\n\n\n<p><strong>Working Directory<\/strong><\/p>\n\n\n\n<p>For the working directory, you have two options:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>\/<\/code> full access<\/li>\n\n\n\n<li><code>\/YOUR\/FOLDER\/PATH<\/code> a specific folder \/ directory<\/li>\n<\/ul>\n\n\n\n<p>Only use <code>\/<\/code> if the account or API permissions are safely limited. Granting full access to a user with unrestricted privileges is not recommended in most environments.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"#lb-10-69a28f6b\" class=\"lb-thumb\" aria-label=\"Bild vergr\u00f6\u00dfern\"><img loading=\"lazy\" decoding=\"async\" width=\"814\" height=\"413\" src=\"https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-14.png\" alt=\"\" class=\"wp-image-425\" srcset=\"https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-14.png 814w, https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-14-300x152.png 300w, https:\/\/techbygiusi.com\/wp-content\/uploads\/2025\/12\/image-14-768x390.png 768w\" sizes=\"auto, (max-width: 814px) 100vw, 814px\"><\/a><\/figure>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Over the past few weeks, I came across several YouTube videos showing how n8n can be used as a small but powerful helper inside a homelab environment. After watching a few of them, I couldn\u2019t resist the urge to build my own agent. Shout-out to @NetworkChuck What my agent already handles What I\u2019m currently working [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[15],"tags":[33,18,12,29],"class_list":["post-393","post","type-post","status-publish","format-standard","hentry","category-guide","tag-ai","tag-homelab","tag-linux","tag-n8n"],"_links":{"self":[{"href":"https:\/\/techbygiusi.com\/index.php\/wp-json\/wp\/v2\/posts\/393","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/techbygiusi.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/techbygiusi.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/techbygiusi.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/techbygiusi.com\/index.php\/wp-json\/wp\/v2\/comments?post=393"}],"version-history":[{"count":18,"href":"https:\/\/techbygiusi.com\/index.php\/wp-json\/wp\/v2\/posts\/393\/revisions"}],"predecessor-version":[{"id":426,"href":"https:\/\/techbygiusi.com\/index.php\/wp-json\/wp\/v2\/posts\/393\/revisions\/426"}],"wp:attachment":[{"href":"https:\/\/techbygiusi.com\/index.php\/wp-json\/wp\/v2\/media?parent=393"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/techbygiusi.com\/index.php\/wp-json\/wp\/v2\/categories?post=393"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/techbygiusi.com\/index.php\/wp-json\/wp\/v2\/tags?post=393"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}