<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Muhammad Gharis</title>
    <description>The latest articles on DEV Community by Muhammad Gharis (@muhammad_gharis_fe079470a).</description>
    <link>https://dev.to/muhammad_gharis_fe079470a</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3972727%2F72333ae6-9d90-46a9-8f08-61572b66b3f8.jpg</url>
      <title>DEV Community: Muhammad Gharis</title>
      <link>https://dev.to/muhammad_gharis_fe079470a</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/muhammad_gharis_fe079470a"/>
    <language>en</language>
    <item>
      <title>The Single All-Purpose AI Agent Is the Wrong Architecture</title>
      <dc:creator>Muhammad Gharis</dc:creator>
      <pubDate>Sun, 28 Jun 2026 21:37:04 +0000</pubDate>
      <link>https://dev.to/muhammad_gharis_fe079470a/the-single-all-purpose-ai-agent-is-the-wrong-architecture-lp3</link>
      <guid>https://dev.to/muhammad_gharis_fe079470a/the-single-all-purpose-ai-agent-is-the-wrong-architecture-lp3</guid>
      <description>&lt;p&gt;Everyone is trying to build one AI agent that does everything.&lt;/p&gt;

&lt;p&gt;One agent to understand the request.&lt;/p&gt;

&lt;p&gt;One agent to query the database.&lt;/p&gt;

&lt;p&gt;One agent to validate the business rules.&lt;/p&gt;

&lt;p&gt;One agent to update the ERP.&lt;/p&gt;

&lt;p&gt;One agent to write the customer response.&lt;/p&gt;

&lt;p&gt;One agent to trigger the downstream workflow.&lt;/p&gt;

&lt;p&gt;That sounds convenient.&lt;/p&gt;

&lt;p&gt;It is also a weak architecture for serious business systems.&lt;/p&gt;

&lt;p&gt;The more responsibility you give to one AI agent, the harder it becomes to debug, validate, secure, and audit.&lt;/p&gt;

&lt;p&gt;In production environments, that matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem with one big agent
&lt;/h2&gt;

&lt;p&gt;A general-purpose AI agent is easy to demo.&lt;/p&gt;

&lt;p&gt;Give it access to tools.&lt;/p&gt;

&lt;p&gt;Let it reason.&lt;/p&gt;

&lt;p&gt;Let it call APIs.&lt;/p&gt;

&lt;p&gt;Let it decide what to do next.&lt;/p&gt;

&lt;p&gt;The demo looks impressive.&lt;/p&gt;

&lt;p&gt;But inside an enterprise system, the question is not only:&lt;/p&gt;

&lt;p&gt;Can the agent complete the task?&lt;/p&gt;

&lt;p&gt;The real questions are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which data was it allowed to access?&lt;/li&gt;
&lt;li&gt;Which business rules did it apply?&lt;/li&gt;
&lt;li&gt;What happens if it chooses the wrong tool?&lt;/li&gt;
&lt;li&gt;What happens if it formats the wrong API payload?&lt;/li&gt;
&lt;li&gt;Who reviews high-risk actions?&lt;/li&gt;
&lt;li&gt;Where is the audit trail?&lt;/li&gt;
&lt;li&gt;Can the failure be isolated?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When one agent owns everything, every failure becomes harder to trace.&lt;/p&gt;

&lt;p&gt;Was it a reasoning issue?&lt;/p&gt;

&lt;p&gt;Was it a data issue?&lt;/p&gt;

&lt;p&gt;Was it a validation issue?&lt;/p&gt;

&lt;p&gt;Was it a permission issue?&lt;/p&gt;

&lt;p&gt;Was it an execution issue?&lt;/p&gt;

&lt;p&gt;That is why a single all-purpose agent becomes risky as soon as it touches real systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  A better model: agent orchestration
&lt;/h2&gt;

&lt;p&gt;The better pattern is not one agent doing everything.&lt;/p&gt;

&lt;p&gt;The better pattern is agent orchestration.&lt;/p&gt;

&lt;p&gt;Instead of one large agent, you design smaller agents or services with limited responsibilities.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Database Query Agent
→ only reads from approved data sources

Validation Agent
→ checks business rules and required fields

Communication Agent
→ formats responses for customers or internal users

Execution Layer
→ performs deterministic API calls only after validation

Audit Layer
→ records every request, decision, and output
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each component has a clear role.&lt;/p&gt;

&lt;p&gt;Each component has boundaries.&lt;/p&gt;

&lt;p&gt;Each component can fail independently.&lt;/p&gt;

&lt;p&gt;That is much easier to control than a single agent with broad access.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why specialization matters
&lt;/h2&gt;

&lt;p&gt;A database query agent should not also decide whether a vendor payment is safe.&lt;/p&gt;

&lt;p&gt;A communication agent should not also update inventory.&lt;/p&gt;

&lt;p&gt;A validation agent should not also send customer messages.&lt;/p&gt;

&lt;p&gt;These responsibilities should be separated.&lt;/p&gt;

&lt;p&gt;That separation gives you several benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easier debugging&lt;/li&gt;
&lt;li&gt;Clear ownership&lt;/li&gt;
&lt;li&gt;Better security boundaries&lt;/li&gt;
&lt;li&gt;More predictable execution&lt;/li&gt;
&lt;li&gt;Cleaner audit trails&lt;/li&gt;
&lt;li&gt;More controlled failure handling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is how backend systems are normally designed.&lt;/p&gt;

&lt;p&gt;AI does not remove the need for architecture.&lt;/p&gt;

&lt;p&gt;It makes architecture more important.&lt;/p&gt;

&lt;h2&gt;
  
  
  The handoff is the real design problem
&lt;/h2&gt;

&lt;p&gt;The important part is not only the agent.&lt;/p&gt;

&lt;p&gt;The important part is the handoff.&lt;/p&gt;

&lt;p&gt;When one agent finishes its task, what exactly does it pass downstream?&lt;/p&gt;

&lt;p&gt;Is the output structured?&lt;/p&gt;

&lt;p&gt;Is it validated?&lt;/p&gt;

&lt;p&gt;Is confidence recorded?&lt;/p&gt;

&lt;p&gt;Is the source data attached?&lt;/p&gt;

&lt;p&gt;Is the next component allowed to act on it?&lt;/p&gt;

&lt;p&gt;Is human approval required?&lt;/p&gt;

&lt;p&gt;This is where many AI systems fail.&lt;/p&gt;

&lt;p&gt;They focus too much on the prompt and not enough on the boundary between steps.&lt;/p&gt;

&lt;p&gt;A strong AI workflow should define:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Input
→ allowed tools
→ expected output schema
→ validation rules
→ failure behavior
→ approval rules
→ audit logging
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without this, the system becomes difficult to trust.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: ERP workflow
&lt;/h2&gt;

&lt;p&gt;Imagine a user sends this request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Please increase inventory for SKU-1001 by 800 units in warehouse WH-01.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A single agent might parse the request and update the ERP.&lt;/p&gt;

&lt;p&gt;That is dangerous.&lt;/p&gt;

&lt;p&gt;A better workflow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request received
→ AI extracts structured intent
→ Validation checks required fields
→ Guardrails check quantity threshold
→ Human approval required because quantity is high
→ ERP update happens only after approval
→ Audit log records the full decision
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The AI is useful.&lt;/p&gt;

&lt;p&gt;But it is not acting alone.&lt;/p&gt;

&lt;p&gt;It is part of a controlled workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where MCP and A2A-style patterns fit
&lt;/h2&gt;

&lt;p&gt;Protocols and patterns around model context, tool access, and agent-to-agent communication are becoming important because they help define how AI systems interact with external tools and other services.&lt;/p&gt;

&lt;p&gt;But the protocol is not the full answer.&lt;/p&gt;

&lt;p&gt;The architecture still matters.&lt;/p&gt;

&lt;p&gt;You still need to decide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which agent owns which responsibility&lt;/li&gt;
&lt;li&gt;What data each agent can access&lt;/li&gt;
&lt;li&gt;Which actions require approval&lt;/li&gt;
&lt;li&gt;How failures are handled&lt;/li&gt;
&lt;li&gt;How audit logs are maintained&lt;/li&gt;
&lt;li&gt;How business rules are enforced&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The technology helps.&lt;/p&gt;

&lt;p&gt;The design still has to be intentional.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frameworks are not the moat
&lt;/h2&gt;

&lt;p&gt;Frameworks like LangGraph, CrewAI, and similar tools can help teams build agent workflows.&lt;/p&gt;

&lt;p&gt;But the framework is not the hard part.&lt;/p&gt;

&lt;p&gt;The hard part is decomposition.&lt;/p&gt;

&lt;p&gt;Where does one responsibility end?&lt;/p&gt;

&lt;p&gt;Where does another begin?&lt;/p&gt;

&lt;p&gt;Which step should be probabilistic?&lt;/p&gt;

&lt;p&gt;Which step must be deterministic?&lt;/p&gt;

&lt;p&gt;Which step requires human review?&lt;/p&gt;

&lt;p&gt;Which step should be blocked completely?&lt;/p&gt;

&lt;p&gt;These are architecture decisions.&lt;/p&gt;

&lt;p&gt;Not prompt engineering decisions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;The future of enterprise AI is not one chatbot controlling everything.&lt;/p&gt;

&lt;p&gt;It is smaller, controlled components working together.&lt;/p&gt;

&lt;p&gt;AI should reason.&lt;/p&gt;

&lt;p&gt;Validation should enforce rules.&lt;/p&gt;

&lt;p&gt;Execution should be deterministic.&lt;/p&gt;

&lt;p&gt;Approval should exist for high-risk actions.&lt;/p&gt;

&lt;p&gt;Audit logs should capture every meaningful step.&lt;/p&gt;

&lt;p&gt;That is the difference between an AI demo and an AI system that can be trusted near business-critical workflows.&lt;/p&gt;

&lt;p&gt;For Oracle, Odoo, ERP, and custom backend environments, this is the direction I believe matters most:&lt;/p&gt;

&lt;p&gt;Not bigger agents.&lt;/p&gt;

&lt;p&gt;Better handoffs.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>architecture</category>
      <category>backend</category>
    </item>
    <item>
      <title>AI Agents Should Not Touch Your ERP Directly. Build an Execution Layer Instead.</title>
      <dc:creator>Muhammad Gharis</dc:creator>
      <pubDate>Sun, 28 Jun 2026 21:31:05 +0000</pubDate>
      <link>https://dev.to/muhammad_gharis_fe079470a/ai-agents-should-not-touch-your-erp-directly-build-an-execution-layer-instead-2b62</link>
      <guid>https://dev.to/muhammad_gharis_fe079470a/ai-agents-should-not-touch-your-erp-directly-build-an-execution-layer-instead-2b62</guid>
      <description>&lt;h2&gt;
  
  
  tags: ai, n8n, fastapi, architecture
&lt;/h2&gt;

&lt;p&gt;Everyone is building AI agents right now.&lt;/p&gt;

&lt;p&gt;That is not the hard part anymore.&lt;/p&gt;

&lt;p&gt;Writing a Python script that calls an LLM is simple. You can connect an API, send a prompt, receive a response, and call it an agent.&lt;/p&gt;

&lt;p&gt;The real problem starts when that agent wants to do something useful inside a business system.&lt;/p&gt;

&lt;p&gt;Update inventory.&lt;/p&gt;

&lt;p&gt;Create a vendor payment.&lt;/p&gt;

&lt;p&gt;Change a CRM record.&lt;/p&gt;

&lt;p&gt;Post a transaction.&lt;/p&gt;

&lt;p&gt;Trigger a customer notification.&lt;/p&gt;

&lt;p&gt;Touch an ERP database.&lt;/p&gt;

&lt;p&gt;That is where many AI agent demos become dangerous.&lt;/p&gt;

&lt;p&gt;Because a raw LLM is probabilistic.&lt;/p&gt;

&lt;p&gt;Enterprise execution needs control.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Most AI agent examples look clean in a demo.&lt;/p&gt;

&lt;p&gt;A user asks something.&lt;/p&gt;

&lt;p&gt;The agent understands it.&lt;/p&gt;

&lt;p&gt;The agent calls a tool.&lt;/p&gt;

&lt;p&gt;The system updates something.&lt;/p&gt;

&lt;p&gt;Done.&lt;/p&gt;

&lt;p&gt;But in a real ERP or backend environment, that is not enough.&lt;/p&gt;

&lt;p&gt;Before an AI-generated action reaches a production system, you need answers to basic questions:&lt;/p&gt;

&lt;p&gt;Who approved this action?&lt;/p&gt;

&lt;p&gt;Was the payload validated?&lt;/p&gt;

&lt;p&gt;Was the user allowed to perform this operation?&lt;/p&gt;

&lt;p&gt;Was the vendor active?&lt;/p&gt;

&lt;p&gt;Was the amount above the approval threshold?&lt;/p&gt;

&lt;p&gt;Was the inventory update within allowed limits?&lt;/p&gt;

&lt;p&gt;Was the final API request deterministic?&lt;/p&gt;

&lt;p&gt;Was every step logged?&lt;/p&gt;

&lt;p&gt;Who owns the failure if the action is wrong?&lt;/p&gt;

&lt;p&gt;This is the gap between an AI experiment and an AI-enabled business workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why direct AI-to-ERP execution is risky
&lt;/h2&gt;

&lt;p&gt;An AI agent should not directly write into an ERP system.&lt;/p&gt;

&lt;p&gt;Not because AI is useless.&lt;/p&gt;

&lt;p&gt;Because ERP systems contain business-critical data.&lt;/p&gt;

&lt;p&gt;They contain customers, invoices, vendors, payments, inventory, payroll, approvals, and financial records.&lt;/p&gt;

&lt;p&gt;If an AI agent sends the wrong payload, chooses the wrong record, or skips a business rule, the damage is not theoretical.&lt;/p&gt;

&lt;p&gt;It can affect reporting, operations, finance, compliance, and customer trust.&lt;/p&gt;

&lt;p&gt;That is why I do not like the pattern where an LLM directly controls execution.&lt;/p&gt;

&lt;p&gt;The LLM should help with reasoning.&lt;/p&gt;

&lt;p&gt;It should extract intent.&lt;/p&gt;

&lt;p&gt;It should summarize context.&lt;/p&gt;

&lt;p&gt;It should classify requests.&lt;/p&gt;

&lt;p&gt;It should draft responses.&lt;/p&gt;

&lt;p&gt;But execution should be handled by deterministic systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  A better pattern: AI execution layer
&lt;/h2&gt;

&lt;p&gt;The safer architecture is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Webhook request
→ AI extraction
→ Schema validation
→ Guardrail decision
→ Human approval if needed
→ ERP/API execution
→ Audit log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This separates reasoning from execution.&lt;/p&gt;

&lt;p&gt;The AI does not directly update the ERP.&lt;/p&gt;

&lt;p&gt;Instead, it produces structured output.&lt;/p&gt;

&lt;p&gt;That output is validated.&lt;/p&gt;

&lt;p&gt;Then business rules decide whether the action is allowed, blocked, or requires human approval.&lt;/p&gt;

&lt;p&gt;Only after that does the workflow call the ERP or backend API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where low-code orchestration helps
&lt;/h2&gt;

&lt;p&gt;This is where tools like n8n become useful.&lt;/p&gt;

&lt;p&gt;Not because low-code replaces backend engineering.&lt;/p&gt;

&lt;p&gt;It does not.&lt;/p&gt;

&lt;p&gt;You still need Python, FastAPI, Django, APIs, validation models, databases, and proper infrastructure.&lt;/p&gt;

&lt;p&gt;But low-code orchestration gives you a visible execution layer.&lt;/p&gt;

&lt;p&gt;You can see the workflow.&lt;/p&gt;

&lt;p&gt;You can see routing logic.&lt;/p&gt;

&lt;p&gt;You can add approval checkpoints.&lt;/p&gt;

&lt;p&gt;You can separate AI reasoning from API execution.&lt;/p&gt;

&lt;p&gt;You can log every decision.&lt;/p&gt;

&lt;p&gt;You can make the process easier for business and technical teams to review.&lt;/p&gt;

&lt;p&gt;That visibility matters when AI starts touching real systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example architecture
&lt;/h2&gt;

&lt;p&gt;A practical setup could look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;n8n Webhook
    ↓
FastAPI AI Extraction Service
    ↓
Pydantic Schema Validation
    ↓
Guardrail Evaluation
    ↓
Decision:
    - Allow
    - Require Approval
    - Block
    ↓
Mock ERP / Real ERP API
    ↓
Audit Log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this architecture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FastAPI handles the backend service layer.&lt;/li&gt;
&lt;li&gt;Pydantic enforces strict schemas.&lt;/li&gt;
&lt;li&gt;n8n handles orchestration and approval routing.&lt;/li&gt;
&lt;li&gt;The ERP API only receives validated requests.&lt;/li&gt;
&lt;li&gt;Every decision is logged.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The AI is useful, but it is not trusted blindly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo scenario
&lt;/h2&gt;

&lt;p&gt;I created a small demo concept around two common ERP-style workflows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Low-risk inventory update&lt;/li&gt;
&lt;li&gt;High-risk vendor payment&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The inventory update can proceed if it passes validation and stays within allowed limits.&lt;/p&gt;

&lt;p&gt;The vendor payment requires human approval if the amount crosses a defined threshold.&lt;/p&gt;

&lt;p&gt;Invalid or incomplete requests are blocked before they reach the ERP layer.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"request_text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Increase inventory for item SKU-1001 by 25 units in warehouse WH-01"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"webhook"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"requested_by"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"operations_user"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The AI extraction service converts this into structured intent.&lt;/p&gt;

&lt;p&gt;Then validation checks the required fields.&lt;/p&gt;

&lt;p&gt;Then guardrails decide whether the action can continue.&lt;/p&gt;

&lt;p&gt;Only then does the mock ERP endpoint receive the request.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the guardrails check
&lt;/h2&gt;

&lt;p&gt;Some simple example rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vendor payment above 10,000 requires approval.&lt;/li&gt;
&lt;li&gt;Missing vendor ID fails validation.&lt;/li&gt;
&lt;li&gt;Inventory update above 500 units requires approval.&lt;/li&gt;
&lt;li&gt;Unknown action type is blocked.&lt;/li&gt;
&lt;li&gt;Low confidence AI extraction requires human review.&lt;/li&gt;
&lt;li&gt;Payment to inactive vendor is blocked.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These rules are not complex.&lt;/p&gt;

&lt;p&gt;That is the point.&lt;/p&gt;

&lt;p&gt;The execution layer should be predictable.&lt;/p&gt;

&lt;p&gt;The LLM should not be responsible for deciding every business rule at runtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why audit logs matter
&lt;/h2&gt;

&lt;p&gt;If AI is involved in business execution, audit logs are not optional.&lt;/p&gt;

&lt;p&gt;You need to know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What request came in&lt;/li&gt;
&lt;li&gt;What the AI extracted&lt;/li&gt;
&lt;li&gt;What validation returned&lt;/li&gt;
&lt;li&gt;Which guardrail decision was made&lt;/li&gt;
&lt;li&gt;Whether approval was required&lt;/li&gt;
&lt;li&gt;Who approved it&lt;/li&gt;
&lt;li&gt;What ERP action was executed&lt;/li&gt;
&lt;li&gt;What response came back&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without this, you do not have an AI workflow.&lt;/p&gt;

&lt;p&gt;You have an invisible automation risk.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this demo is not
&lt;/h2&gt;

&lt;p&gt;This is not a production ERP connector.&lt;/p&gt;

&lt;p&gt;It does not claim to solve compliance by itself.&lt;/p&gt;

&lt;p&gt;It does not replace authentication, RBAC, rate limits, secret management, monitoring, or proper security review.&lt;/p&gt;

&lt;p&gt;Self-hosting also does not automatically make a system compliant.&lt;/p&gt;

&lt;p&gt;Compliance depends on implementation, hosting, contracts, access control, logging, data handling, and internal policy.&lt;/p&gt;

&lt;p&gt;The goal of the demo is simpler:&lt;/p&gt;

&lt;p&gt;Show the architecture pattern.&lt;/p&gt;

&lt;p&gt;AI for reasoning.&lt;/p&gt;

&lt;p&gt;Deterministic systems for execution.&lt;/p&gt;

&lt;p&gt;Orchestration for visibility.&lt;/p&gt;

&lt;p&gt;Approval for high-risk actions.&lt;/p&gt;

&lt;p&gt;Audit logs for accountability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters for ERP systems
&lt;/h2&gt;

&lt;p&gt;This pattern applies well to environments like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Odoo&lt;/li&gt;
&lt;li&gt;Oracle&lt;/li&gt;
&lt;li&gt;Django/FastAPI business systems&lt;/li&gt;
&lt;li&gt;Internal admin portals&lt;/li&gt;
&lt;li&gt;Finance workflows&lt;/li&gt;
&lt;li&gt;Inventory workflows&lt;/li&gt;
&lt;li&gt;CRM automation&lt;/li&gt;
&lt;li&gt;Support ticket routing&lt;/li&gt;
&lt;li&gt;Vendor and invoice processing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The more critical the system, the more important the handoff design becomes.&lt;/p&gt;

&lt;p&gt;The main question is not:&lt;/p&gt;

&lt;p&gt;Which LLM should we use?&lt;/p&gt;

&lt;p&gt;The better question is:&lt;/p&gt;

&lt;p&gt;Where does the AI stop, and where does controlled execution begin?&lt;/p&gt;

&lt;h2&gt;
  
  
  GitHub demo
&lt;/h2&gt;

&lt;p&gt;I am preparing a small reference repo for this pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://github.com/gharisj3/ai-agent-execution-layer-demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The repo structure includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FastAPI backend&lt;/li&gt;
&lt;li&gt;Mock ERP endpoints&lt;/li&gt;
&lt;li&gt;Pydantic validation&lt;/li&gt;
&lt;li&gt;Guardrail rules&lt;/li&gt;
&lt;li&gt;Audit log storage&lt;/li&gt;
&lt;li&gt;n8n workflow export&lt;/li&gt;
&lt;li&gt;Sample payloads&lt;/li&gt;
&lt;li&gt;Demo script&lt;/li&gt;
&lt;li&gt;Security notes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The demo flow is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Webhook request → AI extraction → schema validation → guardrail decision → human approval if needed → mock ERP execution → audit log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;AI agents will become more useful inside business systems.&lt;/p&gt;

&lt;p&gt;But they should not be allowed to operate like invisible admin users.&lt;/p&gt;

&lt;p&gt;The future is not one chatbot controlling everything.&lt;/p&gt;

&lt;p&gt;The better direction is controlled execution layers, clear permissions, validation rules, approval checkpoints, and audit trails.&lt;/p&gt;

&lt;p&gt;That is where AI becomes useful for real operations.&lt;/p&gt;

&lt;p&gt;Not because it can generate text.&lt;/p&gt;

&lt;p&gt;Because it can support business workflows without bypassing the controls those workflows require.&lt;/p&gt;

&lt;p&gt;If you are exploring this pattern for Odoo, Oracle, Django/FastAPI backends, or n8n-based automation, I am happy to discuss how it can be adapted to your environment.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>fastapi</category>
      <category>n8nbrightdatachallenge</category>
      <category>architecture</category>
    </item>
    <item>
      <title>I Built a WhatsApp Native Helpdesk for Odoo Community</title>
      <dc:creator>Muhammad Gharis</dc:creator>
      <pubDate>Mon, 22 Jun 2026 22:50:14 +0000</pubDate>
      <link>https://dev.to/muhammad_gharis_fe079470a/i-built-a-whatsapp-native-helpdesk-for-odoo-community-4lg</link>
      <guid>https://dev.to/muhammad_gharis_fe079470a/i-built-a-whatsapp-native-helpdesk-for-odoo-community-4lg</guid>
      <description>&lt;h1&gt;
  
  
  I Built a WhatsApp Native Helpdesk for Odoo Community
&lt;/h1&gt;

&lt;p&gt;Most customer support systems still assume that customers want to open tickets by email.&lt;/p&gt;

&lt;p&gt;But in many markets, that is not how support actually happens.&lt;/p&gt;

&lt;p&gt;In Pakistan, MENA, South Asia, Africa, and many WhatsApp-first regions, customers usually do not start with a support portal or email thread.&lt;/p&gt;

&lt;p&gt;They send a WhatsApp message.&lt;/p&gt;

&lt;p&gt;That message becomes the real support request.&lt;/p&gt;

&lt;p&gt;The problem is that Odoo Community does not provide a complete WhatsApp-native helpdesk workflow out of the box.&lt;/p&gt;

&lt;p&gt;So I built an open-source module:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WhatsApp Native Helpdesk for Odoo Community&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;GitHub repo:&lt;br&gt;
&lt;a href="https://github.com/gharisj3/odoo-whatsapp-native-helpdesk" rel="noopener noreferrer"&gt;https://github.com/gharisj3/odoo-whatsapp-native-helpdesk&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Many small and mid-sized businesses already use Odoo Community for CRM, sales, accounting, inventory, and operations.&lt;/p&gt;

&lt;p&gt;But customer support often lives outside Odoo.&lt;/p&gt;

&lt;p&gt;Support messages are scattered across:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;WhatsApp chats&lt;/li&gt;
&lt;li&gt;Agent phones&lt;/li&gt;
&lt;li&gt;Manual spreadsheets&lt;/li&gt;
&lt;li&gt;Email screenshots&lt;/li&gt;
&lt;li&gt;Internal notes&lt;/li&gt;
&lt;li&gt;Verbal follow-ups&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This creates a few serious problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No central ticket history&lt;/li&gt;
&lt;li&gt;No ownership&lt;/li&gt;
&lt;li&gt;No SLA visibility&lt;/li&gt;
&lt;li&gt;No escalation process&lt;/li&gt;
&lt;li&gt;No clean audit trail&lt;/li&gt;
&lt;li&gt;No connection between support and business records&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For WhatsApp-first businesses, the support channel is already clear.&lt;/p&gt;

&lt;p&gt;The missing piece is bringing that workflow into Odoo Community.&lt;/p&gt;


&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I built a WhatsApp-native support desk module for Odoo Community.&lt;/p&gt;

&lt;p&gt;The module allows businesses to receive WhatsApp customer messages, create or update support tickets in Odoo, assign tickets to agents, track status and SLA, and reply back to the customer through WhatsApp using n8n as the automation layer.&lt;/p&gt;

&lt;p&gt;The core flow is simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Customer WhatsApp Message
        ↓
Meta WhatsApp Cloud API
        ↓
n8n Workflow
        ↓
Odoo Webhook
        ↓
Odoo Support Ticket
        ↓
Agent Reply from Odoo
        ↓
n8n Workflow
        ↓
WhatsApp Reply to Customer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The goal was not to build a chatbot.&lt;/p&gt;

&lt;p&gt;The goal was to build real support ticketing around the communication channel customers already use.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why n8n Is Used
&lt;/h2&gt;

&lt;p&gt;I used n8n as the integration layer because it keeps the WhatsApp API handling separate from Odoo.&lt;/p&gt;

&lt;p&gt;That means Odoo does not need to store Meta WhatsApp access tokens directly.&lt;/p&gt;

&lt;p&gt;n8n handles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;WhatsApp webhook receiving&lt;/li&gt;
&lt;li&gt;Payload normalization&lt;/li&gt;
&lt;li&gt;WhatsApp Cloud API calls&lt;/li&gt;
&lt;li&gt;Status update routing&lt;/li&gt;
&lt;li&gt;Future automation workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Odoo handles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ticket creation&lt;/li&gt;
&lt;li&gt;Customer mapping&lt;/li&gt;
&lt;li&gt;Agent assignment&lt;/li&gt;
&lt;li&gt;Message history&lt;/li&gt;
&lt;li&gt;SLA tracking&lt;/li&gt;
&lt;li&gt;Status management&lt;/li&gt;
&lt;li&gt;Internal support workflow&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This separation makes the system easier to extend later.&lt;/p&gt;

&lt;p&gt;For example, the same pattern can be reused for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CRM enrichment&lt;/li&gt;
&lt;li&gt;Invoice follow-ups&lt;/li&gt;
&lt;li&gt;Order status updates&lt;/li&gt;
&lt;li&gt;POS support&lt;/li&gt;
&lt;li&gt;Vendor workflows&lt;/li&gt;
&lt;li&gt;AI-assisted reply suggestions&lt;/li&gt;
&lt;li&gt;Customer satisfaction surveys&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;p&gt;The current version includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;WhatsApp-to-ticket creation&lt;/li&gt;
&lt;li&gt;Existing ticket update when the same customer replies&lt;/li&gt;
&lt;li&gt;Partner auto-mapping by phone number or WhatsApp ID&lt;/li&gt;
&lt;li&gt;Agent reply from inside Odoo&lt;/li&gt;
&lt;li&gt;Outbound WhatsApp message flow through n8n&lt;/li&gt;
&lt;li&gt;Message deduplication using WhatsApp message ID&lt;/li&gt;
&lt;li&gt;Ticket stages&lt;/li&gt;
&lt;li&gt;Team assignment&lt;/li&gt;
&lt;li&gt;Priority tracking&lt;/li&gt;
&lt;li&gt;SLA tracking&lt;/li&gt;
&lt;li&gt;First response tracking&lt;/li&gt;
&lt;li&gt;Failed message handling&lt;/li&gt;
&lt;li&gt;Retry action for failed outbound messages&lt;/li&gt;
&lt;li&gt;Message status sync&lt;/li&gt;
&lt;li&gt;Dashboard views&lt;/li&gt;
&lt;li&gt;Docker-based local setup&lt;/li&gt;
&lt;li&gt;Importable n8n workflow examples&lt;/li&gt;
&lt;li&gt;Postman API collection&lt;/li&gt;
&lt;li&gt;Security groups and access rules&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Ticket Lifecycle
&lt;/h2&gt;

&lt;p&gt;A normal support flow looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A customer sends a WhatsApp message.&lt;/li&gt;
&lt;li&gt;n8n receives the webhook from Meta WhatsApp Cloud API.&lt;/li&gt;
&lt;li&gt;n8n normalizes the payload.&lt;/li&gt;
&lt;li&gt;Odoo receives the payload through a secure webhook endpoint.&lt;/li&gt;
&lt;li&gt;Odoo checks whether the customer already exists.&lt;/li&gt;
&lt;li&gt;If the customer does not exist, Odoo creates a partner.&lt;/li&gt;
&lt;li&gt;Odoo checks whether there is an open ticket for that customer.&lt;/li&gt;
&lt;li&gt;If an open ticket exists, the message is added to the same ticket.&lt;/li&gt;
&lt;li&gt;If no open ticket exists, a new ticket is created.&lt;/li&gt;
&lt;li&gt;The support agent replies from Odoo.&lt;/li&gt;
&lt;li&gt;n8n sends the reply through WhatsApp Cloud API.&lt;/li&gt;
&lt;li&gt;Odoo stores the outbound message and delivery status.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This keeps the full conversation history inside Odoo.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;For businesses that rely on WhatsApp, this kind of workflow can reduce a lot of operational friction.&lt;/p&gt;

&lt;p&gt;Instead of support being managed inside individual chat threads, it becomes structured.&lt;/p&gt;

&lt;p&gt;Agents can see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Who owns the issue&lt;/li&gt;
&lt;li&gt;What the latest message was&lt;/li&gt;
&lt;li&gt;Whether the SLA is at risk&lt;/li&gt;
&lt;li&gt;Which stage the ticket is in&lt;/li&gt;
&lt;li&gt;Whether a reply failed&lt;/li&gt;
&lt;li&gt;Whether the issue was resolved&lt;/li&gt;
&lt;li&gt;Which customer record the issue belongs to&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is a big improvement over scattered WhatsApp conversations.&lt;/p&gt;




&lt;h2&gt;
  
  
  Repository Structure
&lt;/h2&gt;

&lt;p&gt;The repository is organized as a real Odoo addon project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;odoo-whatsapp-native-helpdesk/
├── addons/
│   └── whatsapp_helpdesk/
├── n8n/
│   └── workflows/
├── docs/
├── postman/
├── scripts/
├── docker-compose.yml
├── Dockerfile
├── .env.example
└── README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Odoo source code is not committed into the repository.&lt;/p&gt;

&lt;p&gt;The project includes bootstrap scripts and Docker setup so Odoo Community can be cloned and run locally during development.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tech Stack
&lt;/h2&gt;

&lt;p&gt;The project uses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Odoo Community&lt;/li&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;li&gt;PostgreSQL&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;n8n&lt;/li&gt;
&lt;li&gt;Meta WhatsApp Cloud API&lt;/li&gt;
&lt;li&gt;REST webhooks&lt;/li&gt;
&lt;li&gt;XML views and security rules&lt;/li&gt;
&lt;li&gt;Postman for API testing&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Local Setup
&lt;/h2&gt;

&lt;p&gt;Clone the repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/gharisj3/odoo-whatsapp-native-helpdesk.git
&lt;span class="nb"&gt;cd &lt;/span&gt;odoo-whatsapp-native-helpdesk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy the environment file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; .env.example .env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make scripts executable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x scripts/&lt;span class="k"&gt;*&lt;/span&gt;.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bootstrap Odoo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./scripts/bootstrap_odoo.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start the services:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then open:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Odoo: http://localhost:8069
n8n:   http://localhost:5678
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Odoo Installation Flow
&lt;/h2&gt;

&lt;p&gt;After Odoo is running:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a new database.&lt;/li&gt;
&lt;li&gt;Activate developer mode.&lt;/li&gt;
&lt;li&gt;Update the Apps List.&lt;/li&gt;
&lt;li&gt;Search for &lt;code&gt;WhatsApp Helpdesk&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Install the module.&lt;/li&gt;
&lt;li&gt;Configure the WhatsApp Helpdesk channel.&lt;/li&gt;
&lt;li&gt;Import the n8n workflows.&lt;/li&gt;
&lt;li&gt;Test inbound and outbound flows.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  n8n Workflow Layer
&lt;/h2&gt;

&lt;p&gt;The project includes example n8n workflows for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inbound WhatsApp message to Odoo ticket&lt;/li&gt;
&lt;li&gt;Odoo agent reply to WhatsApp&lt;/li&gt;
&lt;li&gt;WhatsApp status update sync&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The workflows are designed as starting points.&lt;/p&gt;

&lt;p&gt;You still need to configure your own:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Meta WhatsApp Cloud API credentials&lt;/li&gt;
&lt;li&gt;WhatsApp phone number ID&lt;/li&gt;
&lt;li&gt;Odoo base URL&lt;/li&gt;
&lt;li&gt;Shared secret&lt;/li&gt;
&lt;li&gt;Production webhook URLs&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Security Design
&lt;/h2&gt;

&lt;p&gt;A few security choices were intentional:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Meta access tokens are not stored in Odoo.&lt;/li&gt;
&lt;li&gt;WhatsApp API calls are handled by n8n.&lt;/li&gt;
&lt;li&gt;Webhook endpoints validate a shared secret.&lt;/li&gt;
&lt;li&gt;Real credentials are excluded from the repository.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.env.example&lt;/code&gt; uses placeholder values only.&lt;/li&gt;
&lt;li&gt;Failed outbound messages are logged without exposing credentials.&lt;/li&gt;
&lt;li&gt;Internal notes are not sent to customers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For production, the setup should run behind HTTPS with proper reverse proxy configuration, strong passwords, and protected Odoo/n8n access.&lt;/p&gt;




&lt;h2&gt;
  
  
  Legal and Compliance Notes
&lt;/h2&gt;

&lt;p&gt;This is an independent open-source project.&lt;/p&gt;

&lt;p&gt;It is not an official Odoo, Meta, WhatsApp, or n8n product.&lt;/p&gt;

&lt;p&gt;It is not certified, endorsed, or sponsored by those companies.&lt;/p&gt;

&lt;p&gt;The names Odoo, WhatsApp, Meta, and n8n are used only to describe integration compatibility and the technologies involved.&lt;/p&gt;

&lt;p&gt;Production usage requires a valid Meta WhatsApp Cloud API setup and compliance with applicable WhatsApp Business Platform rules, messaging policies, customer consent requirements, and local laws.&lt;/p&gt;

&lt;p&gt;This project does not bypass WhatsApp Business Platform rules.&lt;/p&gt;

&lt;p&gt;Businesses are responsible for using approved templates where required and for following customer messaging policies.&lt;/p&gt;




&lt;h2&gt;
  
  
  Current Limitations
&lt;/h2&gt;

&lt;p&gt;The current release focuses on the core support workflow.&lt;/p&gt;

&lt;p&gt;Some items are planned for future versions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Media attachment handling&lt;/li&gt;
&lt;li&gt;WhatsApp template message support&lt;/li&gt;
&lt;li&gt;Multi-number routing&lt;/li&gt;
&lt;li&gt;Customer satisfaction survey&lt;/li&gt;
&lt;li&gt;AI-assisted reply suggestions&lt;/li&gt;
&lt;li&gt;Auto-priority classification&lt;/li&gt;
&lt;li&gt;Working-hours SLA calendar&lt;/li&gt;
&lt;li&gt;CRM and sales order linking&lt;/li&gt;
&lt;li&gt;Shopify or WooCommerce lookup through n8n&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why I Built This
&lt;/h2&gt;

&lt;p&gt;I work around ERP, Odoo, backend systems, and automation workflows.&lt;/p&gt;

&lt;p&gt;I kept seeing the same gap:&lt;/p&gt;

&lt;p&gt;Businesses were running operations in Odoo, but support conversations were happening somewhere else.&lt;/p&gt;

&lt;p&gt;For WhatsApp-first markets, that gap matters.&lt;/p&gt;

&lt;p&gt;This project is my attempt to make that support flow more structured, traceable, and automation-ready while still keeping it open-source friendly.&lt;/p&gt;




&lt;h2&gt;
  
  
  GitHub Repository
&lt;/h2&gt;

&lt;p&gt;You can check the project here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/gharisj3/odoo-whatsapp-native-helpdesk" rel="noopener noreferrer"&gt;https://github.com/gharisj3/odoo-whatsapp-native-helpdesk&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  More From Me
&lt;/h2&gt;

&lt;p&gt;LinkedIn:&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/muhammad-gharis-javed-318266202/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/muhammad-gharis-javed-318266202/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fiverr:&lt;br&gt;
&lt;a href="https://www.fiverr.com/muhammadghar709" rel="noopener noreferrer"&gt;https://www.fiverr.com/muhammadghar709&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Digital products and templates:&lt;br&gt;
&lt;a href="https://omniacademy.gumroad.com/" rel="noopener noreferrer"&gt;https://omniacademy.gumroad.com/&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;WhatsApp is not just a chat app for many businesses.&lt;/p&gt;

&lt;p&gt;It is where support starts.&lt;/p&gt;

&lt;p&gt;The next step is making those conversations structured enough to manage, assign, track, and improve.&lt;/p&gt;

&lt;p&gt;That is what this project is built for.&lt;/p&gt;

</description>
      <category>odoo</category>
      <category>n8nbrightdatachallenge</category>
      <category>opensource</category>
      <category>automation</category>
    </item>
    <item>
      <title>Why ERP Go-Live Fails Without a Command Center</title>
      <dc:creator>Muhammad Gharis</dc:creator>
      <pubDate>Sun, 14 Jun 2026 08:05:00 +0000</pubDate>
      <link>https://dev.to/muhammad_gharis_fe079470a/why-erp-go-live-fails-without-a-command-center-4056</link>
      <guid>https://dev.to/muhammad_gharis_fe079470a/why-erp-go-live-fails-without-a-command-center-4056</guid>
      <description>&lt;p&gt;ERP implementation does not usually fail because of one big issue.&lt;/p&gt;

&lt;p&gt;It usually fails because many small issues are not tracked properly.&lt;/p&gt;

&lt;p&gt;During go-live, teams are dealing with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;open issues&lt;/li&gt;
&lt;li&gt;UAT feedback&lt;/li&gt;
&lt;li&gt;user sign-offs&lt;/li&gt;
&lt;li&gt;cutover activities&lt;/li&gt;
&lt;li&gt;data migration tasks&lt;/li&gt;
&lt;li&gt;access rights checks&lt;/li&gt;
&lt;li&gt;business confirmations&lt;/li&gt;
&lt;li&gt;pending reports&lt;/li&gt;
&lt;li&gt;integration readiness&lt;/li&gt;
&lt;li&gt;support responsibilities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If these items are not clearly tracked, the go-live phase becomes stressful very quickly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem with ERP go-live
&lt;/h2&gt;

&lt;p&gt;A go-live phase needs discipline.&lt;/p&gt;

&lt;p&gt;Without a structured tracker, teams may struggle with questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which issues are still open?&lt;/li&gt;
&lt;li&gt;Who owns each action item?&lt;/li&gt;
&lt;li&gt;Has UAT been signed off?&lt;/li&gt;
&lt;li&gt;Which reports are pending?&lt;/li&gt;
&lt;li&gt;Are integrations ready?&lt;/li&gt;
&lt;li&gt;Is the cutover plan approved?&lt;/li&gt;
&lt;li&gt;Which tasks are critical before go-live?&lt;/li&gt;
&lt;li&gt;Who confirmed the final business readiness?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For systems like Odoo ERP, even a small missed configuration, access rule, or data issue can create operational problems after launch.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a command center should include
&lt;/h2&gt;

&lt;p&gt;A simple ERP go-live command center should include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;go-live checklist&lt;/li&gt;
&lt;li&gt;cutover plan&lt;/li&gt;
&lt;li&gt;UAT issue tracker&lt;/li&gt;
&lt;li&gt;sign-off tracker&lt;/li&gt;
&lt;li&gt;open issues log&lt;/li&gt;
&lt;li&gt;responsible owner column&lt;/li&gt;
&lt;li&gt;priority and status fields&lt;/li&gt;
&lt;li&gt;final readiness review&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This gives the implementation team and business stakeholders one place to track readiness.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;I created an &lt;strong&gt;Odoo ERP Go-Live Command Center Pack&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It is designed for consultants, implementation teams, ERP users, and small businesses preparing for an Odoo go-live.&lt;/p&gt;

&lt;p&gt;The pack includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;go-live checklist&lt;/li&gt;
&lt;li&gt;cutover planning template&lt;/li&gt;
&lt;li&gt;UAT issue tracker&lt;/li&gt;
&lt;li&gt;sign-off templates&lt;/li&gt;
&lt;li&gt;open issue tracking structure&lt;/li&gt;
&lt;li&gt;readiness documentation format&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is to reduce confusion during go-live and give teams a simple structure to manage the final stage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who this is useful for
&lt;/h2&gt;

&lt;p&gt;This can help:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Odoo consultants&lt;/li&gt;
&lt;li&gt;ERP implementation teams&lt;/li&gt;
&lt;li&gt;business users&lt;/li&gt;
&lt;li&gt;project managers&lt;/li&gt;
&lt;li&gt;SMEs going live with ERP&lt;/li&gt;
&lt;li&gt;support teams&lt;/li&gt;
&lt;li&gt;functional consultants&lt;/li&gt;
&lt;li&gt;technical consultants&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have listed the ready-made pack on Gumroad for anyone working around Odoo ERP implementation or go-live planning.&lt;/p&gt;

&lt;p&gt;Check it here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://omniacademy.gumroad.com/l/hjacq" rel="noopener noreferrer"&gt;https://omniacademy.gumroad.com/l/hjacq&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Connect with me
&lt;/h2&gt;

&lt;p&gt;Gumroad: &lt;a href="https://omniacademy.gumroad.com" rel="noopener noreferrer"&gt;https://omniacademy.gumroad.com&lt;/a&gt;&lt;br&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/gharisj3" rel="noopener noreferrer"&gt;https://github.com/gharisj3&lt;/a&gt;&lt;br&gt;&lt;br&gt;
LinkedIn: &lt;a href="https://www.linkedin.com/in/muhammad-gharis-javed-318266202" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/muhammad-gharis-javed-318266202&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Contra: &lt;a href="https://contra.com/muhammad_gharis_j2g71vgn" rel="noopener noreferrer"&gt;https://contra.com/muhammad_gharis_j2g71vgn&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Fiverr: &lt;a href="https://www.fiverr.com/sellers/muhammadghar709" rel="noopener noreferrer"&gt;https://www.fiverr.com/sellers/muhammadghar709&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Email: &lt;a href="mailto:gharis@omni-academy.com"&gt;gharis@omni-academy.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>erp</category>
      <category>odoo</category>
      <category>uat</category>
      <category>ai</category>
    </item>
    <item>
      <title>I Built an n8n Client Intake Workflow Pack with Google Sheets CRM and WhatsApp Follow-Up Structure</title>
      <dc:creator>Muhammad Gharis</dc:creator>
      <pubDate>Sun, 14 Jun 2026 08:04:08 +0000</pubDate>
      <link>https://dev.to/muhammad_gharis_fe079470a/i-built-an-n8n-client-intake-workflow-pack-with-google-sheets-crm-and-whatsapp-follow-up-structure-4d12</link>
      <guid>https://dev.to/muhammad_gharis_fe079470a/i-built-an-n8n-client-intake-workflow-pack-with-google-sheets-crm-and-whatsapp-follow-up-structure-4d12</guid>
      <description>&lt;p&gt;Client intake is one of the most underrated parts of freelancing and agency work.&lt;/p&gt;

&lt;p&gt;Many service providers can deliver the work, but their intake process is messy.&lt;/p&gt;

&lt;p&gt;A typical flow looks like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;client sends a WhatsApp message&lt;/li&gt;
&lt;li&gt;requirements are discussed in chat&lt;/li&gt;
&lt;li&gt;important details get buried&lt;/li&gt;
&lt;li&gt;no proper CRM record is created&lt;/li&gt;
&lt;li&gt;follow-up dates are forgotten&lt;/li&gt;
&lt;li&gt;onboarding steps are repeated manually&lt;/li&gt;
&lt;li&gt;client information is scattered across messages, emails, and sheets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This creates confusion before the actual work even starts.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;When client intake is not structured, it affects everything after that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;unclear requirements&lt;/li&gt;
&lt;li&gt;missed follow-ups&lt;/li&gt;
&lt;li&gt;poor project handover&lt;/li&gt;
&lt;li&gt;delayed proposals&lt;/li&gt;
&lt;li&gt;weak client experience&lt;/li&gt;
&lt;li&gt;no central tracking sheet&lt;/li&gt;
&lt;li&gt;repeated manual work&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For freelancers and small agencies, this can directly affect sales and delivery quality.&lt;/p&gt;

&lt;h2&gt;
  
  
  The simple workflow idea
&lt;/h2&gt;

&lt;p&gt;A better client intake system should help you:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;collect client details&lt;/li&gt;
&lt;li&gt;store them in a tracker&lt;/li&gt;
&lt;li&gt;assign status and priority&lt;/li&gt;
&lt;li&gt;document requirements&lt;/li&gt;
&lt;li&gt;prepare follow-up actions&lt;/li&gt;
&lt;li&gt;create a basic CRM-style view&lt;/li&gt;
&lt;li&gt;use reusable messages and prompts&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This does not always require a complex SaaS tool.&lt;/p&gt;

&lt;p&gt;A simple combination of n8n, Google Sheets, WhatsApp follow-up structure, and documentation can be enough for many small teams.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;I created an &lt;strong&gt;n8n Client Intake Workflow Pack&lt;/strong&gt; for freelancers, agencies, consultants, and automation builders.&lt;/p&gt;

&lt;p&gt;It includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;client intake workflow structure&lt;/li&gt;
&lt;li&gt;Google Sheets CRM tracker idea&lt;/li&gt;
&lt;li&gt;WhatsApp follow-up automation structure&lt;/li&gt;
&lt;li&gt;setup guide&lt;/li&gt;
&lt;li&gt;client tracking format&lt;/li&gt;
&lt;li&gt;reusable workflow documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is to help small teams organize client intake without starting from zero.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who this is useful for
&lt;/h2&gt;

&lt;p&gt;This can help:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;freelancers&lt;/li&gt;
&lt;li&gt;consultants&lt;/li&gt;
&lt;li&gt;small agencies&lt;/li&gt;
&lt;li&gt;automation service providers&lt;/li&gt;
&lt;li&gt;virtual assistants&lt;/li&gt;
&lt;li&gt;business operations teams&lt;/li&gt;
&lt;li&gt;people learning n8n workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have listed the ready-made pack on Gumroad for anyone who wants to check it out.&lt;/p&gt;

&lt;p&gt;Link:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://omniacademy.gumroad.com/l/jdbaw" rel="noopener noreferrer"&gt;https://omniacademy.gumroad.com/l/jdbaw&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Connect with me
&lt;/h2&gt;

&lt;p&gt;Gumroad: &lt;a href="https://omniacademy.gumroad.com" rel="noopener noreferrer"&gt;https://omniacademy.gumroad.com&lt;/a&gt;&lt;br&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/gharisj3" rel="noopener noreferrer"&gt;https://github.com/gharisj3&lt;/a&gt;&lt;br&gt;&lt;br&gt;
LinkedIn: &lt;a href="https://www.linkedin.com/in/muhammad-gharis-javed-318266202" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/muhammad-gharis-javed-318266202&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Contra: &lt;a href="https://contra.com/muhammad_gharis_j2g71vgn" rel="noopener noreferrer"&gt;https://contra.com/muhammad_gharis_j2g71vgn&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Fiverr: &lt;a href="https://www.fiverr.com/sellers/muhammadghar709" rel="noopener noreferrer"&gt;https://www.fiverr.com/sellers/muhammadghar709&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Email: &lt;a href="mailto:gharis@omni-academy.com"&gt;gharis@omni-academy.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>n8nbrightdatachallenge</category>
      <category>crm</category>
      <category>whatsapp</category>
      <category>ai</category>
    </item>
    <item>
      <title>25 No-Code Automation Ideas for Freelancers, Agencies and Small Businesses</title>
      <dc:creator>Muhammad Gharis</dc:creator>
      <pubDate>Sun, 14 Jun 2026 08:03:04 +0000</pubDate>
      <link>https://dev.to/muhammad_gharis_fe079470a/25-no-code-automation-ideas-for-freelancers-agencies-and-small-businesses-16ce</link>
      <guid>https://dev.to/muhammad_gharis_fe079470a/25-no-code-automation-ideas-for-freelancers-agencies-and-small-businesses-16ce</guid>
      <description>&lt;p&gt;Many people want to start using automation, but they get stuck at the same point:&lt;/p&gt;

&lt;p&gt;They do not know what to automate first.&lt;/p&gt;

&lt;p&gt;The problem is not always the tool.&lt;/p&gt;

&lt;p&gt;The problem is choosing the right workflow.&lt;/p&gt;

&lt;p&gt;A freelancer, agency, or small business may use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;WhatsApp&lt;/li&gt;
&lt;li&gt;Google Sheets&lt;/li&gt;
&lt;li&gt;email&lt;/li&gt;
&lt;li&gt;forms&lt;/li&gt;
&lt;li&gt;invoices&lt;/li&gt;
&lt;li&gt;CRM notes&lt;/li&gt;
&lt;li&gt;client onboarding documents&lt;/li&gt;
&lt;li&gt;task trackers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But without a clear automation checklist, everything stays manual.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common manual problems
&lt;/h2&gt;

&lt;p&gt;Small teams usually waste time on tasks like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;copying client details from messages to spreadsheets&lt;/li&gt;
&lt;li&gt;sending the same follow-up message again and again&lt;/li&gt;
&lt;li&gt;forgetting invoice reminders&lt;/li&gt;
&lt;li&gt;tracking leads manually&lt;/li&gt;
&lt;li&gt;creating client handover notes from scratch&lt;/li&gt;
&lt;li&gt;checking forms and updating sheets&lt;/li&gt;
&lt;li&gt;repeating onboarding steps for every client&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These tasks are small individually, but together they consume hours every week.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I created this checklist
&lt;/h2&gt;

&lt;p&gt;I created a &lt;strong&gt;Free AI Automation Workflow Checklist&lt;/strong&gt; with 25 no-code automation ideas.&lt;/p&gt;

&lt;p&gt;The purpose is simple:&lt;/p&gt;

&lt;p&gt;Help freelancers, consultants, agencies, and small businesses identify practical automation opportunities without overcomplicating the process.&lt;/p&gt;

&lt;p&gt;This is not about building a massive system.&lt;/p&gt;

&lt;p&gt;It is about finding small workflows that can save time immediately.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example automation ideas
&lt;/h2&gt;

&lt;p&gt;Some useful workflow categories include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;lead capture automation&lt;/li&gt;
&lt;li&gt;client intake automation&lt;/li&gt;
&lt;li&gt;CRM update automation&lt;/li&gt;
&lt;li&gt;invoice reminder automation&lt;/li&gt;
&lt;li&gt;follow-up automation&lt;/li&gt;
&lt;li&gt;onboarding automation&lt;/li&gt;
&lt;li&gt;handover documentation automation&lt;/li&gt;
&lt;li&gt;Google Sheets tracking automation&lt;/li&gt;
&lt;li&gt;AI prompt-based content or data processing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A simple checklist can help you decide what to automate first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who can use this
&lt;/h2&gt;

&lt;p&gt;This checklist is useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;freelancers&lt;/li&gt;
&lt;li&gt;consultants&lt;/li&gt;
&lt;li&gt;small agencies&lt;/li&gt;
&lt;li&gt;beginner automation builders&lt;/li&gt;
&lt;li&gt;no-code learners&lt;/li&gt;
&lt;li&gt;small business owners&lt;/li&gt;
&lt;li&gt;virtual assistants&lt;/li&gt;
&lt;li&gt;operations teams&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have listed it on Gumroad as a free / pay-what-you-want resource.&lt;/p&gt;

&lt;p&gt;You can check it here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://omniacademy.gumroad.com/l/sexej" rel="noopener noreferrer"&gt;https://omniacademy.gumroad.com/l/sexej&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Connect with me
&lt;/h2&gt;

&lt;p&gt;Gumroad: &lt;a href="https://omniacademy.gumroad.com" rel="noopener noreferrer"&gt;https://omniacademy.gumroad.com&lt;/a&gt;&lt;br&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/gharisj3" rel="noopener noreferrer"&gt;https://github.com/gharisj3&lt;/a&gt;&lt;br&gt;&lt;br&gt;
LinkedIn: &lt;a href="https://www.linkedin.com/in/muhammad-gharis-javed-318266202" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/muhammad-gharis-javed-318266202&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Contra: &lt;a href="https://contra.com/muhammad_gharis_j2g71vgn" rel="noopener noreferrer"&gt;https://contra.com/muhammad_gharis_j2g71vgn&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Fiverr: &lt;a href="https://www.fiverr.com/sellers/muhammadghar709" rel="noopener noreferrer"&gt;https://www.fiverr.com/sellers/muhammadghar709&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Email: &lt;a href="mailto:gharis@omni-academy.com"&gt;gharis@omni-academy.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>startup</category>
      <category>ai</category>
      <category>requestforpost</category>
      <category>automaton</category>
    </item>
    <item>
      <title>I Built a Simple AI Lead Qualification CRM Workflow Pack for Freelancers and Small Teams</title>
      <dc:creator>Muhammad Gharis</dc:creator>
      <pubDate>Sun, 14 Jun 2026 07:41:08 +0000</pubDate>
      <link>https://dev.to/muhammad_gharis_fe079470a/i-built-a-simple-ai-lead-qualification-crm-workflow-pack-for-freelancers-and-small-teams-2c8o</link>
      <guid>https://dev.to/muhammad_gharis_fe079470a/i-built-a-simple-ai-lead-qualification-crm-workflow-pack-for-freelancers-and-small-teams-2c8o</guid>
      <description>&lt;h1&gt;
  
  
  I Built a Simple AI Lead Qualification CRM Workflow Pack for Freelancers and Small Teams
&lt;/h1&gt;

&lt;p&gt;Most freelancers, agencies, consultants, and small businesses do not lose leads because they are bad at selling.&lt;/p&gt;

&lt;p&gt;They lose leads because their follow-up system is weak.&lt;/p&gt;

&lt;p&gt;A common situation looks like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;leads come from LinkedIn, WhatsApp, email, forms, or referrals&lt;/li&gt;
&lt;li&gt;notes are saved in random chats&lt;/li&gt;
&lt;li&gt;follow-ups are forgotten&lt;/li&gt;
&lt;li&gt;lead quality is not scored properly&lt;/li&gt;
&lt;li&gt;there is no simple CRM pipeline&lt;/li&gt;
&lt;li&gt;every new client inquiry starts from zero again&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Large CRM tools are useful, but many small teams do not need a complex SaaS system on day one.&lt;/p&gt;

&lt;p&gt;They need a lightweight system that helps them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;capture leads&lt;/li&gt;
&lt;li&gt;qualify leads&lt;/li&gt;
&lt;li&gt;score lead quality&lt;/li&gt;
&lt;li&gt;track follow-ups&lt;/li&gt;
&lt;li&gt;move leads through a pipeline&lt;/li&gt;
&lt;li&gt;reuse AI prompts for lead analysis&lt;/li&gt;
&lt;li&gt;document the sales process clearly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I built a practical &lt;strong&gt;AI Lead Qualification CRM Workflow Pack&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the pack includes
&lt;/h2&gt;

&lt;p&gt;This pack is designed for freelancers, consultants, agencies, and small businesses that want a simple AI-assisted lead qualification workflow.&lt;/p&gt;

&lt;p&gt;It includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;n8n lead qualification workflow idea&lt;/li&gt;
&lt;li&gt;lead scoring sheet&lt;/li&gt;
&lt;li&gt;CRM pipeline template&lt;/li&gt;
&lt;li&gt;AI prompt pack for lead analysis&lt;/li&gt;
&lt;li&gt;follow-up tracking structure&lt;/li&gt;
&lt;li&gt;simple workflow documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is not to replace a full CRM platform.&lt;/p&gt;

&lt;p&gt;The goal is to help small teams organize leads before they become messy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I built it
&lt;/h2&gt;

&lt;p&gt;In real freelance and agency work, most missed opportunities come from poor tracking.&lt;/p&gt;

&lt;p&gt;A lead may be interested today, but if nobody follows up after 2 days, that opportunity becomes cold.&lt;/p&gt;

&lt;p&gt;A simple workflow can make a big difference:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Capture the lead&lt;/li&gt;
&lt;li&gt;Score the lead&lt;/li&gt;
&lt;li&gt;Add notes&lt;/li&gt;
&lt;li&gt;Assign a follow-up date&lt;/li&gt;
&lt;li&gt;Move the lead through stages&lt;/li&gt;
&lt;li&gt;Reuse AI prompts to analyze intent and priority&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This kind of structure saves time and reduces manual decision-making.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who this is useful for
&lt;/h2&gt;

&lt;p&gt;This can help:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;freelancers&lt;/li&gt;
&lt;li&gt;solo consultants&lt;/li&gt;
&lt;li&gt;small agencies&lt;/li&gt;
&lt;li&gt;service providers&lt;/li&gt;
&lt;li&gt;automation builders&lt;/li&gt;
&lt;li&gt;CRM beginners&lt;/li&gt;
&lt;li&gt;people selling digital or professional services&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have listed this as a small paid digital product on Gumroad for anyone who wants to use the ready-made version instead of building it from scratch.&lt;/p&gt;

&lt;p&gt;Check it here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://omniacademy.gumroad.com/l/pkybo" rel="noopener noreferrer"&gt;https://omniacademy.gumroad.com/l/pkybo&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Connect with me
&lt;/h2&gt;

&lt;p&gt;Gumroad: &lt;a href="https://omniacademy.gumroad.com" rel="noopener noreferrer"&gt;https://omniacademy.gumroad.com&lt;/a&gt;&lt;br&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/gharisj3" rel="noopener noreferrer"&gt;https://github.com/gharisj3&lt;/a&gt;&lt;br&gt;&lt;br&gt;
LinkedIn: &lt;a href="https://www.linkedin.com/in/muhammad-gharis-javed-318266202" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/muhammad-gharis-javed-318266202&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Contra: &lt;a href="https://contra.com/muhammad_gharis_j2g71vgn" rel="noopener noreferrer"&gt;https://contra.com/muhammad_gharis_j2g71vgn&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Fiverr: &lt;a href="https://www.fiverr.com/sellers/muhammadghar709" rel="noopener noreferrer"&gt;https://www.fiverr.com/sellers/muhammadghar709&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Email: &lt;a href="mailto:gharis@omni-academy.com"&gt;gharis@omni-academy.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>crm</category>
      <category>tooling</category>
      <category>freelance</category>
    </item>
    <item>
      <title>How I Built an AI Business Automation Workflow Pack with n8n, Google Sheets and JSON Templates</title>
      <dc:creator>Muhammad Gharis</dc:creator>
      <pubDate>Thu, 11 Jun 2026 15:30:25 +0000</pubDate>
      <link>https://dev.to/muhammad_gharis_fe079470a/how-i-built-an-ai-business-automation-workflow-pack-with-n8n-google-sheets-and-json-templates-5f1c</link>
      <guid>https://dev.to/muhammad_gharis_fe079470a/how-i-built-an-ai-business-automation-workflow-pack-with-n8n-google-sheets-and-json-templates-5f1c</guid>
      <description>&lt;h1&gt;
  
  
  How I Built an AI Business Automation Workflow Pack with n8n, Google Sheets and JSON Templates
&lt;/h1&gt;

&lt;p&gt;Most business automation ideas sound simple at the start:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Capture a lead, save it somewhere, send a reply, and follow up later.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But when you try to build it properly for a real client or business, the workflow becomes more serious.&lt;/p&gt;

&lt;p&gt;You need to think about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How the lead data enters the system&lt;/li&gt;
&lt;li&gt;Where the data is stored&lt;/li&gt;
&lt;li&gt;What happens if a field is missing&lt;/li&gt;
&lt;li&gt;How the AI response is generated&lt;/li&gt;
&lt;li&gt;How follow-ups are tracked&lt;/li&gt;
&lt;li&gt;What happens if an API fails&lt;/li&gt;
&lt;li&gt;How the client will understand and maintain the workflow later&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is why I decided to build a structured &lt;strong&gt;AI Business Automation Workflow Pack&lt;/strong&gt; using n8n-style workflow templates, Google Sheets-style CRM trackers, JSON workflow files, prompt templates, testing checklists, and client handover documents.&lt;/p&gt;

&lt;p&gt;This post explains the thinking behind it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem I Wanted to Solve
&lt;/h2&gt;

&lt;p&gt;Many freelancers and small businesses want automation, but they usually do not need a huge CRM or expensive SaaS setup at the beginning.&lt;/p&gt;

&lt;p&gt;They need something practical:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Capture leads from forms or webhooks&lt;/li&gt;
&lt;li&gt;Store inquiries in a simple CRM tracker&lt;/li&gt;
&lt;li&gt;Draft AI-assisted replies&lt;/li&gt;
&lt;li&gt;Follow up with leads&lt;/li&gt;
&lt;li&gt;Track invoice/payment reminders&lt;/li&gt;
&lt;li&gt;Triage support messages&lt;/li&gt;
&lt;li&gt;Deliver the workflow to a client professionally&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The real pain is not just building one automation.&lt;/p&gt;

&lt;p&gt;The real pain is building a repeatable system that can be reused across clients and projects.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Core Stack
&lt;/h2&gt;

&lt;p&gt;For this product, I designed the pack around a simple and practical stack:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Webhook / Form Input
        ↓
n8n Workflow Template
        ↓
Data Cleaning / Validation
        ↓
AI Prompt / Reply Draft
        ↓
Google Sheets-style CRM Tracker
        ↓
Email / Follow-Up / Client Output
        ↓
Testing + Handover Documentation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The goal was to make each workflow easy to understand, modify, and reuse.&lt;/p&gt;




&lt;h2&gt;
  
  
  What the Pack Includes
&lt;/h2&gt;

&lt;p&gt;I structured the product into several parts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. n8n workflow JSON templates
2. Google Sheets-style CRM trackers
3. AI prompt templates
4. PDF setup guides
5. Testing checklists
6. Error handling checklists
7. Client handover documents
8. README and license files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The idea is that a freelancer or automation consultant can use the pack as a starting point instead of creating everything from scratch.&lt;/p&gt;




&lt;h2&gt;
  
  
  Workflow 1: Lead Intake to CRM Tracker
&lt;/h2&gt;

&lt;p&gt;The first workflow is a simple lead intake flow.&lt;/p&gt;

&lt;p&gt;The structure looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Webhook receives lead
        ↓
Validate required fields
        ↓
Normalize name, email, phone, source
        ↓
Assign lead status
        ↓
Save to CRM tracker
        ↓
Return success response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example lead data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"John Smith"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"john@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"phone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"+123456789"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Website Form"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"I need automation for my business"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The workflow is designed to make sure every lead has a proper structure before it is stored.&lt;/p&gt;




&lt;h2&gt;
  
  
  Workflow 2: Contact Form to Google Sheets + Email Alert
&lt;/h2&gt;

&lt;p&gt;This workflow is useful for small businesses that receive contact form messages.&lt;/p&gt;

&lt;p&gt;The flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Contact form submission
        ↓
Clean message text
        ↓
Store submission
        ↓
Prepare internal notification
        ↓
Send email alert
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important part here is not just sending an email.&lt;/p&gt;

&lt;p&gt;The important part is keeping a proper record of every inquiry so nothing gets lost.&lt;/p&gt;




&lt;h2&gt;
  
  
  Workflow 3: AI Email Reply Draft
&lt;/h2&gt;

&lt;p&gt;This is one of the most useful workflows in the pack.&lt;/p&gt;

&lt;p&gt;The flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client message received
        ↓
Send message to AI prompt
        ↓
Generate professional reply draft
        ↓
Save draft to tracker
        ↓
Human reviews before sending
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I intentionally designed this as a &lt;strong&gt;draft workflow&lt;/strong&gt;, not a fully automatic send workflow.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because AI-generated replies should usually be reviewed before sending to a real client, especially in business communication.&lt;/p&gt;

&lt;p&gt;Example output structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sales_inquiry"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"priority"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"medium"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"suggested_reply"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Thank you for reaching out. I would be happy to understand your automation requirements..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"next_action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"schedule_discovery_call"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.86&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This keeps the workflow safer and more professional.&lt;/p&gt;




&lt;h2&gt;
  
  
  Workflow 4: Client Follow-Up Reminder
&lt;/h2&gt;

&lt;p&gt;Follow-ups are where many freelancers and small businesses lose money.&lt;/p&gt;

&lt;p&gt;A lead comes in, the client sounds interested, then nobody follows up.&lt;/p&gt;

&lt;p&gt;The workflow logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Read lead tracker
        ↓
Find pending follow-ups
        ↓
Check last contact date
        ↓
Prepare follow-up message
        ↓
Update follow-up status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A simple follow-up tracker can include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Lead Name
Email
Phone
Status
Last Contact Date
Next Follow-Up Date
Follow-Up Message
Assigned Person
Notes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can be very useful for freelancers, agencies, and small sales teams.&lt;/p&gt;




&lt;h2&gt;
  
  
  Workflow 5: Invoice / Payment Reminder
&lt;/h2&gt;

&lt;p&gt;This workflow is designed for overdue invoice reminders.&lt;/p&gt;

&lt;p&gt;The flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Read invoice tracker
        ↓
Find unpaid invoices
        ↓
Check due date
        ↓
Generate polite reminder message
        ↓
Prepare email or message output
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example reminder logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;If due date is passed and payment status is unpaid:
    Prepare reminder
Else:
    Do nothing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is simple, but very practical.&lt;/p&gt;

&lt;p&gt;Many freelancers do not need advanced accounting software in the beginning. They just need a clean way to track pending payments and follow up professionally.&lt;/p&gt;




&lt;h2&gt;
  
  
  Workflow 6: Support Ticket Triage
&lt;/h2&gt;

&lt;p&gt;The final workflow is for support requests.&lt;/p&gt;

&lt;p&gt;The flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Support request received
        ↓
Classify category
        ↓
Detect priority
        ↓
Generate suggested response
        ↓
Log ticket status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example categories:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Billing
Technical Issue
Feature Request
Account Access
General Question
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example priority levels:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Low
Medium
High
Critical
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This type of workflow is useful for agencies, SaaS teams, support teams, and service businesses.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I Used JSON Templates
&lt;/h2&gt;

&lt;p&gt;JSON templates make workflow packaging easier because they can be imported, reviewed, versioned, and reused.&lt;/p&gt;

&lt;p&gt;For automation builders, this is useful because the workflow is not just a screenshot or idea.&lt;/p&gt;

&lt;p&gt;It becomes a file that can be copied, modified, tested, and improved.&lt;/p&gt;

&lt;p&gt;A good workflow template should include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Clear node names
Placeholder credentials
No real API keys
Sample test data
Documentation notes
Error handling path
Clean workflow structure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I used placeholders like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;YOUR_API_KEY_HERE
YOUR_WEBHOOK_URL_HERE
YOUR_SHEET_ID_HERE
YOUR_EMAIL_HERE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Never include real credentials in a template product.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I Included Google Sheets-Style Trackers
&lt;/h2&gt;

&lt;p&gt;Not every small business wants to pay for a CRM immediately.&lt;/p&gt;

&lt;p&gt;A spreadsheet can work well for early-stage workflows.&lt;/p&gt;

&lt;p&gt;The CRM tracker structure includes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Leads
Contacts
Companies
Follow-Ups
Automation Logs
Email Drafts
Status Dashboard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives users a simple place to store and review automation output.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Testing Checklists Matter
&lt;/h2&gt;

&lt;p&gt;A workflow is not production-ready just because it runs once.&lt;/p&gt;

&lt;p&gt;Before using an automation with a real client, I like to test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Required fields
Invalid email format
Duplicate records
API failure
Empty response
Wrong data type
Webhook response
Sheet writing
Email output
End-to-end flow
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is why I included workflow testing and error handling checklists in the pack.&lt;/p&gt;

&lt;p&gt;A good automation product should not only help users build faster. It should help them build safer.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lessons Learned While Building This
&lt;/h2&gt;

&lt;p&gt;Here are the biggest lessons from creating this kind of automation pack:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Generic workflows are not enough
&lt;/h3&gt;

&lt;p&gt;A workflow is more valuable when it comes with setup guides, checklists, trackers, and handover documents.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. AI should support humans, not replace review
&lt;/h3&gt;

&lt;p&gt;For email replies, proposals, and client communication, AI drafts should usually be reviewed before sending.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Templates need placeholders, not secrets
&lt;/h3&gt;

&lt;p&gt;Never include real credentials, API keys, tokens, or client data.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Small businesses prefer simple systems
&lt;/h3&gt;

&lt;p&gt;A clear spreadsheet plus a workflow is sometimes more useful than a complex SaaS setup.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Documentation increases trust
&lt;/h3&gt;

&lt;p&gt;If a client cannot understand the automation, they will not feel comfortable using it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Who This Type of Pack Is Useful For
&lt;/h2&gt;

&lt;p&gt;This kind of workflow pack can help:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Freelancers
Automation consultants
n8n builders
Virtual assistants
Small agencies
Startup operators
Small business owners
Backend developers
AI automation service providers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The main use case is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Build client-ready business automations faster without starting from zero every time.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  What I Published
&lt;/h2&gt;

&lt;p&gt;I packaged the full version as a digital product here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://omniacademy.gumroad.com/l/qwajt?layout=profile" rel="noopener noreferrer"&gt;AI Business Automation Workflow Pack — n8n Templates, Google Sheets CRM &amp;amp; Client Automation Kit&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It includes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;6 workflow templates
CRM tracker templates
AI prompt templates
PDF setup guides
Testing checklists
Error handling checklist
Client handover documents
README and license files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Disclosure: This is my own digital product from Omni Academy Consulting and Technologies. The article is written to share the build process and structure behind the product.&lt;/p&gt;




&lt;h2&gt;
  
  
  Connect With Me
&lt;/h2&gt;

&lt;p&gt;You can also connect with me here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LinkedIn: &lt;a href="https://www.linkedin.com/in/muhammad-gharis-javed-318266202/" rel="noopener noreferrer"&gt;LinkedIn Profile&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/gharisj3" rel="noopener noreferrer"&gt;Github Repo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Gumroad: &lt;a href="https://omniacademy.gumroad.com" rel="noopener noreferrer"&gt;Omni Academy Consulting and Technologies&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;AI automation is not only about connecting tools.&lt;/p&gt;

&lt;p&gt;It is about designing a repeatable business process.&lt;/p&gt;

&lt;p&gt;A strong automation workflow should be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Understandable
Testable
Documented
Safe
Reusable
Client-ready
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is the standard I tried to follow while building this pack.&lt;/p&gt;

&lt;p&gt;If you are building automation products or client workflows, my advice is simple:&lt;/p&gt;

&lt;p&gt;Do not only build the workflow.&lt;/p&gt;

&lt;p&gt;Build the system around the workflow.&lt;/p&gt;

</description>
      <category>n8n</category>
      <category>automation</category>
      <category>ai</category>
      <category>freelance</category>
    </item>
    <item>
      <title>Why Your AI-Connected ERP Will Fail in Production And How to Fix It Before It Does</title>
      <dc:creator>Muhammad Gharis</dc:creator>
      <pubDate>Wed, 10 Jun 2026 20:56:06 +0000</pubDate>
      <link>https://dev.to/muhammad_gharis_fe079470a/why-your-ai-connected-erp-will-fail-in-production-and-how-to-fix-it-before-it-does-306o</link>
      <guid>https://dev.to/muhammad_gharis_fe079470a/why-your-ai-connected-erp-will-fail-in-production-and-how-to-fix-it-before-it-does-306o</guid>
      <description>&lt;p&gt;Most AI + ERP integrations fail in production not because the AI model is weak, but because there is no validation layer between the LLM output and the database.&lt;/p&gt;

&lt;p&gt;Raw AI responses should never go directly into ERP fields.&lt;/p&gt;

&lt;h3&gt;
  
  
  Structure
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;The demo problem: AI works perfectly in a controlled example&lt;/li&gt;
&lt;li&gt;The production problem: real data is messy and LLM output is unpredictable&lt;/li&gt;
&lt;li&gt;Example failure: hallucinated vendor name in accounts payable&lt;/li&gt;
&lt;li&gt;Why direct AI → ERP writes are dangerous&lt;/li&gt;
&lt;li&gt;The fix: FastAPI middleware + Pydantic v2 validation&lt;/li&gt;
&lt;li&gt;Code example: validated AI response schema&lt;/li&gt;
&lt;li&gt;Code example: FastAPI endpoint returning structured output&lt;/li&gt;
&lt;li&gt;Production pattern: AI → validation → workflow → ERP&lt;/li&gt;
&lt;li&gt;Error handling: log failure instead of corrupting records&lt;/li&gt;
&lt;li&gt;Repo reference: omni-odoo-stack&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Suggested CTA
&lt;/h3&gt;

&lt;p&gt;I built this pattern into my open-source Odoo automation repo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/gharisj3/omni-odoo-stack" rel="noopener noreferrer"&gt;https://github.com/gharisj3/omni-odoo-stack&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Post 3
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Title
&lt;/h3&gt;

&lt;p&gt;How to Build a WhatsApp to CRM Pipeline with n8n and Odoo 19&lt;/p&gt;

&lt;h3&gt;
  
  
  Tags
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;n8n&lt;/code&gt;, &lt;code&gt;odoo&lt;/code&gt;, &lt;code&gt;automation&lt;/code&gt;, &lt;code&gt;webhooks&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Hook
&lt;/h3&gt;

&lt;p&gt;Every WhatsApp message from a potential client should create a CRM lead automatically.&lt;/p&gt;

&lt;p&gt;Here is the architecture I use to make that happen with n8n, Odoo, and WhatsApp Cloud API.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why This Can Perform Well
&lt;/h3&gt;

&lt;p&gt;WhatsApp automation is highly practical.&lt;/p&gt;

&lt;p&gt;Odoo + WhatsApp tutorials are limited.&lt;/p&gt;

&lt;p&gt;n8n users actively search for CRM, webhook, WhatsApp, and API automation examples.&lt;/p&gt;

&lt;h3&gt;
  
  
  Core Angle
&lt;/h3&gt;

&lt;p&gt;Show a practical architecture for turning WhatsApp conversations into CRM leads using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Meta WhatsApp Cloud API&lt;/li&gt;
&lt;li&gt;n8n webhook trigger&lt;/li&gt;
&lt;li&gt;Odoo CRM&lt;/li&gt;
&lt;li&gt;FastAPI AI lead scoring&lt;/li&gt;
&lt;li&gt;duplicate prevention&lt;/li&gt;
&lt;li&gt;error logging&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Structure
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Why WhatsApp is a serious business intake channel&lt;/li&gt;
&lt;li&gt;What you need:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Meta Business account&lt;/li&gt;
&lt;li&gt;WhatsApp Cloud API&lt;/li&gt;
&lt;li&gt;self-hosted n8n&lt;/li&gt;
&lt;li&gt;Odoo 19&lt;/li&gt;
&lt;li&gt;optional FastAPI AI middleware

&lt;ol&gt;
&lt;li&gt;Step 1: WhatsApp webhook setup&lt;/li&gt;
&lt;li&gt;Step 2: n8n webhook trigger&lt;/li&gt;
&lt;li&gt;Step 3: parse phone number, message body, and message ID&lt;/li&gt;
&lt;li&gt;Step 4: duplicate prevention using message ID&lt;/li&gt;
&lt;li&gt;Step 5: call AI scoring middleware&lt;/li&gt;
&lt;li&gt;Step 6: create CRM lead in Odoo&lt;/li&gt;
&lt;li&gt;Step 7: send WhatsApp confirmation&lt;/li&gt;
&lt;li&gt;Step 8: log success or failure&lt;/li&gt;
&lt;li&gt;Full workflow JSON available in repo&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Important Wording Change
&lt;/h3&gt;

&lt;p&gt;Avoid:&lt;/p&gt;

&lt;p&gt;“No Code”&lt;/p&gt;

&lt;p&gt;Use:&lt;/p&gt;

&lt;p&gt;“No Zapier, No Monthly Automation Fees”&lt;/p&gt;

&lt;p&gt;Because the workflow still requires API setup, webhook configuration, and Odoo endpoint understanding.&lt;/p&gt;

&lt;h3&gt;
  
  
  Suggested CTA
&lt;/h3&gt;

&lt;p&gt;The full workflow JSON is available here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/gharisj3/omni-odoo-stack" rel="noopener noreferrer"&gt;https://github.com/gharisj3/omni-odoo-stack&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Post 4
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Title
&lt;/h3&gt;

&lt;p&gt;Self-Hosting Odoo 19 on Oracle OCI Free Tier — Complete Setup Guide&lt;/p&gt;

&lt;h3&gt;
  
  
  Tags
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;odoo&lt;/code&gt;, &lt;code&gt;docker&lt;/code&gt;, &lt;code&gt;oracle&lt;/code&gt;, &lt;code&gt;devops&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Hook
&lt;/h3&gt;

&lt;p&gt;Odoo hosting can cost $50–200/month on typical VPS or managed platforms.&lt;/p&gt;

&lt;p&gt;Oracle OCI Always Free gives developers a powerful free-tier path for self-hosted ERP experiments.&lt;/p&gt;

&lt;p&gt;Here is the setup approach.&lt;/p&gt;

&lt;h3&gt;
  
  
  Important Warning Before Publishing
&lt;/h3&gt;

&lt;p&gt;Do not publish this as a “complete guide” until you have actually deployed and boot-tested Odoo on OCI.&lt;/p&gt;

&lt;p&gt;This post will attract people who copy commands directly.&lt;/p&gt;

&lt;p&gt;If the guide is not tested, it can hurt your credibility.&lt;/p&gt;

&lt;h3&gt;
  
  
  Safer Title Until Tested
&lt;/h3&gt;

&lt;p&gt;How I Plan to Self-Host Odoo 19 on Oracle OCI Free Tier&lt;/p&gt;

&lt;h3&gt;
  
  
  Stronger Title After Testing
&lt;/h3&gt;

&lt;p&gt;Self-Hosting Odoo 19 on Oracle OCI Free Tier — Complete Tested Setup Guide&lt;/p&gt;

&lt;h3&gt;
  
  
  Structure
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Why OCI Always Free is interesting for Odoo&lt;/li&gt;
&lt;li&gt;Free-tier limits and what to verify before relying on it&lt;/li&gt;
&lt;li&gt;Create ARM VM&lt;/li&gt;
&lt;li&gt;Configure SSH access&lt;/li&gt;
&lt;li&gt;Open firewall ports&lt;/li&gt;
&lt;li&gt;Install Docker and Docker Compose&lt;/li&gt;
&lt;li&gt;Deploy PostgreSQL + Odoo with Docker Compose&lt;/li&gt;
&lt;li&gt;Configure Nginx reverse proxy&lt;/li&gt;
&lt;li&gt;Add SSL with Let's Encrypt&lt;/li&gt;
&lt;li&gt;First Odoo login and database setup&lt;/li&gt;
&lt;li&gt;Common errors and fixes&lt;/li&gt;
&lt;li&gt;Final architecture diagram&lt;/li&gt;
&lt;li&gt;Link to omni-odoo-stack repo&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Publish Status
&lt;/h3&gt;

&lt;p&gt;Hold until runtime tested.&lt;/p&gt;




&lt;h2&gt;
  
  
  Post 5
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Title
&lt;/h3&gt;

&lt;p&gt;5 Odoo Backend Problems I Fix Every Week And the Code That Solves Them&lt;/p&gt;

&lt;h3&gt;
  
  
  Tags
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;odoo&lt;/code&gt;, &lt;code&gt;python&lt;/code&gt;, &lt;code&gt;postgresql&lt;/code&gt;, &lt;code&gt;backend&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Hook
&lt;/h3&gt;

&lt;p&gt;These five problems account for most Odoo backend issues I see in real projects.&lt;/p&gt;

&lt;p&gt;Here is the symptom, the root cause, and the code pattern that fixes each one.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why This Can Perform Well
&lt;/h3&gt;

&lt;p&gt;This is search-friendly and practical.&lt;/p&gt;

&lt;p&gt;Developers search for specific Odoo issues, not general strategy.&lt;/p&gt;

&lt;p&gt;Listicles with code also perform well because readers can scan quickly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Structure
&lt;/h3&gt;

&lt;h2&gt;
  
  
  Problem 1 — Slow Scheduled Actions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Symptom
&lt;/h3&gt;

&lt;p&gt;Scheduled action times out on large datasets.&lt;/p&gt;

&lt;h3&gt;
  
  
  Root Cause
&lt;/h3&gt;

&lt;p&gt;The job searches too many records at once and processes everything in a single transaction.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bad Pattern
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;records&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sale.order&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;([])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Better Pattern
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;records&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sale.order&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;state&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;draft&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
    &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Lesson
&lt;/h3&gt;

&lt;p&gt;Always filter and batch scheduled jobs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Problem 2 — Duplicate Records from Webhooks
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Symptom
&lt;/h3&gt;

&lt;p&gt;Every webhook creates duplicate CRM leads, invoices, or messages.&lt;/p&gt;

&lt;h3&gt;
  
  
  Root Cause
&lt;/h3&gt;

&lt;p&gt;No idempotency check.&lt;/p&gt;

&lt;h3&gt;
  
  
  Better Pattern
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;existing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;omni.whatsapp.message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;external_message_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message_id&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
    &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;duplicate_skipped&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;omni.whatsapp.message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Lesson
&lt;/h3&gt;

&lt;p&gt;Every external webhook should have a deduplication key.&lt;/p&gt;




&lt;h2&gt;
  
  
  Problem 3 — Slow Search Views
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Symptom
&lt;/h3&gt;

&lt;p&gt;Odoo list view takes several seconds to load.&lt;/p&gt;

&lt;h3&gt;
  
  
  Root Cause
&lt;/h3&gt;

&lt;p&gt;Frequently filtered fields are not indexed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Better Pattern
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;partner_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Many2one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;res.partner&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Customer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Lesson
&lt;/h3&gt;

&lt;p&gt;Index fields used in domains, filters, and joins.&lt;/p&gt;




&lt;h2&gt;
  
  
  Problem 4 — Custom Module Breaks on Upgrade
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Symptom
&lt;/h3&gt;

&lt;p&gt;Module works in one Odoo version but fails after upgrade.&lt;/p&gt;

&lt;h3&gt;
  
  
  Root Cause
&lt;/h3&gt;

&lt;p&gt;Private/internal methods are used instead of stable ORM patterns.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bad Pattern
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_some_private_method&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Better Pattern
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;state&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;confirmed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Lesson
&lt;/h3&gt;

&lt;p&gt;Avoid private methods unless there is no alternative.&lt;/p&gt;




&lt;h2&gt;
  
  
  Problem 5 — n8n + Odoo Authentication Fails
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Symptom
&lt;/h3&gt;

&lt;p&gt;n8n returns 401 errors when calling custom Odoo controllers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Root Cause
&lt;/h3&gt;

&lt;p&gt;The built-in Odoo node uses JSON-RPC patterns, but custom REST controllers often need explicit HTTP authentication/session handling.&lt;/p&gt;

&lt;h3&gt;
  
  
  Better Pattern
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Authenticate against Odoo
2. Store session cookie
3. Call custom endpoint with cookie/header
4. Handle errors explicitly
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Lesson
&lt;/h3&gt;

&lt;p&gt;For custom controllers, HTTP Request nodes often give more control than the built-in Odoo node.&lt;/p&gt;




&lt;h2&gt;
  
  
  Suggested Ending
&lt;/h2&gt;

&lt;p&gt;Backend issues in Odoo are rarely solved by adding more automation.&lt;/p&gt;

&lt;p&gt;They are solved by better architecture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;batching&lt;/li&gt;
&lt;li&gt;validation&lt;/li&gt;
&lt;li&gt;idempotency&lt;/li&gt;
&lt;li&gt;indexing&lt;/li&gt;
&lt;li&gt;clean ORM usage&lt;/li&gt;
&lt;li&gt;proper API boundaries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I use these same patterns in my open-source Odoo automation repo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/gharisj3/omni-odoo-stack" rel="noopener noreferrer"&gt;https://github.com/gharisj3/omni-odoo-stack&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>fastapi</category>
      <category>erp</category>
    </item>
    <item>
      <title>I Replaced a $300/month Automation Stack with n8n, FastAPI, and Docker</title>
      <dc:creator>Muhammad Gharis</dc:creator>
      <pubDate>Wed, 10 Jun 2026 20:52:43 +0000</pubDate>
      <link>https://dev.to/muhammad_gharis_fe079470a/i-replaced-a-300month-automation-stack-with-n8n-fastapi-and-docker-58oj</link>
      <guid>https://dev.to/muhammad_gharis_fe079470a/i-replaced-a-300month-automation-stack-with-n8n-fastapi-and-docker-58oj</guid>
      <description>&lt;p&gt;Most small business automation stacks start simple.&lt;/p&gt;

&lt;p&gt;A form submission goes into a CRM.&lt;/p&gt;

&lt;p&gt;A lead gets scored.&lt;/p&gt;

&lt;p&gt;An email or WhatsApp message gets sent.&lt;/p&gt;

&lt;p&gt;Maybe an invoice gets extracted with AI.&lt;/p&gt;

&lt;p&gt;Then one day, the stack looks like this:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Monthly Cost&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Zapier Professional&lt;/td&gt;
&lt;td&gt;$49&lt;/td&gt;
&lt;td&gt;Workflow automation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Make Core&lt;/td&gt;
&lt;td&gt;$29&lt;/td&gt;
&lt;td&gt;Secondary automation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OpenAI API&lt;/td&gt;
&lt;td&gt;$60+&lt;/td&gt;
&lt;td&gt;AI processing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HubSpot Starter&lt;/td&gt;
&lt;td&gt;$50&lt;/td&gt;
&lt;td&gt;CRM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typeform&lt;/td&gt;
&lt;td&gt;$25&lt;/td&gt;
&lt;td&gt;Form intake&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Airtable Plus&lt;/td&gt;
&lt;td&gt;$20&lt;/td&gt;
&lt;td&gt;Data storage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Webhook testing / API tools&lt;/td&gt;
&lt;td&gt;$20+&lt;/td&gt;
&lt;td&gt;Debugging and routing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Extra automation tools&lt;/td&gt;
&lt;td&gt;$30+&lt;/td&gt;
&lt;td&gt;Glue logic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$280–$300+/month&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fragmented automation stack&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The bigger problem is not only the cost.&lt;/p&gt;

&lt;p&gt;The bigger problem is fragmentation.&lt;/p&gt;

&lt;p&gt;Zapier triggers Make.&lt;/p&gt;

&lt;p&gt;Make calls an AI API.&lt;/p&gt;

&lt;p&gt;The AI response gets written to Airtable.&lt;/p&gt;

&lt;p&gt;A separate sync pushes data into the CRM.&lt;/p&gt;

&lt;p&gt;Errors happen silently.&lt;/p&gt;

&lt;p&gt;Duplicate records appear.&lt;/p&gt;

&lt;p&gt;Nobody knows where the source of truth lives.&lt;/p&gt;

&lt;p&gt;I built &lt;strong&gt;omni-odoo-stack&lt;/strong&gt; to explore a cleaner alternative:&lt;/p&gt;

&lt;p&gt;A self-hosted, open-source-friendly automation architecture using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;n8n&lt;/li&gt;
&lt;li&gt;FastAPI&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;PostgreSQL&lt;/li&gt;
&lt;li&gt;Odoo 19 Community&lt;/li&gt;
&lt;li&gt;Groq / Llama 3&lt;/li&gt;
&lt;li&gt;WhatsApp Cloud API&lt;/li&gt;
&lt;li&gt;Nginx&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal was to show how a business automation stack can be designed with fewer moving parts, better validation, and lower infrastructure cost.&lt;/p&gt;

&lt;p&gt;Repository:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/gharisj3/omni-odoo-stack" rel="noopener noreferrer"&gt;github.com/gharisj3/omni-odoo-stack&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Replacement Stack
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Paid / Fragmented Tool&lt;/th&gt;
&lt;th&gt;Replacement&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Zapier / Make / Pipedream&lt;/td&gt;
&lt;td&gt;n8n self-hosted&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Raw AI API calls&lt;/td&gt;
&lt;td&gt;FastAPI + Pydantic validation&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HubSpot CRM&lt;/td&gt;
&lt;td&gt;Odoo 19 Community CRM&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Airtable&lt;/td&gt;
&lt;td&gt;PostgreSQL&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typeform&lt;/td&gt;
&lt;td&gt;Custom webhook endpoint&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Webhook testing tools&lt;/td&gt;
&lt;td&gt;n8n webhook trigger + logs&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VPS hosting&lt;/td&gt;
&lt;td&gt;Oracle OCI Always Free path&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The architecture is designed to run on a single Docker Compose stack.&lt;/p&gt;

&lt;p&gt;The exact cloud cost depends on provider limits and usage, but the project is designed around a &lt;strong&gt;$0/month infrastructure path&lt;/strong&gt; using open-source and free-tier-friendly components.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;

&lt;p&gt;At a high level, the system looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Inbound trigger
Webhook / form / WhatsApp / API
        ↓
n8n
Workflow orchestration
        ↓
FastAPI middleware
AI processing + validation
        ↓
Groq / Llama 3
LLM intelligence layer
        ↓
PostgreSQL
Data layer
        ↓
Odoo 19 Community
CRM, accounting, inventory, HR
        ↓
Outbound action
WhatsApp reply / email / record update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The most important design decision is separation.&lt;/p&gt;

&lt;p&gt;n8n handles orchestration.&lt;/p&gt;

&lt;p&gt;FastAPI handles AI and validation.&lt;/p&gt;

&lt;p&gt;Odoo handles ERP records.&lt;/p&gt;

&lt;p&gt;PostgreSQL stores the data.&lt;/p&gt;

&lt;p&gt;WhatsApp handles communication.&lt;/p&gt;

&lt;p&gt;No single tool is forced to do everything.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why n8n Beats Zapier and Make for Technical Users
&lt;/h2&gt;

&lt;p&gt;Zapier and Make are excellent products.&lt;/p&gt;

&lt;p&gt;If you are non-technical and need something running quickly, they are useful.&lt;/p&gt;

&lt;p&gt;But for developers, agencies, and technical teams, self-hosted n8n gives more control.&lt;/p&gt;




&lt;h2&gt;
  
  
  Problem 1: Per-Execution Pricing Adds Up
&lt;/h2&gt;

&lt;p&gt;Zapier charges by tasks.&lt;/p&gt;

&lt;p&gt;Make charges by operations.&lt;/p&gt;

&lt;p&gt;That works for small flows.&lt;/p&gt;

&lt;p&gt;But once you start processing thousands of records, invoices, leads, or messages, pricing can grow quickly.&lt;/p&gt;

&lt;p&gt;Self-hosted n8n removes per-execution platform pricing.&lt;/p&gt;

&lt;p&gt;You still pay for server resources, API calls, and external services, but the workflow engine itself is under your control.&lt;/p&gt;




&lt;h2&gt;
  
  
  Problem 2: Error Handling Needs to Be First-Class
&lt;/h2&gt;

&lt;p&gt;In real workflows, things fail.&lt;/p&gt;

&lt;p&gt;APIs timeout.&lt;/p&gt;

&lt;p&gt;AI returns malformed JSON.&lt;/p&gt;

&lt;p&gt;A CRM rejects a payload.&lt;/p&gt;

&lt;p&gt;A webhook gets sent twice.&lt;/p&gt;

&lt;p&gt;A database write fails.&lt;/p&gt;

&lt;p&gt;A production workflow needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;retries&lt;/li&gt;
&lt;li&gt;validation&lt;/li&gt;
&lt;li&gt;logging&lt;/li&gt;
&lt;li&gt;duplicate prevention&lt;/li&gt;
&lt;li&gt;alerting&lt;/li&gt;
&lt;li&gt;fallback paths&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;n8n gives you enough flexibility to route failures into dedicated error workflows, log them, and notify the right person.&lt;/p&gt;

&lt;p&gt;That matters more than people think.&lt;/p&gt;




&lt;h2&gt;
  
  
  Problem 3: Your Data Flow Should Be Understandable
&lt;/h2&gt;

&lt;p&gt;In many automation stacks, the logic is spread across five tools.&lt;/p&gt;

&lt;p&gt;One part lives in Zapier.&lt;/p&gt;

&lt;p&gt;Another part lives in Make.&lt;/p&gt;

&lt;p&gt;Another part lives in Airtable.&lt;/p&gt;

&lt;p&gt;Another part lives inside the CRM.&lt;/p&gt;

&lt;p&gt;Another part lives in an AI prompt.&lt;/p&gt;

&lt;p&gt;When something breaks, debugging becomes painful.&lt;/p&gt;

&lt;p&gt;A self-hosted stack lets you keep the workflow, API layer, database, and ERP integration closer together.&lt;/p&gt;

&lt;p&gt;That makes the system easier to reason about.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why FastAPI Instead of Calling AI Directly from n8n
&lt;/h2&gt;

&lt;p&gt;The biggest mistake I see in AI automation stacks is this:&lt;/p&gt;

&lt;p&gt;Call an LLM directly from a workflow tool and write the raw response into a business system.&lt;/p&gt;

&lt;p&gt;That is dangerous.&lt;/p&gt;

&lt;p&gt;Example of what not to do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Dangerous pattern
&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;

&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The LLM can return anything.&lt;/p&gt;

&lt;p&gt;Wrong fields.&lt;/p&gt;

&lt;p&gt;Wrong format.&lt;/p&gt;

&lt;p&gt;Wrong amounts.&lt;/p&gt;

&lt;p&gt;Wrong dates.&lt;/p&gt;

&lt;p&gt;Invalid JSON.&lt;/p&gt;

&lt;p&gt;Hallucinated values.&lt;/p&gt;

&lt;p&gt;If that response goes directly into a CRM, ERP, or accounting system, you are asking for corrupted business data.&lt;/p&gt;

&lt;p&gt;So I added a FastAPI middleware layer between the workflow and the AI model.&lt;/p&gt;

&lt;p&gt;The middleware validates AI output before anything touches Odoo or PostgreSQL.&lt;/p&gt;




&lt;h2&gt;
  
  
  Pydantic Validation Layer
&lt;/h2&gt;

&lt;p&gt;Here is a simplified example using Pydantic v2:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Literal&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pydantic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Field&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LeadAnalysis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ge&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;le&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;next_action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Literal&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;low&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;medium&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;high&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InvoiceData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;vendor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;
    &lt;span class="n"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;line_items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the AI response does not match the schema, the middleware rejects it.&lt;/p&gt;

&lt;p&gt;That means bad data never reaches the ERP.&lt;/p&gt;




&lt;h2&gt;
  
  
  FastAPI Endpoint Example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Header&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pydantic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ValidationError&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="nd"&gt;@app.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/analyze/lead&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response_model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;LeadAnalysis&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;analyze_lead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lead&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x_api_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;(...)):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;x_api_key&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Invalid API key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;llama3-8b-8192&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Analyze this lead and respond only with valid JSON &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                    &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;matching this schema: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;LeadAnalysis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;model_json_schema&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;. &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                    &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Lead data: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;lead&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;response_format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;json_object&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;LeadAnalysis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;except &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSONDecodeError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ValidationError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;422&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the safety layer.&lt;/p&gt;

&lt;p&gt;n8n calls FastAPI.&lt;/p&gt;

&lt;p&gt;FastAPI calls the AI model.&lt;/p&gt;

&lt;p&gt;Pydantic validates the response.&lt;/p&gt;

&lt;p&gt;Only validated data is returned to the workflow.&lt;/p&gt;




&lt;h2&gt;
  
  
  Docker Compose Setup
&lt;/h2&gt;

&lt;p&gt;One Docker Compose file can run the core stack:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.8"&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:16&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${POSTGRES_DB}&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${POSTGRES_USER}&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${POSTGRES_PASSWORD}&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;postgres_data:/var/lib/postgresql/data&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;omni_net&lt;/span&gt;

  &lt;span class="na"&gt;odoo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;odoo:19&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;db&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;db&lt;/span&gt;
      &lt;span class="na"&gt;USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${POSTGRES_USER}&lt;/span&gt;
      &lt;span class="na"&gt;PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${POSTGRES_PASSWORD}&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;odoo_data:/var/lib/odoo&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./odoo/addons:/mnt/extra-addons&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./odoo/config/odoo.conf:/etc/odoo/odoo.conf&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;omni_net&lt;/span&gt;

  &lt;span class="na"&gt;ai-middleware&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./ai&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;GROQ_API_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${GROQ_API_KEY}&lt;/span&gt;
      &lt;span class="na"&gt;API_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${AI_API_KEY}&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;omni_net&lt;/span&gt;

  &lt;span class="na"&gt;n8n&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;n8nio/n8n&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;N8N_BASIC_AUTH_ACTIVE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;
      &lt;span class="na"&gt;N8N_BASIC_AUTH_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${N8N_BASIC_AUTH_USER}&lt;/span&gt;
      &lt;span class="na"&gt;N8N_BASIC_AUTH_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${N8N_BASIC_AUTH_PASSWORD}&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;n8n_data:/home/node/.n8n&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;omni_net&lt;/span&gt;

  &lt;span class="na"&gt;nginx&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx:alpine&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;80:80"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;443:443"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./nginx/nginx.conf:/etc/nginx/nginx.conf&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;odoo&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;n8n&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ai-middleware&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;omni_net&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;postgres_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;odoo_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;n8n_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;omni_net&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bridge&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Startup flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; .env.example .env

&lt;span class="c"&gt;# Fill in your environment variables&lt;/span&gt;

docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Four main services.&lt;/p&gt;

&lt;p&gt;One network.&lt;/p&gt;

&lt;p&gt;One command.&lt;/p&gt;




&lt;h2&gt;
  
  
  Workflow 1: Lead Intake
&lt;/h2&gt;

&lt;p&gt;This replaces a typical form + automation + CRM workflow.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WhatsApp message / web form submission
        ↓
n8n webhook trigger
        ↓
HTTP Request → POST /analyze/lead
        ↓
Validate AI response
        ↓
HTTP Request → POST /api/omni/lead
        ↓
Create Odoo CRM lead
        ↓
Send WhatsApp confirmation
        ↓
Log automation event
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Old pattern:&lt;/p&gt;

&lt;p&gt;Form tool → Zapier → AI API → HubSpot → notification&lt;/p&gt;

&lt;p&gt;New pattern:&lt;/p&gt;

&lt;p&gt;Webhook → n8n → FastAPI → Odoo → WhatsApp&lt;/p&gt;




&lt;h2&gt;
  
  
  Workflow 2: Invoice Processing
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Invoice text or payload arrives
        ↓
n8n webhook trigger
        ↓
HTTP Request → POST /extract/invoice
        ↓
Pydantic validation
        ↓
Create vendor bill in Odoo
        ↓
Send confirmation
        ↓
Log validation failures if needed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key point is not AI extraction.&lt;/p&gt;

&lt;p&gt;The key point is validated AI extraction.&lt;/p&gt;

&lt;p&gt;A malformed invoice should never become an accounting record.&lt;/p&gt;




&lt;h2&gt;
  
  
  Workflow 3: HR Onboarding
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;New employee form submitted
        ↓
n8n webhook trigger
        ↓
Create employee in Odoo HR
        ↓
Generate welcome message through FastAPI
        ↓
Send WhatsApp welcome message
        ↓
Notify HR manager
        ↓
Log onboarding event
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This shows that the same stack can support sales, finance, and HR workflows.&lt;/p&gt;




&lt;h2&gt;
  
  
  Error Handling Pattern
&lt;/h2&gt;

&lt;p&gt;The single biggest problem with many automation stacks is silent failure.&lt;/p&gt;

&lt;p&gt;A workflow fails.&lt;/p&gt;

&lt;p&gt;Nobody notices.&lt;/p&gt;

&lt;p&gt;Leads disappear.&lt;/p&gt;

&lt;p&gt;Invoices are not processed.&lt;/p&gt;

&lt;p&gt;Customers never get replies.&lt;/p&gt;

&lt;p&gt;Every serious workflow should have an error path.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Every important workflow step
        ↓
Success path → continue normally
        ↓
Error path → log failure
           → notify admin
           → stop workflow safely
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this stack, failures can be logged into Odoo using &lt;code&gt;omni.automation.log&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;They can also trigger WhatsApp or email alerts.&lt;/p&gt;

&lt;p&gt;That gives the business visibility into what failed and why.&lt;/p&gt;




&lt;h2&gt;
  
  
  Five Gotchas That Will Save You Hours
&lt;/h2&gt;

&lt;h2&gt;
  
  
  1. n8n's Odoo Node Is Not Enough for Every Case
&lt;/h2&gt;

&lt;p&gt;The built-in Odoo node is useful for standard operations.&lt;/p&gt;

&lt;p&gt;But for custom Odoo REST controllers, HTTP Request nodes are often better.&lt;/p&gt;

&lt;p&gt;They give you more control over:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;authentication&lt;/li&gt;
&lt;li&gt;headers&lt;/li&gt;
&lt;li&gt;custom endpoints&lt;/li&gt;
&lt;li&gt;error responses&lt;/li&gt;
&lt;li&gt;payload shape&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. Webhook Idempotency Is Not Optional
&lt;/h2&gt;

&lt;p&gt;Webhook providers may retry failed events.&lt;/p&gt;

&lt;p&gt;If you do not check for duplicate message IDs or event IDs, you can create duplicate records.&lt;/p&gt;

&lt;p&gt;For lead intake, that means duplicate CRM leads.&lt;/p&gt;

&lt;p&gt;For accounting, that could mean duplicate bills.&lt;/p&gt;

&lt;p&gt;Always store an external event ID and check it before creating new records.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. AI Rate Limits Need Workflow Design
&lt;/h2&gt;

&lt;p&gt;Free-tier AI APIs can have rate limits.&lt;/p&gt;

&lt;p&gt;Do not assume every request will succeed immediately.&lt;/p&gt;

&lt;p&gt;For high-volume workflows, add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;wait nodes&lt;/li&gt;
&lt;li&gt;retries&lt;/li&gt;
&lt;li&gt;backoff&lt;/li&gt;
&lt;li&gt;failure logging&lt;/li&gt;
&lt;li&gt;fallback behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rate limits should be treated as part of the architecture, not as an afterthought.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Odoo Filestore Persistence Is Easy to Miss
&lt;/h2&gt;

&lt;p&gt;Odoo stores attachments in its filestore.&lt;/p&gt;

&lt;p&gt;If you do not mount the filestore properly in Docker, files can disappear when containers are recreated.&lt;/p&gt;

&lt;p&gt;Use named volumes for persistence.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Docker Services Should Talk by Service Name
&lt;/h2&gt;

&lt;p&gt;Inside a Docker Compose network, services should not call each other using &lt;code&gt;localhost&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Use service names instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://odoo:8069
http://ai-middleware:8000
http://n8n:5678
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;localhost&lt;/code&gt; points to the current container, not another service.&lt;/p&gt;

&lt;p&gt;This causes many avoidable connection errors.&lt;/p&gt;




&lt;h2&gt;
  
  
  Before and After
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Monthly platform cost&lt;/td&gt;
&lt;td&gt;Around $300&lt;/td&gt;
&lt;td&gt;Designed for $0/month infrastructure path&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Services to maintain&lt;/td&gt;
&lt;td&gt;Many separate tools&lt;/td&gt;
&lt;td&gt;One Docker Compose stack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Workflow ownership&lt;/td&gt;
&lt;td&gt;Spread across vendors&lt;/td&gt;
&lt;td&gt;Self-hosted orchestration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Error visibility&lt;/td&gt;
&lt;td&gt;Often limited&lt;/td&gt;
&lt;td&gt;Central logs and alerts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data model&lt;/td&gt;
&lt;td&gt;Fragmented&lt;/td&gt;
&lt;td&gt;PostgreSQL + Odoo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI safety&lt;/td&gt;
&lt;td&gt;Raw responses&lt;/td&gt;
&lt;td&gt;Pydantic validation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vendor lock-in&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Lower&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Important note:&lt;/p&gt;

&lt;p&gt;This does not mean there are no external services.&lt;/p&gt;

&lt;p&gt;WhatsApp Cloud API and Groq are still external APIs.&lt;/p&gt;

&lt;p&gt;The difference is that the workflow engine, database, ERP, middleware, and deployment structure are controlled by you.&lt;/p&gt;




&lt;h2&gt;
  
  
  Full Repository
&lt;/h2&gt;

&lt;p&gt;Everything is open source and available here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/gharisj3/omni-odoo-stack" rel="noopener noreferrer"&gt;github.com/gharisj3/omni-odoo-stack&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The repo includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Docker Compose setup&lt;/li&gt;
&lt;li&gt;Odoo configuration&lt;/li&gt;
&lt;li&gt;Custom Odoo modules&lt;/li&gt;
&lt;li&gt;FastAPI middleware&lt;/li&gt;
&lt;li&gt;Pydantic v2 validators&lt;/li&gt;
&lt;li&gt;Importable n8n workflow JSON files&lt;/li&gt;
&lt;li&gt;Documentation&lt;/li&gt;
&lt;li&gt;Setup notes&lt;/li&gt;
&lt;li&gt;Architecture notes&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;The point of this project is not just to replace paid tools.&lt;/p&gt;

&lt;p&gt;The point is to show that business automation needs real backend architecture.&lt;/p&gt;

&lt;p&gt;A good automation stack needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;validation&lt;/li&gt;
&lt;li&gt;observability&lt;/li&gt;
&lt;li&gt;retry handling&lt;/li&gt;
&lt;li&gt;duplicate prevention&lt;/li&gt;
&lt;li&gt;API boundaries&lt;/li&gt;
&lt;li&gt;secure configuration&lt;/li&gt;
&lt;li&gt;persistent storage&lt;/li&gt;
&lt;li&gt;clean deployment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is what turns a demo workflow into something a business can actually rely on.&lt;/p&gt;




&lt;h2&gt;
  
  
  About Me
&lt;/h2&gt;

&lt;p&gt;I am a backend engineer specializing in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Odoo ERP customization&lt;/li&gt;
&lt;li&gt;n8n workflow automation&lt;/li&gt;
&lt;li&gt;Python backend systems&lt;/li&gt;
&lt;li&gt;FastAPI middleware&lt;/li&gt;
&lt;li&gt;PostgreSQL optimization&lt;/li&gt;
&lt;li&gt;WhatsApp Cloud API integration&lt;/li&gt;
&lt;li&gt;AI middleware with structured output validation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have 8+ years of production experience across Odoo, Python, backend automation, and ERP integrations.&lt;/p&gt;

&lt;p&gt;I am open to remote contract work involving Odoo modules, n8n automation, AI middleware, PostgreSQL optimization, and backend integrations.&lt;/p&gt;

&lt;p&gt;GitHub:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/gharisj3" rel="noopener noreferrer"&gt;github.com/gharisj3&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;LinkedIn:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/muhammad-gharis-javed-318266202/" rel="noopener noreferrer"&gt;linkedin.com/in/muhammad-gharis-javed-318266202&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Project repo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/gharisj3/omni-odoo-stack" rel="noopener noreferrer"&gt;github.com/gharisj3/omni-odoo-stack&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>n8nbrightdatachallenge</category>
      <category>docker</category>
      <category>opensource</category>
    </item>
    <item>
      <title>How I Built a Production-Grade Odoo 19 + n8n + WhatsApp + Groq AI Stack on $0 Infrastructure</title>
      <dc:creator>Muhammad Gharis</dc:creator>
      <pubDate>Wed, 10 Jun 2026 20:43:03 +0000</pubDate>
      <link>https://dev.to/muhammad_gharis_fe079470a/how-i-built-a-production-grade-odoo-19-n8n-whatsapp-groq-ai-stack-on-0-infrastructure-8kd</link>
      <guid>https://dev.to/muhammad_gharis_fe079470a/how-i-built-a-production-grade-odoo-19-n8n-whatsapp-groq-ai-stack-on-0-infrastructure-8kd</guid>
      <description>&lt;p&gt;If you've ever tried to connect an ERP system to real-time messaging, AI processing, and workflow automation at the same time, you know how quickly the architecture can become messy.&lt;/p&gt;

&lt;p&gt;If you've ever tried to connect an ERP system to real-time messaging, AI processing, and workflow automation at the same time, you know how quickly the architecture can become messy.&lt;/p&gt;

&lt;p&gt;You need an ERP.&lt;/p&gt;

&lt;p&gt;You need automation.&lt;/p&gt;

&lt;p&gt;You need message intake.&lt;/p&gt;

&lt;p&gt;You need AI processing.&lt;/p&gt;

&lt;p&gt;You need validation.&lt;/p&gt;

&lt;p&gt;You need logs.&lt;/p&gt;

&lt;p&gt;You need deployment.&lt;/p&gt;

&lt;p&gt;And very quickly, what started as “just connect WhatsApp to Odoo” becomes a full backend system.&lt;/p&gt;

&lt;p&gt;I built &lt;strong&gt;omni-odoo-stack&lt;/strong&gt; to explore that exact problem.&lt;/p&gt;

&lt;p&gt;It is an open-source ERP automation stack built around:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Odoo 19 Community&lt;/li&gt;
&lt;li&gt;PostgreSQL 16&lt;/li&gt;
&lt;li&gt;n8n&lt;/li&gt;
&lt;li&gt;FastAPI&lt;/li&gt;
&lt;li&gt;Groq / Llama 3&lt;/li&gt;
&lt;li&gt;WhatsApp Cloud API&lt;/li&gt;
&lt;li&gt;Docker Compose&lt;/li&gt;
&lt;li&gt;Nginx&lt;/li&gt;
&lt;li&gt;Oracle OCI Always Free deployment path&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal was simple:&lt;/p&gt;

&lt;p&gt;Build a realistic &lt;strong&gt;ERP + automation + AI middleware&lt;/strong&gt; architecture using open-source or free-tier-friendly tools.&lt;/p&gt;

&lt;p&gt;Repository:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/gharisj3/omni-odoo-stack" rel="noopener noreferrer"&gt;github.com/gharisj3/omni-odoo-stack&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What the Stack Does
&lt;/h2&gt;

&lt;p&gt;At a high level, the system connects five layers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WhatsApp Cloud API
        ↓
n8n workflow orchestration
        ↓
FastAPI + Groq AI middleware
        ↓
Odoo 19 Community
        ↓
PostgreSQL 16
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a WhatsApp message arrives, n8n receives the webhook, extracts the payload, sends the data to FastAPI for AI-assisted analysis, validates the structured response using Pydantic v2, and writes a clean CRM lead into Odoo.&lt;/p&gt;

&lt;p&gt;The sender can then receive an automated WhatsApp confirmation.&lt;/p&gt;

&lt;p&gt;The important part is not just that the flow works conceptually.&lt;/p&gt;

&lt;p&gt;The important part is the separation of responsibilities.&lt;/p&gt;

&lt;p&gt;Odoo remains the ERP core.&lt;/p&gt;

&lt;p&gt;n8n handles workflow orchestration.&lt;/p&gt;

&lt;p&gt;FastAPI acts as the AI safety boundary.&lt;/p&gt;

&lt;p&gt;PostgreSQL stores the business data.&lt;/p&gt;

&lt;p&gt;WhatsApp handles the communication layer.&lt;/p&gt;




&lt;h2&gt;
  
  
  Infrastructure Stack
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ERP&lt;/td&gt;
&lt;td&gt;Odoo 19 Community&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database&lt;/td&gt;
&lt;td&gt;PostgreSQL 16&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Automation&lt;/td&gt;
&lt;td&gt;n8n self-hosted&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI middleware&lt;/td&gt;
&lt;td&gt;FastAPI&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LLM provider&lt;/td&gt;
&lt;td&gt;Groq / Llama 3&lt;/td&gt;
&lt;td&gt;Free-tier friendly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Messaging&lt;/td&gt;
&lt;td&gt;Meta WhatsApp Cloud API&lt;/td&gt;
&lt;td&gt;Free-tier friendly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reverse proxy&lt;/td&gt;
&lt;td&gt;Nginx&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deployment&lt;/td&gt;
&lt;td&gt;Docker Compose&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hosting target&lt;/td&gt;
&lt;td&gt;Oracle OCI Always Free&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSL&lt;/td&gt;
&lt;td&gt;Let's Encrypt&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Oracle OCI Always Free is useful for this kind of project because the ARM instance can provide enough resources for a small ERP automation stack without needing a paid VPS.&lt;/p&gt;

&lt;p&gt;The repo is designed with OCI deployment in mind, but I am being careful with wording here:&lt;/p&gt;

&lt;p&gt;This is a &lt;strong&gt;production-style portfolio architecture&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It is not yet being claimed as a fully production-deployed system until the full Docker runtime has been boot-tested on OCI.&lt;/p&gt;

&lt;p&gt;That distinction matters.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Four Custom Odoo Modules
&lt;/h2&gt;

&lt;p&gt;I built four custom Odoo modules from scratch. Each module handles a different part of the system.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. omni_crm
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;omni_crm&lt;/code&gt; extends &lt;code&gt;crm.lead&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It adds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Computed lead scoring&lt;/li&gt;
&lt;li&gt;AI analysis fields&lt;/li&gt;
&lt;li&gt;WhatsApp contact shortcut behavior&lt;/li&gt;
&lt;li&gt;Public lead intake API&lt;/li&gt;
&lt;li&gt;Demo CRM lead data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST /api/omni/lead
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This endpoint allows external systems like n8n to create leads in Odoo through a clean REST-style controller instead of forcing all automation through manual imports or UI actions.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. omni_whatsapp
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;omni_whatsapp&lt;/code&gt; introduces a new model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;omni.whatsapp.message
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It stores WhatsApp message activity inside Odoo.&lt;/p&gt;

&lt;p&gt;Fields include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Phone number&lt;/li&gt;
&lt;li&gt;Message body&lt;/li&gt;
&lt;li&gt;Direction: inbound or outbound&lt;/li&gt;
&lt;li&gt;Status&lt;/li&gt;
&lt;li&gt;Linked CRM lead&lt;/li&gt;
&lt;li&gt;Message history&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It also includes webhook endpoints for Meta WhatsApp Cloud API integration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET  /whatsapp/webhook
POST /whatsapp/webhook
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The GET endpoint is used for Meta webhook verification.&lt;/p&gt;

&lt;p&gt;The POST endpoint receives inbound WhatsApp events.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. omni_ai
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;omni_ai&lt;/code&gt; introduces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;omni.ai.request
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This module logs AI requests and responses.&lt;/p&gt;

&lt;p&gt;It stores:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prompt&lt;/li&gt;
&lt;li&gt;Response&lt;/li&gt;
&lt;li&gt;Model used&lt;/li&gt;
&lt;li&gt;Token usage&lt;/li&gt;
&lt;li&gt;Status&lt;/li&gt;
&lt;li&gt;Timestamp&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It also includes an hourly cron job to process unanalyzed leads.&lt;/p&gt;

&lt;p&gt;The idea is simple:&lt;/p&gt;

&lt;p&gt;Do not let AI calls disappear into the background.&lt;/p&gt;

&lt;p&gt;Every AI action should be visible, inspectable, and traceable inside the ERP.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. omni_automation
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;omni_automation&lt;/code&gt; introduces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;omni.automation.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This module tracks end-to-end automation events.&lt;/p&gt;

&lt;p&gt;It can be used to monitor:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;WhatsApp intake&lt;/li&gt;
&lt;li&gt;CRM lead creation&lt;/li&gt;
&lt;li&gt;AI processing&lt;/li&gt;
&lt;li&gt;Vendor bill automation&lt;/li&gt;
&lt;li&gt;HR onboarding automation&lt;/li&gt;
&lt;li&gt;Failed workflow events&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It includes tree, form, and graph views so the automation layer is visible inside Odoo.&lt;/p&gt;

&lt;p&gt;That visibility is important.&lt;/p&gt;

&lt;p&gt;Automation without logs becomes a black box.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why the AI Middleware Lives Outside Odoo
&lt;/h2&gt;

&lt;p&gt;This was the most important architectural decision in the project.&lt;/p&gt;

&lt;p&gt;A lot of AI-connected ERP implementations put LLM calls directly inside ERP models or controllers.&lt;/p&gt;

&lt;p&gt;That works for demos, but it creates problems later.&lt;/p&gt;

&lt;p&gt;Problems include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prompts become tightly coupled to Odoo modules&lt;/li&gt;
&lt;li&gt;Model changes require ERP code changes&lt;/li&gt;
&lt;li&gt;Raw LLM responses can accidentally corrupt ERP records&lt;/li&gt;
&lt;li&gt;Validation becomes inconsistent&lt;/li&gt;
&lt;li&gt;Token usage is harder to track&lt;/li&gt;
&lt;li&gt;Swapping models becomes harder than necessary&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I separated the AI layer into a standalone FastAPI service.&lt;/p&gt;

&lt;p&gt;Odoo does not talk directly to the model.&lt;/p&gt;

&lt;p&gt;n8n and Odoo communicate with the middleware.&lt;/p&gt;

&lt;p&gt;The middleware validates input, calls the LLM, validates output, and only then returns structured data.&lt;/p&gt;

&lt;p&gt;Example Pydantic v2 model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Literal&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pydantic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Field&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LeadAnalysis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ge&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;le&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;next_action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Literal&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;low&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;medium&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;high&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example invoice extraction model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pydantic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseModel&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LineItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;
    &lt;span class="n"&gt;unit_price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;
    &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InvoiceData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;vendor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;
    &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;
    &lt;span class="n"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;line_items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;LineItem&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every AI response must match the expected schema before it reaches Odoo.&lt;/p&gt;

&lt;p&gt;If the response is missing a field, has the wrong type, or produces an invalid value, the middleware returns an error and the workflow can log the failure.&lt;/p&gt;

&lt;p&gt;Odoo never receives unsafe data.&lt;/p&gt;

&lt;p&gt;That is the entire point of the middleware.&lt;/p&gt;




&lt;h2&gt;
  
  
  FastAPI Middleware Endpoints
&lt;/h2&gt;

&lt;p&gt;The middleware exposes these endpoints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET  /health
POST /analyze/lead
POST /extract/invoice
POST /generate/message
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;n8n receives WhatsApp webhook
        ↓
n8n sends payload to FastAPI
        ↓
FastAPI calls Groq / Llama 3
        ↓
Pydantic validates structured output
        ↓
n8n writes validated data into Odoo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The middleware is also easier to evolve independently.&lt;/p&gt;

&lt;p&gt;If I want to replace Groq with OpenAI, Claude, or another model provider, I can change the middleware layer without rewriting Odoo modules.&lt;/p&gt;

&lt;p&gt;That is the benefit of keeping AI outside the ERP core.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Three n8n Workflows
&lt;/h2&gt;

&lt;p&gt;The repo includes three importable n8n workflow JSON files.&lt;/p&gt;




&lt;h2&gt;
  
  
  Workflow 1: WhatsApp Lead Intake
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Meta WhatsApp webhook
        ↓
Extract contact and message data
        ↓
Call FastAPI /analyze/lead
        ↓
Validate AI response
        ↓
Create CRM lead in Odoo
        ↓
Send WhatsApp confirmation
        ↓
Log automation event
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This workflow is designed for businesses that receive leads through WhatsApp and want automatic CRM creation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Workflow 2: Invoice Processing
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Invoice payload or WhatsApp invoice text
        ↓
Call FastAPI /extract/invoice
        ↓
Validate structured invoice data
        ↓
Create vendor bill in Odoo
        ↓
Send confirmation
        ↓
Log validation failures if needed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This flow demonstrates how AI extraction can be placed behind validation before data enters accounting workflows.&lt;/p&gt;




&lt;h2&gt;
  
  
  Workflow 3: HR Onboarding
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Employee onboarding form
        ↓
Create employee in Odoo
        ↓
Generate welcome message through AI middleware
        ↓
Send WhatsApp notification to employee
        ↓
Notify HR manager
        ↓
Log onboarding event
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This workflow demonstrates how the same architecture can support HR automation, not just sales or finance.&lt;/p&gt;




&lt;h2&gt;
  
  
  Five Things I Learned While Building This
&lt;/h2&gt;

&lt;h2&gt;
  
  
  1. n8n's Odoo Node Is Not Enough for Every Case
&lt;/h2&gt;

&lt;p&gt;The built-in Odoo node in n8n is useful, but custom Odoo REST controllers often require HTTP Request nodes.&lt;/p&gt;

&lt;p&gt;For custom endpoints, the practical pattern is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Authenticate with Odoo
Store session/cookie
Call custom REST endpoint
Handle response
Log errors
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For complex projects, I prefer explicit HTTP Request nodes because they make the flow easier to debug.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. WhatsApp Webhook Idempotency Matters
&lt;/h2&gt;

&lt;p&gt;Messaging systems can resend webhook events.&lt;/p&gt;

&lt;p&gt;If your workflow creates a CRM lead every time it receives the same message, you can end up with duplicate leads.&lt;/p&gt;

&lt;p&gt;The fix is to store and check a unique message identifier before creating records.&lt;/p&gt;

&lt;p&gt;In real projects, I would always design the WhatsApp intake layer with duplicate prevention.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Pydantic v2 Requires Correct Syntax
&lt;/h2&gt;

&lt;p&gt;Pydantic v2 introduced changes from v1.&lt;/p&gt;

&lt;p&gt;If you are using it for AI output validation, make sure your models and validators follow v2 syntax.&lt;/p&gt;

&lt;p&gt;The goal is not just to parse JSON.&lt;/p&gt;

&lt;p&gt;The goal is to reject unsafe or malformed output before it touches business systems.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Odoo Filestore Persistence Is Easy to Miss
&lt;/h2&gt;

&lt;p&gt;Odoo stores attachments in the filestore.&lt;/p&gt;

&lt;p&gt;If the filestore is not mounted properly in Docker, attachments can disappear when containers are recreated.&lt;/p&gt;

&lt;p&gt;For an ERP system, that is not acceptable.&lt;/p&gt;

&lt;p&gt;Docker volumes need to be planned carefully.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Docker Services Should Talk by Service Name
&lt;/h2&gt;

&lt;p&gt;Inside a Docker Compose network, services should not call each other using &lt;code&gt;localhost&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Wrong:
http://localhost:8069

Correct:
http://odoo:8069
http://ai-middleware:8000
http://n8n:5678
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This sounds basic, but it is one of the most common causes of connection errors when wiring multiple services together.&lt;/p&gt;




&lt;h2&gt;
  
  
  Nginx Routing
&lt;/h2&gt;

&lt;p&gt;The stack uses Nginx as the reverse proxy.&lt;/p&gt;

&lt;p&gt;The intended routing is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/       → Odoo
/n8n/   → n8n
/ai/    → FastAPI middleware
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example configuration pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://odoo:8069&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/n8n/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://n8n:5678/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;rewrite&lt;/span&gt; &lt;span class="s"&gt;^/n8n/(.*)&lt;/span&gt;$ &lt;span class="n"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="s"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/ai/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://ai-middleware:8000/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;rewrite&lt;/span&gt; &lt;span class="s"&gt;^/ai/(.*)&lt;/span&gt;$ &lt;span class="n"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="s"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rewrite rules matter because services like n8n and FastAPI may not expect the external prefix in the request path.&lt;/p&gt;




&lt;h2&gt;
  
  
  About Groq and Rate Limits
&lt;/h2&gt;

&lt;p&gt;The project is designed to work with Groq and Llama 3-style structured AI tasks.&lt;/p&gt;

&lt;p&gt;For real deployments, rate limits should always be checked from the current provider dashboard because limits can change.&lt;/p&gt;

&lt;p&gt;In production-style workflows, I would add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Wait nodes in n8n&lt;/li&gt;
&lt;li&gt;Retry logic&lt;/li&gt;
&lt;li&gt;Backoff handling&lt;/li&gt;
&lt;li&gt;Token usage logging&lt;/li&gt;
&lt;li&gt;Fallback behavior&lt;/li&gt;
&lt;li&gt;Dead-letter logging for failed events&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is not just to call an AI model.&lt;/p&gt;

&lt;p&gt;The goal is to make the AI call reliable enough for business workflows.&lt;/p&gt;




&lt;h2&gt;
  
  
  Repository Contents
&lt;/h2&gt;

&lt;p&gt;The repository includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Docker Compose setup&lt;/li&gt;
&lt;li&gt;Odoo configuration&lt;/li&gt;
&lt;li&gt;Nginx configuration&lt;/li&gt;
&lt;li&gt;Four custom Odoo modules&lt;/li&gt;
&lt;li&gt;FastAPI AI middleware&lt;/li&gt;
&lt;li&gt;Three importable n8n workflows&lt;/li&gt;
&lt;li&gt;Environment example file&lt;/li&gt;
&lt;li&gt;README&lt;/li&gt;
&lt;li&gt;Setup documentation&lt;/li&gt;
&lt;li&gt;Architecture notes&lt;/li&gt;
&lt;li&gt;Phase notes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Repository:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/gharisj3/omni-odoo-stack" rel="noopener noreferrer"&gt;github.com/gharisj3/omni-odoo-stack&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Would Do Differently
&lt;/h2&gt;

&lt;p&gt;One thing I would change is boot-testing the full Docker stack before publishing the first public version.&lt;/p&gt;

&lt;p&gt;The project has been scaffolded, committed, documented, and syntax-checked.&lt;/p&gt;

&lt;p&gt;Python syntax, JSON workflow files, and XML structure were reviewed.&lt;/p&gt;

&lt;p&gt;But full runtime verification on OCI is still pending.&lt;/p&gt;

&lt;p&gt;That is why I describe this as a &lt;strong&gt;production-style architecture&lt;/strong&gt; rather than claiming it is already production-deployed.&lt;/p&gt;

&lt;p&gt;That wording matters.&lt;/p&gt;

&lt;p&gt;If you deploy it and hit issues, open an issue on GitHub. I am happy to improve the repo based on real runtime feedback.&lt;/p&gt;




&lt;h2&gt;
  
  
  Who This Is For
&lt;/h2&gt;

&lt;p&gt;This project is useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Odoo developers learning external automation patterns&lt;/li&gt;
&lt;li&gt;n8n users integrating workflows with Odoo&lt;/li&gt;
&lt;li&gt;Backend engineers exploring ERP automation&lt;/li&gt;
&lt;li&gt;Odoo partners evaluating AI middleware architecture&lt;/li&gt;
&lt;li&gt;Agencies that need WhatsApp + ERP workflow examples&lt;/li&gt;
&lt;li&gt;Developers looking for a free-tier-friendly ERP automation stack&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;Most ERP automation problems are not just workflow problems.&lt;/p&gt;

&lt;p&gt;They are backend reliability problems.&lt;/p&gt;

&lt;p&gt;You need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clean data models&lt;/li&gt;
&lt;li&gt;Safe API boundaries&lt;/li&gt;
&lt;li&gt;Structured validation&lt;/li&gt;
&lt;li&gt;Retry handling&lt;/li&gt;
&lt;li&gt;Duplicate prevention&lt;/li&gt;
&lt;li&gt;Event logs&lt;/li&gt;
&lt;li&gt;Database persistence&lt;/li&gt;
&lt;li&gt;Deployment clarity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is what this project is meant to demonstrate.&lt;/p&gt;

&lt;p&gt;Not just that Odoo can connect to AI.&lt;/p&gt;

&lt;p&gt;But that AI, automation, messaging, and ERP can be designed as separate layers that work together cleanly.&lt;/p&gt;




&lt;h2&gt;
  
  
  About Me
&lt;/h2&gt;

&lt;p&gt;I am a backend engineer specializing in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Odoo ERP customization&lt;/li&gt;
&lt;li&gt;Python backend systems&lt;/li&gt;
&lt;li&gt;n8n workflow automation&lt;/li&gt;
&lt;li&gt;PostgreSQL optimization&lt;/li&gt;
&lt;li&gt;WhatsApp Cloud API integration&lt;/li&gt;
&lt;li&gt;Claude/OpenAI/Groq AI middleware&lt;/li&gt;
&lt;li&gt;Pydantic-validated structured outputs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have 8+ years of production experience across Odoo v14–v19 and backend automation work.&lt;/p&gt;

&lt;p&gt;I am open to remote contract work with Odoo partners, SaaS teams, and agencies.&lt;/p&gt;

&lt;p&gt;GitHub:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/gharisj3" rel="noopener noreferrer"&gt;github.com/gharisj3&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;LinkedIn:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/muhammad-gharis-javed-318266202/" rel="noopener noreferrer"&gt;linkedin.com/in/muhammad-gharis-javed-318266202&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Project repo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/gharisj3/omni-odoo-stack" rel="noopener noreferrer"&gt;github.com/gharisj3/omni-odoo-stack&lt;/a&gt;&lt;/p&gt;

</description>
      <category>odoo</category>
      <category>python</category>
      <category>n8nbrightdatachallenge</category>
      <category>docker</category>
    </item>
    <item>
      <title>Anti-Subscription Stack</title>
      <dc:creator>Muhammad Gharis</dc:creator>
      <pubDate>Mon, 08 Jun 2026 10:39:38 +0000</pubDate>
      <link>https://dev.to/muhammad_gharis_fe079470a/anti-subscription-stack-38dn</link>
      <guid>https://dev.to/muhammad_gharis_fe079470a/anti-subscription-stack-38dn</guid>
      <description>&lt;p&gt;Most small businesses do not need another monthly SaaS subscription.&lt;/p&gt;

&lt;p&gt;They need simple software that helps them run daily operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Save customer records&lt;/li&gt;
&lt;li&gt;Track leads&lt;/li&gt;
&lt;li&gt;Create invoices&lt;/li&gt;
&lt;li&gt;Manage inventory&lt;/li&gt;
&lt;li&gt;View sales reports&lt;/li&gt;
&lt;li&gt;Export data when needed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is it.&lt;/p&gt;

&lt;p&gt;But somehow, even basic business tools have turned into complicated subscription products with multiple pricing tiers, feature gates, usage limits, and dashboards that small teams never fully use.&lt;/p&gt;

&lt;p&gt;This is why I think there is still a strong place for lightweight, self-hosted tools.&lt;/p&gt;

&lt;p&gt;Especially tools built with simple stacks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Core PHP
MySQL
HTML
CSS
JavaScript
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No heavy framework.&lt;br&gt;&lt;br&gt;
No paid API.&lt;br&gt;&lt;br&gt;
No complex deployment.&lt;br&gt;&lt;br&gt;
No monthly platform dependency.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Problem With Overbuilt Business Software
&lt;/h2&gt;

&lt;p&gt;A small shop, freelancer, salon, repair center, consultant, or local agency usually does not need enterprise software.&lt;/p&gt;

&lt;p&gt;They need something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Clients
Products
Invoices
Payments
Tasks
Reports
Users
Settings
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But many modern tools are built as if every customer is a funded startup with a large operations team.&lt;/p&gt;

&lt;p&gt;The result?&lt;/p&gt;

&lt;p&gt;Small businesses often end up with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Too many features&lt;/li&gt;
&lt;li&gt;Too many screens&lt;/li&gt;
&lt;li&gt;Too many monthly fees&lt;/li&gt;
&lt;li&gt;Too much onboarding&lt;/li&gt;
&lt;li&gt;Too much vendor lock-in&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For basic workflows, this is unnecessary.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Self-Hosted Still Matters
&lt;/h2&gt;

&lt;p&gt;Self-hosted software is not dead.&lt;/p&gt;

&lt;p&gt;For many use cases, it is actually practical.&lt;/p&gt;

&lt;p&gt;A small business owner or freelancer may prefer self-hosted tools because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They pay once instead of monthly&lt;/li&gt;
&lt;li&gt;They can keep their own database&lt;/li&gt;
&lt;li&gt;They can customize the system&lt;/li&gt;
&lt;li&gt;They can host it on basic shared hosting&lt;/li&gt;
&lt;li&gt;They are not locked into one vendor&lt;/li&gt;
&lt;li&gt;They can hire any PHP developer to modify it later&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is especially useful for small internal systems.&lt;/p&gt;

&lt;p&gt;A CRM, POS, HRM, invoice system, or reporting dashboard does not always need to be a full SaaS platform.&lt;/p&gt;

&lt;p&gt;Sometimes a simple admin panel is enough.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I Still Like Core PHP for These Tools
&lt;/h2&gt;

&lt;p&gt;Core PHP gets criticized a lot.&lt;/p&gt;

&lt;p&gt;Sometimes fairly.&lt;/p&gt;

&lt;p&gt;But for small business tools, it still has advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Runs almost everywhere&lt;/li&gt;
&lt;li&gt;Easy deployment&lt;/li&gt;
&lt;li&gt;Low hosting requirements&lt;/li&gt;
&lt;li&gt;Easy for junior developers to understand&lt;/li&gt;
&lt;li&gt;No complicated build step&lt;/li&gt;
&lt;li&gt;No framework upgrade pressure&lt;/li&gt;
&lt;li&gt;Great for CRUD-heavy systems&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A clean Core PHP project can still be professional if it uses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PDO&lt;/li&gt;
&lt;li&gt;Prepared statements&lt;/li&gt;
&lt;li&gt;Proper validation&lt;/li&gt;
&lt;li&gt;Session security&lt;/li&gt;
&lt;li&gt;Organized folders&lt;/li&gt;
&lt;li&gt;Reusable components&lt;/li&gt;
&lt;li&gt;Clear documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bad PHP is bad.&lt;/p&gt;

&lt;p&gt;But simple PHP is not automatically bad.&lt;/p&gt;




&lt;h2&gt;
  
  
  Example: A Lightweight CRM Structure
&lt;/h2&gt;

&lt;p&gt;A simple CRM does not need to start huge.&lt;/p&gt;

&lt;p&gt;It can begin with this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;crm/
  config/
    database.php

  modules/
    clients/
    leads/
    tasks/
    invoices/

  public/
    index.php
    assets/

  database/
    install.sql

  docs/
    installation.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is enough for a clean first version.&lt;/p&gt;

&lt;p&gt;You can add complexity later only when the business actually needs it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Most Useful Modules for Small Businesses
&lt;/h2&gt;

&lt;p&gt;If I were building a lightweight business toolkit, I would start with these modules.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Client Management
&lt;/h3&gt;

&lt;p&gt;Store customer details, contact info, notes, and status.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Lead Pipeline
&lt;/h3&gt;

&lt;p&gt;Track potential deals from new lead to won or lost.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Invoice Generator
&lt;/h3&gt;

&lt;p&gt;Create simple invoices with printable HTML templates.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Inventory Tracking
&lt;/h3&gt;

&lt;p&gt;Useful for shops, repair centers, and small product sellers.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Task Management
&lt;/h3&gt;

&lt;p&gt;Assign daily work and track progress.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Reports
&lt;/h3&gt;

&lt;p&gt;Show monthly sales, pending invoices, top clients, and stock alerts.&lt;/p&gt;

&lt;p&gt;Nothing fancy.&lt;/p&gt;

&lt;p&gt;Just useful.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Real Opportunity for Developers
&lt;/h2&gt;

&lt;p&gt;Many developers are chasing big SaaS ideas.&lt;/p&gt;

&lt;p&gt;But there is a quieter opportunity:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Build small, reliable tools that solve boring business problems.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Boring problems pay because businesses already understand them.&lt;/p&gt;

&lt;p&gt;A shop owner does not need to be educated about inventory.&lt;/p&gt;

&lt;p&gt;An agency owner does not need to be convinced about invoices.&lt;/p&gt;

&lt;p&gt;A freelancer already understands client tracking.&lt;/p&gt;

&lt;p&gt;The problem is obvious.&lt;/p&gt;

&lt;p&gt;The solution just needs to be simple and affordable.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Am Building
&lt;/h2&gt;

&lt;p&gt;I am working on a lightweight Core PHP business toolkit starting with a CRM starter system.&lt;/p&gt;

&lt;p&gt;The goal is to make it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple to install&lt;/li&gt;
&lt;li&gt;Easy to customize&lt;/li&gt;
&lt;li&gt;Cleanly structured&lt;/li&gt;
&lt;li&gt;Useful for real business workflows&lt;/li&gt;
&lt;li&gt;Suitable for freelancers and small agencies&lt;/li&gt;
&lt;li&gt;Free from heavy framework dependency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I am starting small with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Clients
Leads
Tasks
Invoices
Dashboard
Reports
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I plan to expand into POS, HRM, and automation modules.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;Not every business tool needs to become a huge SaaS.&lt;/p&gt;

&lt;p&gt;Sometimes the better product is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Smaller&lt;/li&gt;
&lt;li&gt;Faster&lt;/li&gt;
&lt;li&gt;Self-hosted&lt;/li&gt;
&lt;li&gt;Easier to understand&lt;/li&gt;
&lt;li&gt;Easier to modify&lt;/li&gt;
&lt;li&gt;Cheaper to maintain&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is the kind of software I want to build more of.&lt;/p&gt;

&lt;p&gt;If you are a developer, freelancer, or small business owner:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Would you rather use a simple self-hosted tool or pay monthly for a SaaS product with more features than you need?&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>php</category>
      <category>webdev</category>
      <category>saas</category>
      <category>business</category>
    </item>
  </channel>
</rss>
