Home Blog Reviews Best Picks Guides Tools Glossary Advertise Subscribe Free
Tech Frontline Jun 28, 2026 7 min read

Adding Human-in-the-Loop Approval to Automated Workflows: 2026’s Blueprint

Learn how to inject human oversight into AI-driven approval workflows for maximum compliance, control, and transparency.

T
Tech Daily Shot Team
Published Jun 28, 2026
Adding Human-in-the-Loop Approval to Automated Workflows: 2026’s Blueprint

As AI-powered automation takes center stage in modern business processes, ensuring responsible oversight is more critical than ever. Human-in-the-loop (HITL) approval mechanisms allow organizations to combine the speed of automation with the judgment and compliance of human reviewers. In this tutorial, we’ll walk you through a practical, reproducible approach to embedding HITL approval into your automated workflows using state-of-the-art tools and best practices for 2026.

For a broader context on this topic and how it fits into the evolution of workflow automation, see our Ultimate Guide to Automating Approval Workflows with AI in 2026. Here, we’ll focus on the nuts and bolts of implementing human-in-the-loop AI workflows, providing hands-on steps, code, and troubleshooting tips.

Prerequisites

1. Define Your Approval Workflow and HITL Requirements

  1. Map the Workflow:
    • Identify the process you want to automate (e.g., expense approvals, procurement, onboarding).
    • Determine which decision points require human oversight (e.g., amounts over $5,000, ambiguous LLM outputs, regulatory triggers).
  2. Specify HITL Triggers:
    • When should the workflow pause for human review?
    • What data should be presented to the reviewer?
    • What actions can the reviewer take (approve, reject, request more info)?
  3. Document Requirements:
    • Write a simple specification, e.g.:
    Expense approval workflow:
    - LLM auto-approves expenses < $1,000
    - HITL required for $1,000–$10,000 or if LLM confidence < 95%
    - Human reviewer receives request in Slack, can Approve/Reject/Comment
    - All decisions logged to PostgreSQL
    

For inspiration, review How to Automate Workflow Approval Loops with Custom AI Agents (Step-by-Step, 2026), which covers agent-based approaches to workflow automation.

2. Set Up Your Development Environment

  1. Create a Python Virtual Environment:
    python3 -m venv hitl-env
    source hitl-env/bin/activate
    
  2. Install Required Packages:
    pip install fastapi uvicorn celery[redis] psycopg2-binary slack_sdk openai pydantic sqlalchemy python-dotenv
    
  3. Start Redis and PostgreSQL:
    • Install Redis and PostgreSQL via your OS package manager if not already present.
    
    redis-server
    
    brew services start postgresql
    
  4. Configure Environment Variables:
    • Create a .env file in your project root with:
    OPENAI_API_KEY=sk-...
    SLACK_BOT_TOKEN=xoxb-...
    SLACK_SIGNING_SECRET=...
    DATABASE_URL=postgresql://user:password@localhost:5432/hitl_demo
    

3. Build the Core Workflow Automation with FastAPI and Celery

  1. Set Up the FastAPI App:
    • Create main.py:
    
    from fastapi import FastAPI, Request
    from pydantic import BaseModel
    from celery import Celery
    import os
    
    app = FastAPI()
    celery_app = Celery("tasks", broker="redis://localhost:6379/0")
    
    class ExpenseRequest(BaseModel):
        employee: str
        amount: float
        description: str
    
    @app.post("/submit-expense/")
    async def submit_expense(expense: ExpenseRequest):
        task = celery_app.send_task("tasks.process_expense", args=[expense.dict()])
        return {"task_id": task.id, "status": "submitted"}
    
  2. Define the Celery Task (AI + HITL Logic):
    • Create tasks.py:
    
    from celery import Celery
    import openai
    import os
    from slack_sdk import WebClient
    
    celery_app = Celery("tasks", broker="redis://localhost:6379/0")
    openai.api_key = os.getenv("OPENAI_API_KEY")
    slack_client = WebClient(token=os.getenv("SLACK_BOT_TOKEN"))
    
    def ai_decision(expense):
        prompt = (f"Should the following expense be approved? "
                  f"Amount: ${expense['amount']}, Description: {expense['description']}")
        response = openai.ChatCompletion.create(
            model="gpt-4",
            messages=[{"role": "user", "content": prompt}],
            temperature=0.2
        )
        answer = response["choices"][0]["message"]["content"]
        confidence = 0.98  # Simulated; parse from answer if your LLM supports confidence
        return answer, confidence
    
    @celery_app.task(name="tasks.process_expense")
    def process_expense(expense):
        answer, confidence = ai_decision(expense)
        if expense["amount"] < 1000 and confidence > 0.95 and "approve" in answer.lower():
            # Auto-approve
            log_decision(expense, "auto-approved", answer, confidence)
            notify_user(expense, "auto-approved")
        else:
            # HITL required
            send_slack_approval(expense, answer, confidence)
    
    def send_slack_approval(expense, ai_answer, confidence):
        slack_client.chat_postMessage(
            channel="#approvals",
            text=(f"Expense approval needed:\n"
                  f"Employee: {expense['employee']}\n"
                  f"Amount: ${expense['amount']}\n"
                  f"Description: {expense['description']}\n"
                  f"AI Suggestion: {ai_answer} (confidence: {confidence*100:.1f}%)\n"
                  f"Please reply with Approve/Reject/Comment.")
        )
    
    def log_decision(expense, status, ai_answer, confidence):
        # Write to PostgreSQL (implement as needed)
        pass
    
    def notify_user(expense, status):
        # Notify the submitter via Slack/email
        pass
    
  3. Start the API and Celery Worker:
    uvicorn main:app --reload
    celery -A tasks worker --loglevel=info
    
  4. Test the API Endpoint:
    curl -X POST http://localhost:8000/submit-expense/ \
      -H "Content-Type: application/json" \
      -d '{"employee": "Jane Doe", "amount": 2500, "description": "Conference travel"}'
    

    You should see a message posted to your Slack #approvals channel for human review if the amount or confidence triggers HITL.

4. Implement the Human Approval Response Handler

  1. Create a Slack Event Webhook:
    • In your Slack app settings, add a Request URL (e.g., https://your-ngrok-url/slack/events).
    • Subscribe to message.channels event.
  2. Expose Your Local Server with ngrok:
    ngrok http 8000
    
    • Copy the HTTPS URL and set it as your Slack request URL.
  3. Add the Slack Event Handler in FastAPI:
    • Update main.py:
    
    from fastapi import APIRouter, Request, BackgroundTasks
    from slack_sdk.signature import SignatureVerifier
    
    router = APIRouter()
    signature_verifier = SignatureVerifier(os.getenv("SLACK_SIGNING_SECRET"))
    
    @router.post("/slack/events")
    async def slack_events(request: Request, background_tasks: BackgroundTasks):
        body = await request.body()
        if not signature_verifier.is_valid_request(body, request.headers):
            return {"ok": False}
        event = await request.json()
        # Slack URL verification challenge
        if event.get("type") == "url_verification":
            return {"challenge": event["challenge"]}
        # Handle message in #approvals
        if event.get("event", {}).get("type") == "message":
            text = event["event"]["text"].lower()
            user = event["event"]["user"]
            if "approve" in text:
                background_tasks.add_task(handle_decision, event, "approved")
            elif "reject" in text:
                background_tasks.add_task(handle_decision, event, "rejected")
        return {"ok": True}
    
    def handle_decision(event, decision):
        # Parse expense from context, update DB, notify user, etc.
        pass
    
    app.include_router(router)
    
  4. Test Human Approval:
    • When a HITL expense appears in #approvals, reply with "Approve" or "Reject".
    • Check that the workflow records the decision and continues processing (e.g., notifies the submitter, updates DB).

5. Persist Decisions and Audit Trails in PostgreSQL

  1. Define the Database Model:
    • Create models.py:
    
    from sqlalchemy import create_engine, Column, Integer, String, Float, DateTime
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy.orm import sessionmaker
    import os
    import datetime
    
    DATABASE_URL = os.getenv("DATABASE_URL")
    engine = create_engine(DATABASE_URL)
    SessionLocal = sessionmaker(bind=engine)
    Base = declarative_base()
    
    class ExpenseDecision(Base):
        __tablename__ = "expense_decisions"
        id = Column(Integer, primary_key=True, index=True)
        employee = Column(String)
        amount = Column(Float)
        description = Column(String)
        status = Column(String)
        decision_by = Column(String)
        ai_answer = Column(String)
        confidence = Column(Float)
        timestamp = Column(DateTime, default=datetime.datetime.utcnow)
    
    def init_db():
        Base.metadata.create_all(bind=engine)
    
  2. Log Decisions in Your Workflow:
    • Update your log_decision function in tasks.py:
    
    from models import SessionLocal, ExpenseDecision
    
    def log_decision(expense, status, ai_answer, confidence, decision_by="AI"):
        db = SessionLocal()
        record = ExpenseDecision(
            employee=expense["employee"],
            amount=expense["amount"],
            description=expense["description"],
            status=status,
            decision_by=decision_by,
            ai_answer=ai_answer,
            confidence=confidence
        )
        db.add(record)
        db.commit()
        db.close()
    
  3. Initialize the Database:
    python
    >>> from models import init_db
    >>> init_db()
    
  4. Verify Audit Trail:
    • Query the expense_decisions table to confirm all approvals (AI and human) are logged.

6. (Optional) Enhance with LLM Prompt Engineering and Advanced HITL Triggers

  1. Refine LLM Prompts:
  2. Add Custom HITL Triggers:
    • Trigger HITL on ambiguous language, missing documentation, or policy exceptions using LLM outputs.
    • Route approvals to specific reviewers based on business rules.
  3. Integrate with Other Platforms:
    • Swap Slack for Microsoft Teams or custom web dashboards as needed.

For a deep dive into prompt design and generative AI in approval workflows, check out Generative AI Prompt Engineering for Approval Workflow Automation.

Common Issues & Troubleshooting

Next Steps

Summary

Adding human-in-the-loop approval to automated workflows is no longer optional—it's essential for trust, compliance, and operational resilience in AI-driven enterprises. By following the blueprint above, you can build robust, auditable, and flexible HITL workflows that balance automation with human judgment.

For a comprehensive overview of AI-powered approval automation, revisit our Ultimate Guide to Automating Approval Workflows with AI in 2026.

human-in-the-loop workflow automation approval workflows ai best practices

Related Articles

Tech Frontline
10 Advanced Prompts for Document AI Workflow Automation in 2026
Jun 28, 2026
Tech Frontline
Prompt Engineering for Finance Automations: Real-World Workflows and Templates
Jun 27, 2026
Tech Frontline
How to Use AI Workflow Automation to Streamline Campus Facilities Management
Jun 27, 2026
Tech Frontline
Prompt Engineering for Complex Multi-Agent Workflows: Patterns That Work in 2026
Jun 26, 2026
Free & Interactive

Tools & Software

100+ hand-picked tools personally tested by our team — for developers, designers, and power users.

🛠 Dev Tools 🎨 Design 🔒 Security ☁️ Cloud
Explore Tools →
Step by Step

Guides & Playbooks

Complete, actionable guides for every stage — from setup to mastery. No fluff, just results.

📚 Homelab 🔒 Privacy 🐧 Linux ⚙️ DevOps
Browse Guides →
Advertise with Us

Put your brand in front of 10,000+ tech professionals

Native placements that feel like recommendations. Newsletter, articles, banners, and directory features.

✉️
Newsletter
10K+ reach
📰
Articles
SEO evergreen
🖼️
Banners
Site-wide
🎯
Directory
Priority

Stay ahead of the tech curve

Join 10,000+ professionals who start their morning smarter. No spam, no fluff — just the most important tech developments, explained.