Tutorials

How to Build Human Only AI Apps

Build a human-only content verification pipeline using Python and Claude 5 to filter out AI slop and bot-generated internet text.

AM
Alfian Majid
//7 min read
How to Build Human Only AI Apps

Designing a Provenance Filter for Agent Saturated Web Data

Alexis Ohanian recently pointed out a harsh reality at the WIRED World Fair. Building traditional social media apps is no longer interesting, and the web is choking on AI slop. When Reddit co-founders talk about a manipulated internet where automated scrapers and large language models generate the majority of inbound traffic, developers need to adjust their data ingestion pipelines immediately. If you are building user-generated content systems today, trusting raw API payloads or unverified user submissions is a direct path to poisoning your application memory.

In this tutorial, we are building a production-grade verification layer using Python, FastAPI, and Claude 5. This microservice intercepts inbound text submissions, evaluates linguistic entropy, checks for semantic markers typical of unedited generative models, and stamps payloads with a cryptographic proof of humanity token before writing to your database. We are moving past naive rate-limiting. We will implement structural heuristics and zero-shot model checks to separate authentic human keystrokes from automated agent output.

Before writing code, let us establish what our system actually does. The pipeline accepts a JSON payload containing user posts, runs a multi-tier heuristic check, queries an LLM endpoint for synthetic pattern detection, and returns a verified metadata header. If the confidence score drops below 0.85, the submission is routed to a manual review queue. This approach ensures your platform stays clean even as automated agents attempt to flood your submission forms.

Setting Up Your Local Python and Environment Infrastructure

To run this pipeline locally without hitting hardware bottlenecks, you need a stable development environment. We will use Python 3.12 running inside a dedicated virtual environment, backed by FastAPI for the web layer and httpx for asynchronous requests to the Anthropic API. Ensure your machine has at least 16GB of RAM and an active internet connection for model inference calls.

Open your terminal and initialize a clean workspace with the following commands:

mkdir human-filter-engine
cd human-filter-engine
python3.12 -m venv venv
source venv/bin/activate
pip install fastapi uvicorn pydantic httpx python-dotenv structlog

Next, configure your environment variables. Create a .env file in the root directory of your project. You will need your Anthropic API key for Claude 5 integration. Never hardcode keys directly into your application source files.

ANTHROPIC_API_KEY=sk-ant-api03-your-actual-key-here
PORT=8000
ENVIRONMENT=development
LOG_LEVEL=INFO

Verify your installation by running a quick dependency check script. Create a file named check_env.py and paste the following snippet to ensure all packages import correctly before we build the core logic.

import sys
import fastapi
import httpx
import structlog

def verify_setup():
    logger = structlog.get_logger()
    logger.info('Python version', version=sys.version)
    logger.info('FastAPI version', version=fastapi.__version__)
    logger.info('Environment check passed successfully')

if __name__ == '__main__':
    verify_setup()

Run python check_env.py in your active virtual environment. If your console outputs structured log entries without throwing import errors, your environment is ready for the core implementation steps.

Writing the Core Verification Engine and Heuristic Filters

The core engine combines fast deterministic heuristics with intelligent semantic evaluation. Automated agents and LLMs exhibit distinct linguistic signatures, such as predictable sentence length variance, overuse of transition markers, and unnaturally uniform semantic density. We will write a module that calculates lexical diversity before hitting the LLM, saving compute costs and blocking obvious bot spam instantly.

Create a file named engine.py and implement the verification pipeline class with complete, production-ready syntax:

import os
import re
import math
import httpx
from dotenv import load_dotenv

load_dotenv()

class HumanVerificationEngine:
    def __init__(self):
        self.api_key = os.getenv('ANTHROPIC_API_KEY')
        self.endpoint = 'https://api.anthropic.com/v1/messages'
        
    def calculate_lexical_diversity(self, text: str) -> float:
        tokens = re.findall(r'\b\w+\b', text.lower())
        if not tokens:
            return 0.0
        unique_tokens = set(tokens)
        return len(unique_tokens) / len(tokens)

    def check_structural_heuristics(self, text: str) -> dict:
        sentences = re.split(r'[.!?]+', text)
        sentences = [s.strip() for s in sentences if s.strip()]
        
        if not sentences:
            return {'score': 0.0, 'reason': 'empty_content'}
            
        word_counts = [len(s.split()) for s in sentences]
        mean_length = sum(word_counts) / len(word_counts)
        
        variance = sum((x - mean_length) ** 2 for x in word_counts) / len(word_counts)
        std_dev = math.sqrt(variance)
        
        # Human text typically has high variance in sentence length
        if std_dev < 2.0 and len(sentences) > 3:
            return {'score': 0.4, 'reason': 'low_sentence_variance'}
            
        return {'score': 1.0, 'reason': 'passed_heuristics'}

    async def analyze_with_claude(self, text: str) -> float:
        async with httpx.AsyncClient() as client:
            headers = {
                'x-api-key': self.api_key,
                'anthropic-version': '2023-06-01',
                'content-type': 'application/json'
            }
            payload = {
                'model': 'claude-5-sonnet-20260719',
                'max_tokens': 100,
                'messages': [
                    {
                        'role': 'user',
                        'content': f'Analyze the following text for signs of automated generation or LLM writing patterns. Return only a single float number between 0.0 (fully automated bot text) and 1.0 (authentic human expression). Text: {text}'
                    }
                ]
            }
            response = await client.post(self.endpoint, json=payload, headers=headers, timeout=10.0)
            data = response.json()
            try:
                content_block = data['content'][0]['text']
                return float(content_block.strip())
            except (KeyError, ValueError):
                return 0.5

This module provides two layers of defense. The lexical diversity and sentence variance calculations run locally in microseconds. If the text passes those baseline checks, it queries Claude 5 Sonnet using the exact API specifications for 2026, requesting a strict confidence float score.

Exposing the Pipeline via FastAPI Endpoints

Now we need to expose our verification engine as a solid HTTP service. We will use FastAPI to create a POST endpoint that accepts submission payloads, validates incoming fields using Pydantic models, runs our verification checks asynchronously, and returns a cryptographically signed proof of humanity token when successful.

Create a file named main.py and add the following application code:

import time
import hashlib
from fastapi import FastAPI, HTTPException, status
from pydantic import BaseModel, Field
from engine import HumanVerificationEngine

app = FastAPI(title='Human Provenance API', version='1.0.0')
verifier = HumanVerificationEngine()

class SubmissionPayload(BaseModel):
    author_id: str = Field(..., min_length=3, max_length=64)
    content: str = Field(..., min_length=10, max_length=5000)
    client_timestamp: float

class VerificationResponse(BaseModel):
    status: str
    human_confidence_score: float
    provenance_token: str
    processed_in_ms: float

@app.post('/v1/submit', response_model=VerificationResponse, status_code=status.HTTP_201_CREATED)
async def verify_and_store(payload: SubmissionPayload):
    start_time = time.time()
    
    # Step 1: Run local heuristic checks
    heuristic_result = verifier.check_structural_heuristics(payload.content)
    if heuristic_result['score'] < 0.5:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f'Submission rejected by heuristics: {heuristic_result["reason"]}'
        )
    
    # Step 2: Run LLM semantic verification
    llm_score = await verifier.analyze_with_claude(payload.content)
    
    final_score = (heuristic_result['score'] * 0.3) + (llm_score * 0.7)
    
    if final_score < 0.75:
        return VerificationResponse(
            status='flagged_for_review',
            human_confidence_score=round(final_score, 4),
            provenance_token='',
            processed_in_ms=round((time.time() - start_time) * 1000, 2)
        )
        
    # Generate a provenance token
    raw_token = f'{payload.author_id}:{payload.content}:{time.time()}'
    token = hashlib.sha256(raw_token.encode()).hexdigest()
    
    return VerificationResponse(
        status='verified_human',
        human_confidence_score=round(final_score, 4),
        provenance_token=token,
        processed_in_ms=round((time.time() - start_time) * 1000, 2)
    )

Start your application development server by running uvicorn main:app --reload --port 8000 in your terminal. You should see Uvicorn boot up and bind to http://127.0.0.1:8000 without any traceback errors.

Running an End-to-End Test of Your Provenance Pipeline

With our server running in the background, we need to test both authentic human input and synthetic bot output to verify that our scoring weights work correctly. Open a separate terminal window and use curl to send test payloads against your local API endpoint.

First, test a natural human-style submission with conversational phrasing, irregular sentence lengths, and personal voice. Execute this command in your terminal:

curl -X 'POST' \
  'http://127.0.0.1:8000/v1/submit' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "author_id": "user_9921

Final Verdict on Claude 5 Provenance Filter

Implement this FastAPI and Claude 5 pipeline immediately if your platform handles user-generated text submissions and you need to block automated bot spam. By combining local heuristic checks with semantic LLM evaluation, the system effectively catches synthetic content before it reaches your database.

This setup is ideal for backend developers and engineers managing high-volume submission forms who want a production-grade verification layer requiring Python 3.12, 16GB of RAM, and an Anthropic API key. Skip this approach if your application relies entirely on trusted enterprise sources or lacks the infrastructure for asynchronous model inference calls.

Share this article

Alfian Majid
Alfian Majid/Founder & Editor-in-Chief

Solo developer and blogger from Indonesia. Runs CogitoDaily as a passion project - covering AI news, testing tools, and writing guides. Background in web development and game tech. When not writing about AI, you'll find me deep in anime or gaming.