Using AI at work

Use few-shot examples to make AI output more consistent and check it automatically

Show an AI a few examples of the exact output structure you want, then validate the returned JSON before using it. A small synthetic ticket dataset demonstrates how formatting examples and automatic checks work together.

Show contents

Who this is forThis guide is for people who use AI to transform repeated work items and need predictable machine-readable output instead of free-form prose.

What you need
  • Python 3.12 and a terminal command that starts that version.
  • Access to an AI assistant where you can paste the example prompt.
  • A text editor that can save UTF-8 JSON files.
  • Only the Python standard library is required for validation: csv, json, and pathlib.

01Define the output contract before prompting

Suppose you want an AI to convert short support tickets into structured records. Each result must contain exactly four keys: ticket_id, priority, owner_team, and action. priority may be LOW, MEDIUM, or HIGH. owner_team may be IT, FACILITIES, or FINANCE. All four values must be non-empty strings.

The important idea is to define the format independently from the AI response. The AI is producing a candidate record. Your script decides whether that candidate satisfies the required structure.

02Create three synthetic tickets

The following tickets are synthetic and were written specifically for this article. They are deliberately simple so you can determine the intended structured result by hand.

ticket_idSynthetic ticket textExpected classification
T101Payroll spreadsheet cannot be opened before today's payment run.HIGH · FINANCE
T102Meeting room B light is flickering but the room is still usable.LOW · FACILITIES
T103New employee laptop cannot connect to the office Wi-Fi.MEDIUM · IT

For this tutorial, the expected actions are also fixed in advance: T101 should be Check payroll workbook access, T102 should be Inspect meeting room B light, and T103 should be Troubleshoot laptop Wi-Fi connection. These expected values are part of the synthetic exercise, not general rules for real support operations.

03Give the AI examples of the exact format

A few-shot prompt includes one or more completed examples before the new inputs. The demonstrations below show both the classification style and the exact JSON shape. They use different synthetic tickets from the three items that will be checked.

text
Convert each ticket into a JSON object.

Rules:
- Return one JSON array only.
- Do not add explanations or Markdown.
- Use exactly these keys in every object: ticket_id, priority, owner_team, action.
- priority must be LOW, MEDIUM, or HIGH.
- owner_team must be IT, FACILITIES, or FINANCE.

Example 1 input:
Ticket ID: E001
Text: Printer on floor 2 is out of paper.

Example 1 output:
{"ticket_id":"E001","priority":"LOW","owner_team":"IT","action":"Refill or check floor 2 printer"}

Example 2 input:
Ticket ID: E002
Text: Expense approval file is unavailable before today's reimbursement deadline.

Example 2 output:
{"ticket_id":"E002","priority":"HIGH","owner_team":"FINANCE","action":"Check expense approval file access"}

Now process these tickets:
T101: Payroll spreadsheet cannot be opened before today's payment run.
T102: Meeting room B light is flickering but the room is still usable.
T103: New employee laptop cannot connect to the office Wi-Fi.

The examples show more than field names. They demonstrate uppercase category values, short action phrases, quoted JSON strings, and the absence of surrounding commentary. That reduces ambiguity about how the answer should be presented.

04Define the expected output before seeing the AI response

For this synthetic exercise, the expected answer is the JSON array below. Save the actual AI response as ai_output.json before running the checker. Do not silently edit a malformed response first; the purpose of the checker is to reveal whether the original response followed the contract.

json
[
  {
    "ticket_id": "T101",
    "priority": "HIGH",
    "owner_team": "FINANCE",
    "action": "Check payroll workbook access"
  },
  {
    "ticket_id": "T102",
    "priority": "LOW",
    "owner_team": "FACILITIES",
    "action": "Inspect meeting room B light"
  },
  {
    "ticket_id": "T103",
    "priority": "MEDIUM",
    "owner_team": "IT",
    "action": "Troubleshoot laptop Wi-Fi connection"
  }
]

There should be exactly 3 objects and 12 field values in total. Each of the three allowed priorities appears once, and each of the three allowed owner teams appears once.

05Validate the AI response automatically

Save the following script as check_ai_output.py. It validates JSON syntax, array length, exact keys, data types, allowed category values, ticket IDs, and the expected synthetic classifications. It writes a review CSV only after parsing the AI response.

python
import csv
import json
from pathlib import Path

SOURCE = Path("ai_output.json")
OUTPUT_DIR = Path("outputs") / "few_shot_check_result"
REPORT = OUTPUT_DIR / "format_check.csv"

EXPECTED = {
    "T101": ("HIGH", "FINANCE", "Check payroll workbook access"),
    "T102": ("LOW", "FACILITIES", "Inspect meeting room B light"),
    "T103": ("MEDIUM", "IT", "Troubleshoot laptop Wi-Fi connection"),
}
REQUIRED_KEYS = {"ticket_id", "priority", "owner_team", "action"}
PRIORITIES = {"LOW", "MEDIUM", "HIGH"}
TEAMS = {"IT", "FACILITIES", "FINANCE"}


def main() -> None:
    if not SOURCE.is_file():
        raise FileNotFoundError(f"AI output not found: {SOURCE}")
    if OUTPUT_DIR.exists():
        raise FileExistsError(f"Output folder already exists: {OUTPUT_DIR}")

    with SOURCE.open("r", encoding="utf-8") as stream:
        data = json.load(stream)

    if not isinstance(data, list):
        raise ValueError("Top-level JSON value must be an array.")
    if len(data) != len(EXPECTED):
        raise ValueError(f"Expected {len(EXPECTED)} objects, got {len(data)}.")

    rows = []
    seen = set()
    for index, item in enumerate(data, start=1):
        errors = []
        if not isinstance(item, dict):
            raise ValueError(f"Item {index} is not a JSON object.")

        if set(item) != REQUIRED_KEYS:
            errors.append("keys")

        for key in REQUIRED_KEYS:
            if key not in item or not isinstance(item.get(key), str) or not item.get(key).strip():
                errors.append(f"invalid_{key}")

        ticket_id = item.get("ticket_id", "")
        if ticket_id in seen:
            errors.append("duplicate_ticket_id")
        seen.add(ticket_id)

        if item.get("priority") not in PRIORITIES:
            errors.append("priority")
        if item.get("owner_team") not in TEAMS:
            errors.append("owner_team")

        expected = EXPECTED.get(ticket_id)
        if expected is None:
            errors.append("unexpected_ticket_id")
        else:
            actual = (
                item.get("priority"),
                item.get("owner_team"),
                item.get("action"),
            )
            if actual != expected:
                errors.append("content_mismatch")

        rows.append({
            "item": index,
            "ticket_id": ticket_id,
            "status": "PASS" if not errors else "FAIL",
            "errors": ";".join(errors),
        })

    missing_ids = set(EXPECTED) - seen
    if missing_ids:
        raise ValueError(f"Missing ticket IDs: {sorted(missing_ids)}")

    OUTPUT_DIR.parent.mkdir(parents=True, exist_ok=True)
    OUTPUT_DIR.mkdir()
    with REPORT.open("x", encoding="utf-8", newline="") as stream:
        writer = csv.DictWriter(
            stream,
            fieldnames=["item", "ticket_id", "status", "errors"],
        )
        writer.writeheader()
        writer.writerows(rows)

    failures = sum(row["status"] == "FAIL" for row in rows)
    print(f"Objects checked: {len(rows)}.")
    print(f"Passed: {len(rows) - failures}; failed: {failures}.")
    print(f"Report: {REPORT.as_posix()}")

    if failures:
        raise RuntimeError("AI output failed one or more checks.")


if __name__ == "__main__":
    main()

06Check the expected result

If ai_output.json exactly matches the expected synthetic output, all 3 objects should pass. The expected console text below is derived by hand and is not an execution log.

text
Objects checked: 3.
Passed: 3; failed: 0.
Report: outputs/few_shot_check_result/format_check.csv
  • Confirm that the top level is a JSON array, not prose surrounding an array.
  • Confirm that every object contains exactly four required keys.
  • Confirm that no ticket is missing or duplicated.
  • Confirm that priority and owner_team use only the allowed labels.
  • Run the checker again without changing OUTPUT_DIR. It should stop with FileExistsError instead of overwriting the previous report.

07Recognize common failures and limits

ProblemWhat the checker should reveal
AI adds an explanation before the JSONjson.load fails because the file is not a single valid JSON value.
One object uses urgency instead of priorityExact-key check fails.
priority is urgentAllowed-value check fails.
T103 appears twiceDuplicate ticket ID check fails and another expected ID may be missing.
JSON structure is valid but the classification is wrongcontent_mismatch is recorded for this synthetic exercise.

Few-shot prompting improves guidance but does not guarantee deterministic output. Different AI systems, settings, context, or later prompts may change the response. Keep the validator even after several successful runs.

This example validates a deliberately small schema with handwritten Python checks. Larger production schemas may benefit from a formal schema system and separate semantic validation. Also remember that valid JSON is only a formatting result: the underlying classification can still be factually or operationally wrong.

Execution and verification record

2026-09-20 · hand-checked example · target: Python 3.12 · standard library: csv, json, pathlib · no execution

  • Manually defined 3 synthetic tickets and their expected priority, owner team, and action values.
  • Manually checked that the expected JSON contains exactly 3 objects and 4 keys per object.
  • Manually confirmed that LOW, MEDIUM, and HIGH each appear once and IT, FACILITIES, and FINANCE each appear once.
  • Inspected the checker for JSON parsing, exact-key checks, non-empty string checks, allowed values, duplicate IDs, missing IDs, and expected-content comparison.
  • Derived the expected result of 3 passes and 0 failures by hand.
Verification limits
  • No AI system was queried by the author of this response, so actual model consistency was not tested.
  • The Python checker was not executed, and no JSON or CSV files were created.
  • The synthetic classifications are exercise-specific expected values, not general support-routing rules.
  • Valid structure does not prove that an AI-generated classification is factually correct.
  • The official documentation URLs were provided from known documentation locations but were not checked live.

Site-wide writing and verification principles

References

The explanations and examples were written for this site. See the official sources below for the related behavior and concepts.