Applied AI Builder
0/18 complete

Module 01 · Technical Foundations

Lab: Send, Inspect, and Log Your First Model Request

Your first model request is complete only when you can explain what was sent, identify which configured model handled it, inspect the returned status and usage metadata, verify the useful output, and preserve a redacted execution record. Seeing fluent text in a terminal is not enough. This lab turns one request into a small, auditable engineering experiment.

The example uses the official OpenAI JavaScript SDK and Responses API because it provides a concrete runnable path. The controls transfer to other providers: keep the credential in the environment, select an available model through configuration, set a narrow task, capture timing and identifiers, inspect usage, and log metadata rather than private content. Model availability changes, so this lesson deliberately does not hard-code a recommended model or price.

// concept

Prepare a Clean Lab

Create a new folder and initialize it:

// powershell5 lines
mkdir first-model-request
cd first-model-request
git init
npm init -y
npm install openai

Create .gitignore before adding credentials:

// prompt — copy me4 lines
.env
request-log.jsonl
node_modules/
*.log

Create .env.example and commit this safe template, not a real .env file:

// prompt — copy me2 lines
OPENAI_API_KEY=set_only_in_your_local_environment
OPENAI_MODEL=copy_an_available_model_id_from_current_official_docs_or_your_dashboard

Set OPENAI_API_KEY in your local environment using the current official quickstart instructions. Set OPENAI_MODEL to a text model available to your API project. Do not send a key to a classmate for troubleshooting; compare redacted configuration names and error categories instead.

Before spending anything, check:

  • the account or project is the intended one;
  • a low budget or alert is configured where available;
  • the prompt contains only synthetic, non-sensitive text;
  • the selected model supports the request;
  • you know where the local log will be written;
  • .env and the log are ignored by Git.

// worked_example

Worked Example: One Request With a Redacted JSONL Log

Create request.mjs:

// javascript58 lines
import OpenAI from "openai";
import { appendFile } from "node:fs/promises";

const apiKey = process.env.OPENAI_API_KEY;
const model = process.env.OPENAI_MODEL;

if (!apiKey) throw new Error("OPENAI_API_KEY is missing from the environment");
if (!model) throw new Error("OPENAI_MODEL is missing from the environment");

const prompt = [
  "Classify this synthetic support message.",
  "Return two lines only: category and one-sentence reason.",
  "Message: My demo order arrived with the wrong colour.",
].join("\n");

if (prompt.length > 500) throw new Error("Prompt exceeds this lab's input cap");

const client = new OpenAI({ apiKey });
const startedAt = new Date();
const startMs = performance.now();

try {
  const response = await client.responses.create({
    model,
    input: prompt,
  });

  const elapsedMs = Math.round(performance.now() - startMs);
  const output = response.output_text?.trim() ?? "";
  if (!output) throw new Error("The response contained no output text");

  console.log(output);
  console.log({ responseId: response.id, model: response.model, elapsedMs });

  const logRecord = {
    timestamp: startedAt.toISOString(),
    task: "synthetic-support-classification",
    response_id: response.id,
    configured_model: model,
    returned_model: response.model ?? null,
    elapsed_ms: elapsedMs,
    usage: response.usage ?? null,
    output_review: {
      non_empty: output.length > 0,
      line_count: output.split(/\r?\n/).filter(Boolean).length,
    },
  };

  await appendFile("request-log.jsonl", `${JSON.stringify(logRecord)}\n`, "utf8");
} catch (error) {
  const safeError = {
    name: error?.name ?? "Error",
    status: error?.status ?? null,
    message: String(error?.message ?? "Unknown error").slice(0, 200),
  };
  console.error(safeError);
  process.exitCode = 1;
}

Run node request.mjs. The SDK reads the key from your process only because the code passes it to the server-side client; it never prints it. The log uses JSON Lines: one complete JSON object per line. This format is easy to append and inspect. Open the log and verify that it contains identifiers, timing, usage, and simple review results—but not the API key, full prompt, or model output.

Why keep configured_model and returned_model separately? Configuration proves what your application requested; returned metadata records what the service reported. Why record a response ID? It gives support and operations a precise event to investigate without pasting the customer's entire content. Why record provider-reported usage rather than estimate it from characters? Tokenization and billable units are provider-specific and can change.

// concept

Inspect the Output as a Claim, Not a Truth

For the synthetic message, define the acceptance check before reading the answer:

  1. Exactly two non-empty lines were requested.
  2. The category should indicate an order or product issue.
  3. The reason must refer only to the supplied wrong-colour fact.
  4. It must not invent a refund, policy, customer identity, or delivery date.

The code checks only non-empty output and line count. A human still checks meaning. In a production workflow, convert these requirements into structured output and automated tests, which the next module covers. A response can be technically successful but factually wrong, badly formatted, unsafe, or irrelevant.

Make one controlled comparison. Change only “wrong colour” to “tracking link has not updated” and run again. Add a note to LAB-NOTES.md: what changed in the output, whether each answer passed the same rubric, the two response IDs, and any usage difference. Do not conclude that one sample proves general reliability.

// failure_cases

Failure Cases and a Diagnostic Order

8 cases to diagnose

  • Missing environment variable

    the local preflight error should appear before a network request. Fix the environment; do not paste the key into the source file.

  • Authentication or permission error

    confirm the project, key status, and permissions. Do not retry it in a tight loop.

  • Unknown or unavailable model

    use the current official model catalog or your dashboard and update OPENAI_MODEL; keep code unchanged.

  • Rate limit

    inspect the error category and current limits. If retrying is appropriate, use bounded exponential backoff with jitter rather than immediate repetition.

  • Network interruption

    distinguish a transport failure from an API response. A client timeout does not always prove server-side work stopped; use request or job identifiers before resubmitting side-effecting work.

  • Empty or unexpected output

    inspect the complete response safely in a local, non-shared environment, then improve parsing and acceptance checks. Do not log private payloads globally.

  • Usage missing

    handle metadata as nullable. Monitoring code should not crash the business workflow because an optional field is absent.

  • Log leak

    logging the entire error or response can capture inputs, headers, or customer data. Whitelist fields rather than trying to redact every possible secret afterward.

// pakistan_angle

Pakistan Angle

Use a small synthetic prompt while learning so limited balances and mobile-data connections are not consumed by repeated large requests. Record latency across several attempts before promising a turnaround time to a Pakistani client; international routing and local connectivity can vary. A slow request is a measurement, not proof that every user will see the same delay.

For bilingual products, test English, Urdu script, and Roman Urdu as separate fixtures and have native readers review meaning. Never send a real WhatsApp chat, CNIC scan, bank document, medical record, school record, or private client brief merely because it is convenient. Check the provider's current data controls, retention terms, region options, and your client's written authorization before processing real material. Keep the log minimal enough to share with a reviewer without revealing the underlying customer message.

// hands_on

Hands-On Exercise: Submit a Verifiable Request Record

5 steps

Produce the following, using only synthetic messages:

  1. request.mjs with environment checks, an input cap, one Responses API call, a non-empty-output check, safe error handling, and JSONL metadata logging.

  2. .env.example and .gitignore; run git status --ignored and confirm the local secret and log are ignored.

  3. request-log.jsonl containing two successful records from prompts that differ in exactly one business detail. Keep this file out of Git and submit a redacted copy only if your instructor's process permits it.

  4. LAB-NOTES.md with the prewritten acceptance rubric, response IDs, observed timing, provider-reported usage, pass/fail results, and one next test.

  5. A failed run caused by temporarily removing OPENAI_MODEL, demonstrating that local preflight prevents a paid request. Record the error text without any environment value. Finish by running git diff --cached before committing the safe source and notes. Search the staged material for OPENAI_API_KEY; the variable name may appear, but no value may appear.

// completion_rubric

Completion Rubric

6 grading bands

  • Pass — secure configuration

    the key is environment-only, ignored by Git, absent from logs, and never submitted.

  • Pass — inspectability

    each successful run records timestamp, task, response ID, configured/returned model, elapsed time, usage when available, and output checks.

  • Pass — verification

    acceptance criteria existed before comparison and unsupported facts are marked as failures.

  • Pass — controlled experiment

    exactly one input detail changed between the two logged runs.

  • Pass — operational judgment

    errors are categorized before retry, and no retry or spend guarantee is claimed.

  • Needs revision

    raw private content is logged, model or price claims are hard-coded as permanently current, or fluent output is accepted without a rubric.

// sources

Sources

// check_yourself

Check yourself

4 questions · answers and options are taken word-for-word from this course

0/4
  1. 1 / 4 · diagnose

    Your work shows this failure mode: “Missing environment variable.” The lesson describes it like this: “The local preflight error should appear before a network request.” What does the lesson tell you to do about it?