This document explores the powerful technique of using a dynamic system prompt to control an AI agent's behavior at runtime. We'll break down the Python script examples-basic-dynamic-system-prompt.py, which showcases how to change an AI's personality on the fly, making interactions more engaging, personalized, and adaptable.
A typical AI agent operates on a fixed "system prompt" or a set of instructions that defines its persona, goals, and constraints. For example, "You are a helpful assistant." While effective, this is static.
The real magic begins when the system prompt becomes dynamic. Instead of a fixed string, we can use a function that generates the instructions based on the immediate context of the conversation. This allows a single agent to adopt multiple personas, switching from a pirate to a robot to a poet in an instant.
Let's dissect the script to see how this is achieved.
CustomContext: Defining the PersonaThe first step is to create a way to signal which persona the agent should adopt. A simple dataclass is perfect for this:
@dataclass
class CustomContext:
style: Literal["haiku", "pirate", "robot"]This CustomContext class holds a style attribute, which will be our switch for changing the agent's behavior.
custom_instructions Function: The Brain of the OperationThis function is the heart of the dynamic behavior. It takes the runtime context and generates the appropriate system prompt.
def custom_instructions(
run_context: RunContextWrapper[CustomContext], agent: Agent[CustomContext]
) -> str:
context = run_context.context
if context.style == "haiku":
return "Only respond in haikus."
elif context.style == "pirate":
return "Respond as a pirate."
else:
return "Respond as a robot and say 'beep boop' a lot."Notice how it inspects context.style and returns a different instruction string for each case. This function is called every time the agent runs, ensuring the instructions are always fresh and relevant to the current context.
When creating the agent, instead of passing a static string to the instructions parameter, we pass a reference to our custom_instructions function.
agent = Agent(
name="Chat agent",
instructions=custom_instructions,
)This tells the Agent to call our function to get its instructions, rather than using a hardcoded value.
main Function: Putting It All TogetherThe main execution block demonstrates the runtime nature of this pattern.
async def main():
# 1. A random style is chosen for each run
context = CustomContext(style=random.choice(["haiku", "pirate", "robot"]))
print(f"Using style: {context.style}\n")
user_message = "Tell me a joke."
print(f"User: {user_message}")
# 2. The context is passed to the Runner
result = await Runner.run(agent, user_message, context=context)
print(f"Assistant: {result.final_output}")In each execution, a new CustomContext is created with a randomly selected style. This context is then passed into Runner.run(), which in turn makes it available to our custom_instructions function.
The script's output perfectly illustrates the power of this approach. For the exact same user input ("Tell me a joke."), the agent's response is dramatically different depending on the randomly chosen style.
If style is "pirate":
User: Tell me a joke.
Assistant: Arrr, why did the pirate go to the seafood restaurant?
Fer the *fish ‘n’ ships*, matey! Yarrr! 🏴☠️If style is "haiku":
User: Tell me a joke.
Assistant: Why did the grape run?
It didn’t want to be squashed—
Wine takes time and sun.If style is "robot":
User: Tell me a joke.
Assistant: Beep boop! Initiating humor protocol. Beep boop!
Why did the computer go to the doctor? Beep boop...
Because it had a virus! Beep boop beep boop!This technique unlocks a new level of sophistication for AI agents:
By replacing static instruction strings with dynamic instruction functions, we can build agents that are more intelligent, adaptable, and ultimately, more useful.
To see it in action, simply run the following command in your terminal:
python examples-basic-dynamic-system-prompt.py