Chapter 3 · the one lever you have on the model
The prompt is the only interface you get.
You can't retrain the model or read its weights. You decide what goes in the system slot, whether to show examples, and whether to hand it a template.
# bare: the model decides length, tone, shape
client.responses.create(model="gpt-5.4-nano", input=QUESTION)
# guided: a system instruction pins the role and the rules
client.responses.create(
model="gpt-5.4-nano", instructions=SYSTEM, input=QUESTION,
)
Same model. The answer changes completely.
The role is the cheap part. The constraints do the work:
Vague roles drift. Specific rules hold.
# OpenAI: system prompt is a top-level argument
responses.create(instructions=SYSTEM, input=QUESTION)
# Gemini: system prompt hangs off the config
generate_content(
contents=QUESTION,
config=types.GenerateContentConfig(system_instruction=SYSTEM),
)
Same prompt text. Different attachment point.
Each one is a docker compose up web app.
PROVIDER = os.environ.get("PROVIDER", "openai")
ai = importlib.import_module(f"ai_{PROVIDER}")
PROVIDER=gemini docker compose up --build swaps the SDK.
The prompt text is identical across both.
Be specific in the system prompt. Show examples when format matters. Hand it a template when you need the same shape every time. Everything fancier is built on these three.