Current Section

Overview

0%

← Back to Tutorials
Python · AI Automation

AI Automation with Python

A Practical Guide

Build controlled business workflows where AI understands unstructured information and Python validates, routes, executes, retries, logs, and measures the result.

Beginner to IntermediatePythonStructured Outputs18–22 min read

What you will build

✓A typed support-ticket analysis schema using Pydantic
✓A model call that returns validated structured output
✓Deterministic Python routing and escalation rules
✓A workflow with explicit processing and failure states
✓A production architecture using queues, retries, and human review
✓A measurement plan covering quality, cost, and business value

30-second explanation

AI automation is a controlled workflow where AI handles uncertain language and Python handles deterministic execution.

AI model

Understands, classifies, extracts, summarises, compares, and drafts.

Python

Validates, calculates, routes, saves, retries, logs, authorises, and executes.

Use AI for uncertainty. Use normal code for certainty.

Understand

Traditional automation vs AI automation

Traditional automation

Known input
↓
Fixed rules
↓
Deterministic result

Best for:

  • • Calculations
  • • Exact validation
  • • Database updates
  • • Fixed routing rules
  • • Predictable transformations

AI automation

Unstructured input
↓
AI interpretation
↓
Structured result
↓
Deterministic workflow

Best for:

  • • Classification
  • • Summarisation
  • • Information extraction
  • • Draft generation
  • • Ambiguous language

Capabilities

Where AI adds value inside a workflow

LanguageUnderstand+

Interpret unstructured emails, documents, notes, forms, and user requests.

Example

Understand that “I cannot see my dashboard after changing my password” describes an access problem.

Decision supportClassify+

Assign categories, priorities, sentiment, departments, or workflow paths.

Example

Classify an incoming message as access, billing, performance, security, or other.

StructureExtract+

Convert messy language into validated fields that software can process.

Example

Extract invoice number, date, amount, supplier, and payment terms.

CompressionSummarise+

Reduce long information into concise, decision-ready summaries.

Example

Convert a long support email into a two-sentence issue summary.

DraftingGenerate+

Create reports, replies, updates, recommendations, and structured documents.

Example

Prepare a customer-response draft for a support agent to review.

WorkflowRoute+

Use structured AI output to trigger deterministic Python workflow logic.

Example

Send security issues to the security team and normal access issues to identity support.

Architecture

The complete AI automation flow

Input

Email, file, API, or database

Python

Prepare and minimise

AI task

Analyse language

Structure

Typed model output

Validate

Schema and rules

Execute

API or workflow action

Review

Human when required

Build

Implementation roadmap

01

Define

Document the manual process, expected outcome, inputs, rules, risks, and success metrics.

02

Isolate

Identify the specific language task where AI adds value.

03

Structure

Define a typed schema for the information the workflow requires.

04

Generate

Ask the model to analyse the input and return structured output.

05

Validate

Apply schema validation and deterministic business rules.

06

Execute

Perform approved actions using Python, APIs, queues, and integrations.

07

Measure

Track quality, cost, latency, manual review, failures, and business value.

Practical project

Automate support-ticket intake

The automation will receive a support message and produce a validated analysis containing summary, category, priority, sentiment, recommended team, and whether human review is required.

Message

Customer issue

Analyse

AI understands content

Structure

Typed result

Validate

Python checks rules

Route

Select team

Review

Escalate if needed

Step 1

Set up the Python environment

mkdir ai-ticket-automation
cd ai-ticket-automation

python -m venv .venv
source .venv/bin/activate

pip install --upgrade openai pydantic

Store your API key in an environment variable.

export OPENAI_API_KEY="your-api-key"

# Confirm that the variable exists without printing the secret.
python -c "import os; print(bool(os.getenv('OPENAI_API_KEY')))"

Step 2

Define the structured output

The schema becomes the contract between the AI model and the Python workflow.

from typing import Literal

from pydantic import BaseModel, Field


class TicketAnalysis(BaseModel):
    summary: str = Field(
        description="A concise description of the customer issue."
    )

    category: Literal[
        "access",
        "billing",
        "performance",
        "security",
        "other",
    ]

    priority: Literal[
        "low",
        "medium",
        "high",
        "critical",
    ]

    sentiment: Literal[
        "positive",
        "neutral",
        "frustrated",
        "angry",
    ]

    recommended_team: Literal[
        "identity-support",
        "billing-support",
        "application-support",
        "security-operations",
        "general-support",
    ]

    requires_human_review: bool

    suggested_next_action: str

Step 3

Analyse the ticket with Structured Outputs

import os

from openai import OpenAI


MODEL = os.getenv("OPENAI_MODEL", "gpt-5.6")

client = OpenAI()


def analyse_ticket(ticket_text: str) -> TicketAnalysis:
    cleaned_text = ticket_text.strip()

    if not cleaned_text:
        raise ValueError("ticket_text cannot be empty")

    response = client.responses.parse(
        model=MODEL,
        input=[
            {
                "role": "system",
                "content": (
                    "You analyse incoming software support tickets. "
                    "Classify only from the allowed schema values. "
                    "Use critical priority only for severe business impact, "
                    "security incidents, or complete service unavailability. "
                    "Set requires_human_review to true for security issues, "
                    "critical priority, unclear requests, or sensitive cases. "
                    "Do not invent facts that are not present in the ticket."
                ),
            },
            {
                "role": "user",
                "content": cleaned_text,
            },
        ],
        text_format=TicketAnalysis,
    )

    result = response.output_parsed

    if result is None:
        raise RuntimeError(
            "The model did not return a structured ticket analysis."
        )

    return result

Step 4

Apply deterministic Python rules

The AI recommends a structured interpretation. Python remains responsible for policy and workflow decisions.

TEAM_BY_CATEGORY = {
    "access": "identity-support",
    "billing": "billing-support",
    "performance": "application-support",
    "security": "security-operations",
    "other": "general-support",
}


def validate_business_rules(
    analysis: TicketAnalysis,
) -> TicketAnalysis:
    expected_team = TEAM_BY_CATEGORY[analysis.category]

    if analysis.recommended_team != expected_team:
        analysis.recommended_team = expected_team

    if analysis.category == "security":
        analysis.priority = "critical"
        analysis.requires_human_review = True

    if analysis.priority == "critical":
        analysis.requires_human_review = True

    return analysis


def requires_escalation(
    analysis: TicketAnalysis,
) -> bool:
    return (
        analysis.priority == "critical"
        or analysis.category == "security"
        or analysis.requires_human_review
    )
The model can suggest a destination, but the authoritative routing table remains in Python.

Step 5

Route the ticket safely

from dataclasses import dataclass
from enum import StrEnum


class WorkflowStatus(StrEnum):
    RECEIVED = "received"
    PROCESSING = "processing"
    CLASSIFIED = "classified"
    VALIDATED = "validated"
    HUMAN_REVIEW = "human_review"
    ROUTED = "routed"
    COMPLETED = "completed"
    FAILED = "failed"


@dataclass
class WorkflowResult:
    status: WorkflowStatus
    analysis: TicketAnalysis | None = None
    message: str | None = None


def route_ticket(
    analysis: TicketAnalysis,
) -> WorkflowResult:
    if requires_escalation(analysis):
        return WorkflowResult(
            status=WorkflowStatus.HUMAN_REVIEW,
            analysis=analysis,
            message=(
                "Ticket requires human review before "
                "creating or updating an external record."
            ),
        )

    # Replace this section with an approved Jira,
    # ServiceNow, database, or internal API integration.
    print(
        f"Routing ticket to {analysis.recommended_team}"
    )

    return WorkflowResult(
        status=WorkflowStatus.COMPLETED,
        analysis=analysis,
        message="Ticket routed successfully.",
    )

Complete implementation

Put the workflow together

import os
from dataclasses import dataclass
from enum import StrEnum
from typing import Literal

from openai import OpenAI
from pydantic import BaseModel, Field


MODEL = os.getenv("OPENAI_MODEL", "gpt-5.6")

client = OpenAI()


class TicketAnalysis(BaseModel):
    summary: str = Field(
        description="A concise description of the customer issue."
    )

    category: Literal[
        "access",
        "billing",
        "performance",
        "security",
        "other",
    ]

    priority: Literal[
        "low",
        "medium",
        "high",
        "critical",
    ]

    sentiment: Literal[
        "positive",
        "neutral",
        "frustrated",
        "angry",
    ]

    recommended_team: Literal[
        "identity-support",
        "billing-support",
        "application-support",
        "security-operations",
        "general-support",
    ]

    requires_human_review: bool
    suggested_next_action: str


class WorkflowStatus(StrEnum):
    RECEIVED = "received"
    PROCESSING = "processing"
    CLASSIFIED = "classified"
    VALIDATED = "validated"
    HUMAN_REVIEW = "human_review"
    ROUTED = "routed"
    COMPLETED = "completed"
    FAILED = "failed"


@dataclass
class WorkflowResult:
    status: WorkflowStatus
    analysis: TicketAnalysis | None = None
    message: str | None = None


TEAM_BY_CATEGORY = {
    "access": "identity-support",
    "billing": "billing-support",
    "performance": "application-support",
    "security": "security-operations",
    "other": "general-support",
}


def analyse_ticket(ticket_text: str) -> TicketAnalysis:
    cleaned_text = ticket_text.strip()

    if not cleaned_text:
        raise ValueError("ticket_text cannot be empty")

    response = client.responses.parse(
        model=MODEL,
        input=[
            {
                "role": "system",
                "content": (
                    "You analyse incoming software support tickets. "
                    "Classify only from the allowed schema values. "
                    "Use critical priority only for severe business impact, "
                    "security incidents, or complete service unavailability. "
                    "Set requires_human_review to true for security issues, "
                    "critical priority, unclear requests, or sensitive cases. "
                    "Do not invent facts that are not present in the ticket."
                ),
            },
            {
                "role": "user",
                "content": cleaned_text,
            },
        ],
        text_format=TicketAnalysis,
    )

    result = response.output_parsed

    if result is None:
        raise RuntimeError(
            "The model did not return a structured ticket analysis."
        )

    return result


def validate_business_rules(
    analysis: TicketAnalysis,
) -> TicketAnalysis:
    expected_team = TEAM_BY_CATEGORY[analysis.category]

    if analysis.recommended_team != expected_team:
        analysis.recommended_team = expected_team

    if analysis.category == "security":
        analysis.priority = "critical"
        analysis.requires_human_review = True

    if analysis.priority == "critical":
        analysis.requires_human_review = True

    return analysis


def requires_escalation(
    analysis: TicketAnalysis,
) -> bool:
    return (
        analysis.priority == "critical"
        or analysis.category == "security"
        or analysis.requires_human_review
    )


def route_ticket(
    analysis: TicketAnalysis,
) -> WorkflowResult:
    if requires_escalation(analysis):
        return WorkflowResult(
            status=WorkflowStatus.HUMAN_REVIEW,
            analysis=analysis,
            message=(
                "Ticket requires human review before "
                "creating or updating an external record."
            ),
        )

    print(
        f"Routing ticket to {analysis.recommended_team}"
    )

    return WorkflowResult(
        status=WorkflowStatus.COMPLETED,
        analysis=analysis,
        message="Ticket routed successfully.",
    )


def process_ticket(
    ticket_text: str,
) -> WorkflowResult:
    try:
        analysis = analyse_ticket(ticket_text)
        validated = validate_business_rules(analysis)
        return route_ticket(validated)

    except Exception as exc:
        return WorkflowResult(
            status=WorkflowStatus.FAILED,
            message=str(exc),
        )


if __name__ == "__main__":
    ticket = """
    Since this morning, nobody in our finance department
    can access the dashboard after resetting their passwords.
    The browser shows an authentication error.
    This is blocking our month-end reporting.
    """

    result = process_ticket(ticket)

    print(f"Status: {result.status}")

    if result.analysis:
        print(
            result.analysis.model_dump_json(indent=2)
        )

    if result.message:
        print(result.message)

Workflow state

Make processing visible and recoverable

RECEIVED

The input has entered the system.

PROCESSING

The Python worker is analysing the input.

CLASSIFIED

The AI result has been produced.

VALIDATED

Schema and business rules have passed.

ROUTED

The workflow destination has been selected.

COMPLETED

The approved workflow action has finished.

HUMAN_REVIEW

Output needs approval or clarification.

RETRY_REQUIRED

A temporary external failure may be retried.

FAILED

Processing stopped and needs investigation.

Reliability

Use queues for production workloads

Request

New work arrives

Queue

Store pending work

Worker

Process asynchronously

AI call

Analyse input

Retry

Handle temporary failure

DLQ

Preserve final failures

Queues are especially useful for rate limits, large documents, batch processing, model downtime, email volumes, and workflows that should continue even when one downstream service is unavailable.

Production system

AI automation is more than one Python script

Input

Email, file, API event, form, database record, message, or scheduled job.

Queue

Buffers work, supports retries, and separates user requests from long-running processing.

Worker

Python service that prepares input, calls the model, validates output, and executes workflow logic.

AI model

Handles the uncertain language task such as classification, extraction, or summarisation.

Validation

Applies schemas, allowed values, business rules, permissions, and safety checks.

Integration

Updates Jira, ServiceNow, Slack, email, databases, dashboards, or internal APIs.

Observability

Records logs, metrics, traces, quality signals, cost, and business outcomes.

Human review

Handles sensitive, uncertain, high-priority, or policy-controlled cases.

Add trusted knowledge

Where RAG fits

Ticket

Incoming issue

Retrieve

Search documentation

Evidence

Approved knowledge

Analyse

AI uses context

Validate

Python checks output

Route

Execute workflow

RAG is one context source inside the automation. Python still owns validation, routing, permissions, execution, and workflow state.

Read the complete RAG guide →

Compare

AI automation vs AI agents

AreaAI automationAI agent
WorkflowMostly predefinedMay choose the next step dynamically
ControlEasier to predict and constrainRequires stronger limits and policy controls
TestingClear paths and expected statesMore possible action sequences
Best useRepeated business processesUncertain multi-step work
Starting pointRecommended for most teamsAdd only when flexibility creates real value
Start with a controlled automation. Add agent behaviour only when dynamic tool selection or planning creates measurable value.

Security

Secure the complete workflow

Minimise data

Send only the content required for the specific AI task.

Protect secrets

Keep credentials, API keys, and private tokens outside prompts and source code.

Validate output

Treat every model response as untrusted until checked by the application.

Restrict integrations

Use least-privilege credentials for Jira, Slack, email, databases, and other systems.

Approve risky actions

Require explicit human review before external, financial, destructive, or sensitive operations.

Control logging

Record useful operational information without retaining unnecessary sensitive content.

Read AI Security Basics →

Measure

Evaluate AI quality and business value

Classification accuracy

How often does the automation select the expected category and priority?

Extraction accuracy

Are important fields correctly extracted from representative inputs?

Invalid-output rate

How often does processing fail schema or business validation?

Escalation accuracy

Are sensitive and high-risk cases sent to human review correctly?

Processing time

How long does the workflow take compared with the previous manual process?

Manual-review rate

What percentage of work still requires intervention?

Cost per item

What is the total cost to process one email, ticket, document, or report?

Business outcome

Does the workflow improve response time, quality, throughput, or user satisfaction?

Cost

Calculate the whole automation cost

Total cost = model input + model output + retries + retrieval + infrastructure + storage + monitoring + human review
✓Use smaller models when they meet the quality target.
✓Reduce unnecessary input before calling the model.
✓Avoid repeating stable work that can be cached.
✓Batch low-priority work where appropriate.
✓Limit retries and agent-style loops.
✓Compare model cost with the cost of errors and human rework.

Build next

Strong first automation projects

Support-ticket intake

Summarise, classify, prioritise, route, and flag incoming customer issues.

Document processing

Extract fields, classify content, identify missing information, and prepare records.

Meeting follow-up

Transform notes into decisions, actions, owners, deadlines, and follow-up communication.

Report generation

Convert raw metrics and operational updates into structured weekly or executive reports.

Email triage

Summarise messages, detect urgency, assign categories, and prepare reply drafts.

Knowledge-assisted workflow

Retrieve approved information with RAG before generating a recommendation or response.

Avoid

Common AI automation mistakes

Automating an unclear process

A broken or unstable manual process usually becomes a broken automated process.

Using AI for deterministic logic

Calculations, fixed validation, permissions, and exact business rules belong in normal code.

Free-form output

Long natural-language responses are difficult for downstream software to use safely.

No workflow states

Without clear states, failures and retries become difficult to diagnose and recover.

No retry strategy

Temporary rate limits and service failures should not permanently lose work.

No human review

Sensitive or uncertain decisions should not be fully automated without appropriate approval.

Ignoring business metrics

A technically working automation may still create no meaningful time or cost savings.

Building an agent too early

Dynamic autonomy adds complexity before the underlying workflow has been understood.

Production checklist

Before launching an AI automation

✓Define the exact business outcome and intended users.
✓Document the existing manual process before automating it.
✓Identify which step genuinely requires language understanding.
✓Keep calculations, permissions, routing rules, and validation deterministic.
✓Define a typed schema for AI-generated output.
✓Use allowed values instead of unlimited free-form labels.
✓Validate model output before any downstream action.
✓Store workflow status and error information.
✓Use queues for long-running or high-volume processing.
✓Set retry limits and use a dead-letter queue for repeated failures.
✓Make workflow actions idempotent where possible.
✓Require human review for sensitive or uncertain cases.
✓Protect credentials and sensitive business information.
✓Track input size, output size, model usage, latency, and retries.
✓Create representative evaluation examples.
✓Measure time saved, quality, cost, and manual-review rate.
✓Test failure behaviour before production.
✓Start with one narrow workflow and expand only after evidence of value.

Key takeaway

Let AI interpret. Let Python control.

Use AI for language understanding, extraction, classification, summarisation, and drafting. Use Python for schemas, calculations, permissions, workflow states, business rules, retries, execution, logging, and approval.

Remember the production pattern:

Define the process → isolate the AI task → request structured output → validate with Python → apply business rules → execute safely → measure real value.

Continue learning

Extend automation with agents, knowledge, and security