Skip to content

AI Agents · Guide

Applied AI Foundations: Python, APIs and JSON

Start with input contracts, HTTP requests, JSON validation and reproducible project files before connecting a model. Includes a source-loader exercise.

Metarix Editorial · Nov 8, 2026 · 5 min read

Share

Documentation-based research

On this page

An applied AI application is still an application. It receives input, calls a component, checks the response, and decides what the user should see when something fails. A fluent model response does not remove those responsibilities.

This first lesson establishes the project habits used throughout Metarix’s Applied AI Engineer learning path. You should already be able to write a Python function, read a file, and run a command in a terminal. If those tasks are unfamiliar, work through the Python tutorial before continuing. You do not need to train a model or study calculus to start this path.

By the end, you should be able to describe an API request, load a small JSON document collection, reject malformed input, and distinguish an application error from an answer with insufficient evidence.

Start with an input–output contract

Our running project is a document assistant for a fictional support handbook. A visitor asks a question. The application finds permitted source material and returns an answer with source IDs, or says it lacks enough information.

Before choosing a model, write down the contract. Input is a nonempty question of at most 500 characters. Output has a status, answer, and citations. The two valid statuses are answered and insufficient_context. An answered response requires at least one source ID from the retrieved context. An abstention has no supporting citations.

Those choices are application rules, not universal AI standards. They make this small project inspectable. The character limit also provides a simple input boundary; it does not by itself prevent prompt injection or control every cost.

Separate errors from abstentions. A missing fixture file is an error and should produce a nonzero process exit. A valid question that the handbook cannot answer is an ordinary result with status insufficient_context. A client needs that distinction to decide whether to retry, fix its request, or show an honest answer.

Understand the API boundary

An HTTP API request has a destination, a method, headers, and sometimes a body. A model request commonly sends JSON in a POST body, uses an authorization header, and receives a JSON response. Python’s urllib.request documentation explains those mechanics without requiring a third-party SDK.

Do not confuse transport success with application success. HTTP 200 means the request succeeded at that layer. The response may still describe an incomplete generation, a refusal, or output that fails your own rules. Conversely, a timeout gives you no reliable completed answer to show.

Keep provider calls behind a function rather than spreading HTTP handling through every part of the application. Later, the project can use a deterministic offline implementation in tests and an explicitly selected live provider in a controlled experiment. The rest of the application should not have to guess which mode ran.

JSON is a format, not a correctness guarantee

JSON represents values such as strings, lists, objects, numbers, booleans, and null. Python’s json module parses that representation into Python values. Parsing alone does not establish that the fields mean what your application expects.

For example, the following object is valid JSON, but the source field has the wrong type for our contract:

json
{"status":"answered","answer":"14 days","citations":"refunds-v1"}

The citations value should be a list of source IDs. Even a correctly typed list could contain an invented ID. We will validate both structure and membership in later lessons.

For source documents, start with a small explicit record:

json
{"id":"refunds-v1","title":"Refund window","text":"The refund window is 14 calendar days after purchase.","audience":"public","updated":"2026-11-08"}

The ID lets answers refer to a source. The audience field supports an access-control exercise. The update date helps track corpus versions. This fictional example does not establish a real refund policy.

Make a project you can reproduce

Use a dedicated directory. Keep source code, synthetic documents, tests, and an evaluation file separate. Record your Python version and the command that produced a result. If you later add packages, use a virtual environment and record compatible dependency versions; the venv documentation explains isolation. Our capstone’s default mode uses only the standard library.

Keep real API keys in a secure process environment or secret manager. A local environment file is not automatically safe: exclude it from source control and avoid printing it. Never put a provider key in browser code, an article screenshot, or the document corpus.

Version the corpus as well as the prompt. A change from “14 days” to “30 days” is a different test condition even when the application code stays the same. Record a source snapshot or content hash so someone can reproduce the result you describe.

Exercise: validate a small source collection

Save two fictional document objects in a JSON list. Write a loader that uses json.loads and verifies that every document has string id, title, text, audience, and updated fields. Reject duplicate IDs. Accept only public or staff as audience values.

Test three failures deliberately: an invalid JSON comma, a missing text field, and two objects with the same ID. Return a clear error without echoing a secret or an entire private document.

You have completed the exercise when a valid collection loads, each malformed collection fails, and you can explain which check failed. Keep the fixtures and command output in your project notes. A test that simply prints an object without checking its fields is not sufficient.

Before continuing

You should now have a stable boundary between user input, source data, provider calls, and application output. The next topic is model interaction: how to ask for structured output, validate it, and handle refusals or incomplete results.

If you already use a local model, our guide to schema validation and retries for local LLM JSON provides additional context. It complements this lesson; this path’s first exercise needs no model account or paid API call.

Documentation checked November 8, 2026. The lesson’s programming exercise is a suggested task; capstone verification is documented separately.

Share

Keep Reading