OpenAI Responses API Messages, Roles and Instructions in Python

In the previous lesson, we learned to send a text prompt with client.responses.create() and read the returned response. A simple prompt works for many tasks, but applications also need a reliable way to distinguish the user’s question from the instructions that guide the assistant’s behavior. The Responses API supports structured messages and high-level instructions so these responsibilities stay clear.

In this beginner tutorial, you’ll learn how messages are represented, how system, developer, user, and assistant roles differ, how instruction priority works, and how to write clearer requests using Python.

1. What is a message?

A message is a unit of conversational content with a role and content. For text-based input, a message can be represented as a Python dictionary

Bash
message = {
    "role": "user",
    "content": "Explain Python functions in simple language."
}

The role identifies the source of the content, while the content holds the text. The API supports richer content types, but plain text is sufficient for this lesson.

2. Understanding message roles

RoleMeaningTypical use
systemHigh-priority instructionsBroad assistant behavior
developerApplication-level instructionsExplain Python to beginners
userEnd-user request or informationWhat is a decorator?
assistantAssistant-generated messagePrevious answer in a conversation

System and developer messages can guide behavior across user requests. User messages provide the question or task. Assistant messages usually represent previous model output supplied as context, they are not an independent instruction authority that overrides the user.

3. How instruction priority works

When instructions conflict, the model is intended to respect the applicable higher-priority instruction. For these common message roles, a simplified order is system → developer → user. Assistant messages can provide context but do not form a higher-priority instruction tier.

flowchart TB
    S["System instructions"] --> D["Developer instructions"]
    D --> U["User request"]
    U -.-> A["Assistant response<br/>conversation content"]

This diagram is a beginner-friendly simplification, not the full model instruction specification. Platform-level rules can outrank system messages.

4. Using the instructions parameter

The instructions parameter is a convenient way to provide high-level guidance separately from the user’s input.

Bash
from dotenv import load_dotenv
from openai import OpenAI

load_dotenv()
client = OpenAI()

response = client.responses.create(
    model="gpt-4.1-mini",
    instructions="You are a patient Python tutor. Explain concepts to beginners.",
    input="What is a Python decorator?",
)

print(response.output_text)

The instructions argument supplies system/developer-level guidance for this request. The input argument supplies the question. Keeping them separate makes the application easier to understand and maintain. Instructions passed to one request should not be assumed to carry over automatically to later requests, including those that use previous_response_id.

5. Simple input versus structured messages

For a single question, a string is often easiest:

Bash
response = client.responses.create(
    model="gpt-4.1-mini",
    input="Explain a Python dictionary.",
)

When you want explicit message roles, pass a list:

Bash
response = client.responses.create(
    model="gpt-4.1-mini",
    input=[
        {
            "role": "developer",
            "content": "Use beginner-friendly language and one short example.",
        },
        {
            "role": "user",
            "content": "Explain a Python dictionary.",
        },
    ],
)

print(response.output_text)

Both are useful. Choose the simplest structure that communicates the task clearly, and avoid repeating conflicting directions across instructions and input messages.

6. Writing effective instructions

Good instructions describe the intended role, objective, constraints, and output expectations. For example:

  • Role: Act as a beginner-friendly Python tutor.
  • Objective: Explain one concept accurately.
  • Constraints: Avoid unnecessary jargon.
  • Output format: Include one short code example.

You can express these together in a readable Python string:

Bash
instructions = (
    "You are a Python tutor for beginners. "
    "Explain the concept in plain English, avoid unnecessary jargon, "
    "and include one short Python example."
)

response = client.responses.create(
    model="gpt-4.1-mini",
    instructions=instructions,
    input="What is a list comprehension?",
)

print(response.output_text)

These instructions make the desired answer clearer without guaranteeing exact wording or formatting.

7. Compare different instructions

A simple experiment is to ask the same question with different guidance:

Bash
question = "What is a Python generator?"

for style in [
    "Explain this to someone new to Python.",
    "Explain this to an experienced Python developer.",
]:
    response = client.responses.create(
        model="gpt-4.1-mini",
        instructions=style,
        input=question,
    )
    print("Style:", style)
    print(response.output_text)
    print("-" * 40)

8. Complete runnable example

Create main.py and install openai and python-dotenv in your active virtual environment if they are not already installed:

Bash
pip install --upgrade openai python-dotenv

Add a project-root .env file containing OPENAI_API_KEY=your_key_here and include .env in .gitignore. Do not commit real credentials.

Bash
from dotenv import load_dotenv
from openai import OpenAI

load_dotenv()
client = OpenAI()

messages = [
    {
        "role": "developer",
        "content": (
            "You are a Python tutor for beginners. "
            "Use plain English and provide one short code example."
        ),
    },
    {
        "role": "user",
        "content": "Explain the difference between a list and a tuple.",
    },
]

response = client.responses.create(
    model="gpt-4.1-mini",
    input=messages,
)

print(response.output_text)

Run the script from your terminal using python main.py. The developer message describes the teaching style, while the user message supplies the actual question. The model’s answer will vary; the code has not yet been live-tested in this editorial workflow.

9. Common mistakes

MistakeBetter approach
Mixing application instructions with every user promptUse instructions or developer messages for application guidance
Assuming user instructions override developer guidanceUnderstand role priority
Treating assistant history as authoritative commandsUse it as conversation context
Writing vague or conflicting directionsState clear, compatible requirements
Trusting instructions embedded in retrieved contentTreat external content as untrusted data
Assuming model output always follows the requested formatValidate outputs where reliability matters

10. Summary and next lesson

Messages identify who supplied content, roles clarify whether it represents high-level guidance, a user request, or earlier assistant output. The instructions parameter helps separate application behavior from the question being answered. These concepts provide the foundation for more reliable conversational applications.

In Blog 06, we’ll learn how to maintain conversation context across multiple API calls, including the trade-offs between sending message history and linking responses.

Leave a Reply

Your email address will not be published. Required fields are marked *