word_count_of_output told you how long the response is. But what if you want the agent to always produce exactly two sentences — not because the prompt says so, but because every call obeys a standing instruction?
I'd add 'respond in two sentences' to every prompt? That feels fragile — I might forget it somewhere.
system_prompt solves that. It's a constructor argument on Agent — every call that agent makes obeys it, automatically:
agent = Agent(model, system_prompt="Summarize in 2 sentences.")
result = agent.run_sync(text)What's the difference between putting the instruction in system_prompt versus just prepending it to the user prompt?
The system prompt is the scope-of-work brief to the model — it defines the agent's role. The user prompt is the actual task. Separating them keeps your code readable and makes it trivial to swap the task without changing the role. A summariser agent always summarises; only what it summarises changes.
def summarize_text(text: str) -> str:
agent = Agent(model, system_prompt="Summarize in 2 sentences.")
return agent.run_sync(text).outputSo I can make a dedicated summariser, a dedicated classifier, a dedicated extractor — each just a different system prompt?
That's the whole model. Each agent is a function with a personality. The tighter the system prompt, the fewer revision rounds you'll need.
'The tighter it is, the fewer revision rounds' — that's exactly how I write scope-of-work docs for subcontractors.
Same principle, same payoff. The sub-contractor (model) works to spec. You review the output, not the process.
system_prompt as a Standing Instructionsystem_prompt is passed to Agent(model, system_prompt=...) — not to .run_sync(). It applies to every call that agent makes.
agent = Agent(model, system_prompt="Summarize in 2 sentences.")
agent.run_sync("Long text here...").output # always 2 sentences
agent.run_sync("Different long text...").output # always 2 sentencesThink of system_prompt as the scope-of-work brief: it defines what the agent does. The run_sync argument is the actual task: it defines what the agent does it to. Changing one does not affect the other.
word_count_of_output told you how long the response is. But what if you want the agent to always produce exactly two sentences — not because the prompt says so, but because every call obeys a standing instruction?
I'd add 'respond in two sentences' to every prompt? That feels fragile — I might forget it somewhere.
system_prompt solves that. It's a constructor argument on Agent — every call that agent makes obeys it, automatically:
agent = Agent(model, system_prompt="Summarize in 2 sentences.")
result = agent.run_sync(text)What's the difference between putting the instruction in system_prompt versus just prepending it to the user prompt?
The system prompt is the scope-of-work brief to the model — it defines the agent's role. The user prompt is the actual task. Separating them keeps your code readable and makes it trivial to swap the task without changing the role. A summariser agent always summarises; only what it summarises changes.
def summarize_text(text: str) -> str:
agent = Agent(model, system_prompt="Summarize in 2 sentences.")
return agent.run_sync(text).outputSo I can make a dedicated summariser, a dedicated classifier, a dedicated extractor — each just a different system prompt?
That's the whole model. Each agent is a function with a personality. The tighter the system prompt, the fewer revision rounds you'll need.
'The tighter it is, the fewer revision rounds' — that's exactly how I write scope-of-work docs for subcontractors.
Same principle, same payoff. The sub-contractor (model) works to spec. You review the output, not the process.
system_prompt as a Standing Instructionsystem_prompt is passed to Agent(model, system_prompt=...) — not to .run_sync(). It applies to every call that agent makes.
agent = Agent(model, system_prompt="Summarize in 2 sentences.")
agent.run_sync("Long text here...").output # always 2 sentences
agent.run_sync("Different long text...").output # always 2 sentencesThink of system_prompt as the scope-of-work brief: it defines what the agent does. The run_sync argument is the actual task: it defines what the agent does it to. Changing one does not affect the other.
Create a free account to get started. Paid plans unlock all tracks.