Easier to read with cream paper, a tint, more contrast or larger text? Choose your colours and text, once, for every page.

Free lesson

How to build a prompt library

After this lesson: I can keep prompts in files with a version and a test.

60 min lesson6 commandsAI coding agent lab: use opencode to explain and fix code, and check its work

Keep prompts in files with versions and tests

A prompt library is a folder of prompts kept as files, each with a version and a test. A prompt that lives in a chat message gets lost, copied wrongly and edited by whoever finds it.

In a file it can be reviewed, tested and rolled back, like code.

By the end of this lesson

Note

I can keep prompts in files with a version and a test.

Key words

WordWhat it meansExample
Librarya folder of prompts kept as files
Variablea named gap code fills in{name}
Versiona number that says which edit this is
Change loga list of what changed and why
Rulea phrase a prompt must always hold
Audita check of every prompt at once

The cells students fill in are left blank in this preview.

What does one prompt file hold?

Each prompt is one file, such as refund-reply.txt. Gaps are variables in braces, like {name}, so code can fill them. A version number sits with the file, and a change log line says what changed.

A test sits beside it. The test holds the rules the prompt must always contain.

What a version number tells you

ChangeBumpFrom 1.2.3 to
Fixed a typopatch1.2.4
Added a limit or an exampleminor1.3.0
Changed the variables, so callers must changemajor2.0.0

The cells students fill in are left blank in this preview.

Write the model helper, part 1

Command
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const base = process.env.AI_URL || \"http://ai:4000\";' '// The token counts of a reply, or null when the reply carries none.' 'function count(data, name) {' '  return data.usage && typeof data.usage[name] === \"number\" ? data.usage[name] : null;' '}' > model.js"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Write the model helper, part 2

Command
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function ask(messages, sample, max) {' '  try {' '    const res = await fetch(base + \"/v1/chat/completions\", {' '      method: \"POST\",' '      headers: { \"content-type\": \"application/json\", authorization: \"Bearer lab\" },' '      body: JSON.stringify({ model: \"lab\", messages: messages, max_tokens: max || 100 }),' '      signal: AbortSignal.timeout(30000),' '    });' '    if (res.ok === false) throw new Error(\"status \" + res.status);' '    const data = await res.json();' '    const text = data.choices[0].message.content;' '    return { text, inTokens: count(data, \"prompt_tokens\"), outTokens: count(data, \"completion_tokens\"), recorded: false };' '  } catch (error) {' '    console.log(\"Recorded sample: no model answered (\" + error.message + \").\");' '    return { text: sample, inTokens: null, outTokens: null, recorded: true };' '  }' '}' 'module.exports = { ask };' >> model.js"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Write the library checker, part 1

Command
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' 'const OLD = \"Role: You are a bus company helper.\nTask: Reply to {name} about a refund.\nLimits: Under 25 words. Never promise a date.\";' 'const RULES = [\"under 25 words\", \"never promise a date\"];' > lib6.js"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Write the library checker, part 2

Command
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function variables(text) {' '  const names = [];' '  for (const f of text.match(/\{[a-z_]+\}/g) || []) {' '    if (names.includes(f.slice(1, -1)) === false) names.push(f.slice(1, -1));' '  }' '  return names;' '}' 'function fill(text, values) {' '  const gone = variables(text).filter(function (n) { return (n in values) === false; });' '  if (gone.length > 0) return { ok: false, missing: gone };' '  let out = text;' '  for (const n of Object.keys(values)) out = out.split(\"{\" + n + \"}\").join(values[n]);' '  return { ok: true, text: out };' '}' >> lib6.js"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Write the library checker, part 3

Command
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function lost(oldText, newText) {' '  const o = oldText.toLowerCase();' '  const n = newText.toLowerCase();' '  return RULES.filter(function (r) { return o.includes(r) && n.includes(r) === false; });' '}' 'async function main() {' '  console.log(\"variables: \" + variables(OLD).join(\", \"));' '  const bad = fill(OLD, {});' '  console.log(\"fill with no values: ok \" + bad.ok + \", missing \" + bad.missing.join(\", \"));' '  const edit = OLD.replace(\"Never promise a date.\", \"\");' '  console.log(\"edit loses: \" + lost(OLD, edit).join(\", \"));' '  const filled = fill(OLD, { name: \"Mina\" });' '  const reply = await ask([{ role: \"user\", content: filled.text }], \"Dear Mina, we are checking your refund.\", 50);' '  console.log(\"model: \" + reply.text);' '}' 'main();' >> lib6.js"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Run and refuse a bad edit

Command
docker exec -w /home/node/project agent node lib6.js

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

What the Run prints

It lists the variable, then shows that filling with no values is refused and names the missing one. Next it edits the prompt to drop a limit and lists the rule the edit loses. That edit would be refused.

The last line is one short reply to the filled prompt. With no model it prints a Recorded sample first.

A common mistake

Warning

Many people think a small edit to a shared prompt is safe. A short edit can remove a limit that other code relied on. Always run the rule test before you save, however small the edit.

About this lab and its source: AI coding agent lab: use opencode to explain and fix code, and check its work

Teaching a class? Set this module for your students with a teacher guide, marked assignments and a lab for every student.