Robin.te.Hofstee

Building an AI Agent Workflow in n8n

Robin te Hofstee9 min readViews5
Building an AI Agent Workflow in n8n

Learn how to build a fully automated AI content generation workflow in n8n, powered by a locally hosted Ollama model, triggered by a chat input and writing to a remote server via SSH.

Building an AI Agent Workflow in n8n

Let’s build a powerful, self-hosted AI content generation workflow using n8n. This workflow will take a user's input directly through a chat interface, feed it to a locally-running AI agent (powered by Ollama), have the agent generate content, and then write that content to a remote server using SSH. This setup isn’t just about automation; it’s a strategic pattern for repetitive creative or writing tasks – think drafting blog posts, generating marketing copy, or even brainstorming ideas. The beauty of this approach lies in its interactivity and control. You’re not relying on external APIs with potential rate limits or unpredictable behavior.

A chat-trigger-driven pipeline is particularly well-suited because it allows for real-time feedback and iteration. Unlike a simple webhook that passively receives data, the chat trigger allows you to directly refine the prompts and the generated content, creating a truly collaborative workflow. We’ll explore why this interactive control is so valuable, and how to build a robust, self-contained solution within n8n.

Setting Up the Chat Trigger Node

n8n’s Chat Trigger node is designed to handle interactive conversations directly within the n8n interface. This is different from standard webhooks or form triggers, which passively receive data. The Chat Trigger node provides you with the raw chat input as $json.chatInput, a structured JSON object containing the message, user ID, and other relevant conversation data. This allows you to not just receive the user's message, but to understand the context of the conversation and potentially use that context in subsequent steps.

For our use case, this is ideal. Imagine a scenario where the user provides a starting prompt, and the AI agent then asks clarifying questions – the Chat Trigger node captures those interactions as part of the conversation history.

Wiring Up the Ollama AI Agent

Now let's bring in the AI agent itself. We'll leverage Ollama, a fantastic open-source LLM platform that allows you to run models locally. The Ollama Chat Model sub-node sits under the AI Agent node and handles the communication with the model. We'll connect to it using the ai_languageModel connection type.

Here’s the breakdown:

  1. Create an Ollama Connection: In n8n, navigate to your credentials and create a new credential of type ‘Ollama’.
  2. Configure the Credential:
    • Name: Give it a descriptive name like "Ollama-Local-Model".
    • Base URL: This is the URL where Ollama is running. Typically, it's something like http://localhost:1234/.
    • Model Name: This is the name of the model you want to use. For example, "mistralai/Mistral-7B-Instruct-v0.2".
  3. Connect the Nodes: Drag the Chat Trigger node and the AI Agent node into your workflow. Connect the output of the Chat Trigger node to the input of the AI Agent node. Make sure the AI Agent node is configured to use the Ollama credential you just created.

The Trade-off: Local vs. Hosted

Running a model locally via Ollama provides significant advantages over relying on hosted APIs, especially for sensitive data and cost-conscious projects. Hosted APIs often involve subscription fees and potential rate limits. More importantly, running locally grants you complete privacy and eliminates any concerns about data being processed by a third-party server. However, there are downsides:

  • Slower Generation: Local models, especially on consumer hardware, will be slower than optimized hosted APIs.
  • Model Quality Ceiling: The quality of the output will be limited by the capabilities of the model itself and the resources available to it. You won’t have the benefit of continual model updates or access to the very largest models.

This isn’t necessarily a bad thing. For many creative writing tasks, the difference in quality might be subtle, and the cost/privacy benefits of a local setup outweigh the slight performance impact.

Crafting a Robust System Message

The system message (also known as the “prompt”) provided to the AI agent significantly impacts the quality and consistency of its output. A vague system message like “Write a blog post about artificial intelligence” will yield unpredictable results. A structured, detailed system message, on the other hand, guides the agent toward the desired output format, tone, and subject matter.

Before:

{
  "system": "Write a blog post about AI."
}

After:

{
  "system": "You are a knowledgeable and engaging technical writer. Your task is to write a blog post explaining the basics of artificial intelligence for a general audience. Keep the tone informative and approachable. The blog post should be approximately 500-700 words long and include a brief overview of different AI approaches, examples of AI applications, and a conclusion summarizing key takeaways. Use clear and concise language, avoiding jargon whenever possible.",
  "instructions": "Write a blog post about AI.  Please focus on the current state of large language models."
}

Notice the added detail: We’ve defined the agent's role, specified the target audience, provided a length constraint, and included specific content requirements. This level of detail dramatically improves the agent's output.

Post-Processing with the Code Node

Raw LLM output is rarely perfect. It might contain extraneous information, formatting inconsistencies, or even hallucinated details. The Code node provides a place to clean and refine the agent's output. We're not simply passing the raw text straight through; we're actively extracting the relevant information and rebuilding the output structure.

For example, let’s say the agent generates a block of text. We don’t want to blindly use that whole block. We need to specifically target the paragraph containing the main point, strip out any conversational filler, and format it correctly for our file.

JavaScript Example (Code Node):

// Assuming $json.chatInput.agentOutput is the raw JSON output from the AI Agent node
 
const output = $json.chatInput.agentOutput;
 
// Extract the main paragraph (simplified example - adjust based on the model's output)
const mainParagraph = output.substring(output.indexOf("AI"), output.indexOf("\n\n"));
 
// Return the cleaned paragraph
const cleanedOutput = {
    content: mainParagraph
};
$set($json.chatInput.agentOutput = cleanedOutput);
 

This demonstrates the fundamental principle: Don’t trust the model's raw output blindly. Extract precisely what you need and rebuild the structure from scratch.

SSH Integration for Remote File Writing

Now let’s get the content to a remote server. We'll use the SSH node to execute a shell command and write the content to a file.

  1. Create an SSH Credential: In n8n, create an SSH credential with the necessary connection details for your remote server.

  2. Connect the Nodes: Chain the Code node (with the output from the AI Agent) to the SSH node.

  3. Configure the SSH Node:

    • Command: echo "$json.chatInput.agentOutput.content" > /path/to/remote/file.txt
    • Explanation: This command uses echo to output the content (extracted from the agent’s response) and redirects it to a file on the remote server. The "$json.chatInput.agentOutput.content" part ensures that the JSON content is properly handled, preventing issues with special characters.

    Important: Base64 Encoding: To handle multi-line content safely within the SSH command, it's highly recommended to base64-encode the content before piping it through the command. This prevents escaping headaches caused by quotes, backticks, and code blocks. The Code node handles this encoding for you – ensure your settings are configured to use base64.

End-to-End Workflow and Resilience

To make the entire pipeline truly functional, chain a second SSH node to run a build or deploy step after the file is written to the remote server. This could be anything from triggering a CI/CD pipeline to restarting a service.

Finally, let’s consider resilience. The AI Agent's output might occasionally be invalid or incomplete. To prevent the workflow from failing silently, we should implement validation:

  • Validate Output: Use a Validate node to check that the agent's output contains the expected fields.
  • Handle Missing Fields: Use a Filter node to handle missing fields with sane fallbacks. Perhaps if the content field is missing, default to an empty string.
  • Never Trust the Model: Never rely on the model for things like the current date or time. Always compute these values in code.

By incorporating these resilience measures, you’ll build a significantly more robust and reliable workflow. Building an AI agent workflow in n8n can be a powerful combination, enabling rapid prototyping and automation of creative tasks.

Share this post
Robin te Hofstee

Written by Robin te Hofstee

Technology enthusiast with a deep love for programming. Sharing practical guides on React, Next.js, Linux and self-hosting.

Self-Hosting n8n on Proxmox

1

Deploying n8n on Proxmox using the Community Scripts LXC installer offers data privacy, unlimited execution, and full control compared to n8n Cloud, ideal for a homelab.