Both the system and developer are specified in the api reference for the role type and the docs mention these roles are their to provide instructions and context. The general consensus seems to be that you should have 1 system role message with high level behavior and purpose, and then potentially multiple developer role messages with additional content that could be dynamic, which is finally followed be a user role message. Im curious if there is any information that really explains the differences between these roles and how to use them. For instance, what if you were to just have multiple system role messages, would that have any downsides to one system message with multiple developer messages?
In a nutshell, the system role was degraded into developer role, being auto replaced if you specify system role at any prompt.
The behavior depends on what model you are using, so it is best to experiment in advance. Usually a first developer/system role at the very beginning is a common practice for higher priority commands.
You can read more here:
Got it, this is helpful to confirm my understanding. So can I just use one developer message first and then a sequence of user messages? is there a reason/use-case to having multiple developer messages?
Yes, that is how it usually goes.
As for an example of exception to this case, gpt-5 can be very resistant to produce markdown outputs. In this case, it recommends reinforcing the developer message every few turns as a way to prevent it to degrade.
“developer” is the only communication method you have on reasoning models.
Let’s say you have a crummy model that can’t pay attention or do the job, like GPT-5. You can intersperse the only authority you have that doesn’t look like it came from the user, with message injections.
(chat history - displaces attention to detail)
developer: The response to this next question MUST be produced in markdown, as your output is received by a native markdown-to-html renderer. No code fences.
user: make me a table…
I authored this with Jarvis, it is long but it is very interesting:
A great way of thinking about developer messages is that they allow us to “inject” system prompts mid agentic stream.
For typical systems that only need “ground rules once”, then instructions do fine, set them there and forget about it.
However some more sophisticated systems need a far more nuanced approach, the rules change mid conversations:
- dev message you are communicating to user on telegram, avoid markdown tables
- user: turn X into a table so I can see why it is faster
- assistant: replies without a table
- dev message you are communicating to user on web, use rich markdown
- user: try again
- assistant: lovely table rendered
Codex harness tends to lean on this kind of pattern.