Automating Repetitive Tasks with AI
Use AI to propose ticket categories, validate the result with Python, and produce a repeatable processing batch.
Overview
For learners who want to complete this practical exercise with inspectable sample data and explicit checks.
- Choose a small task to automate first.
- Separate AI proposals from execution.
- Use IDs and validation to prevent missing or duplicated items.
You will build: A triage.json containing three valid proposals without applying them to a support system.
Prerequisites
- Python 3.10+, an editor, and an AI assistant with text chat.
The script runs offline; paste fictional records into an assistant you can access. No API or automatic messaging is required.
Step-by-step tutorial
Step 1. Choose a batch with stable IDs
Start by categorizing the three fictional tickets below rather than automating deletion or email sending first. Allowed labels are access, billing, and other. Ambiguous tickets should be routed for review instead of receiving a confident decision.
Step 2. Ask for structured AI proposals
Classify the records below. Return a JSON array with exactly three fields per item: id, category (access/billing/other), needs_review (boolean). Preserve every ID exactly once. Ambiguous input means other and needs_review=true. Do not write customer replies.
T1: Cannot sign in after password reset
T2: Please explain my sample invoice
T3: I have a questionSave the actual output as proposals.json. To test the script before using AI, use the authored fixture below; it is not a measured model result.
[{"id":"T1","category":"access","needs_review":false},
{"id":"T2","category":"billing","needs_review":false},
{"id":"T3","category":"other","needs_review":true}]Step 3. Validate before writing output
Save this as triage.py beside proposals.json. It checks structure and IDs, not whether the assigned category is semantically correct. Compare all three labels against the source before real use.
import json
from pathlib import Path
TICKETS = [{"id": "T1", "text": "Cannot sign in after password reset"},
{"id": "T2", "text": "Please explain my sample invoice"},
{"id": "T3", "text": "I have a question"}]
ALLOWED = {"access", "billing", "other"}
def validate(proposals):
expected = {item["id"] for item in TICKETS}
if not isinstance(proposals, list) or len(proposals) != len(expected):
raise ValueError("wrong batch size")
seen = set()
for item in proposals:
if not isinstance(item, dict) or set(item) != {"id", "category", "needs_review"}:
raise ValueError("invalid fields")
if item["id"] not in expected or item["id"] in seen:
raise ValueError("unknown or duplicate id")
if item["category"] not in ALLOWED or type(item["needs_review"]) is not bool:
raise ValueError("invalid classification")
seen.add(item["id"])
return sorted(proposals, key=lambda item: item["id"])
if __name__ == "__main__":
proposals = json.loads(Path("proposals.json").read_text(encoding="utf-8"))
result = validate(proposals)
Path("triage.json").write_text(json.dumps(result, indent=2) + "\n", encoding="utf-8")
print("Validated", len(result), "proposals; no messages sent")python3 triage.pyStep 4. Test errors and rerun safely
Duplicate T1 or change a category to admin; the script must reject the batch before writing a new result. Correct it, run twice with the same input, and compare triage.json contents. Keep only checked results for a separately authorized import into a support tool.
Verification
- All three IDs appear exactly once, with needs_review=true for T3.
- Invalid batches stop before writing, and nothing sends messages.
Troubleshooting
The assistant wraps JSON in Markdown
Cause: The output violates the machine-readable contract.
Fix: Request plain JSON or remove only the surrounding code fence; never parse it with eval.
The script succeeds but the label is wrong
Cause: Structural validation does not establish semantic correctness.
Fix: Inspect the source, correct the proposal, and add failures to the prompt test set.
Exercises & extensions
- Add a multi-intent ticket and check that it is flagged for review.
- Turn the steps into an n8n workflow in the next tutorial.
There is no real CRM integration or customer data. Idempotency here means stable output content, not distributed transaction guarantees.
