You want the same agent to always behave a specific way — a summarizer, say, or a translator. Where would you put those instructions?
Every time in the prompt? Start each call with "Please summarize..."?
That works but is fragile. Agent(model, system_prompt=...) accepts a fixed instruction the model reads before every user message. The system prompt is baked in once, and run_sync carries only the variable content:
agent = Agent(model, system_prompt="Summarize the following text in 2 sentences. Return only the summary.")
result = agent.run_sync(long_text)System prompt says what the agent is. The run_sync argument says what to work on right now.
So system_prompt is the job description, and the run_sync input is the task for that run?
Exactly. The model concatenates them internally and treats the system prompt as instructions rather than content to process. That structural separation matters — it keeps the model from confusing your directions with the text you want summarized:
def summarize_text(text: str) -> str:
agent = Agent(model, system_prompt="Summarize the following text in 2 sentences. Return only the summary.")
return agent.run_sync(text).outputWhy "Return only the summary" in the prompt? Is that just being polite?
Without it the model may prefix its answer with "Here's a summary:" or ask a follow-up question. The explicit "return only" framing trims the preamble. Every production summarizer prompt has some version of that line.
So I can spin up a classifier, a translator, a tone-rewriter — each one is just a new Agent with a different system_prompt?
That is the pattern. Same model, same call shape, a different personality per agent. Now write summarize_text(text) — create the agent with the system prompt from the example, run it on the input, return .output as a string.
TL;DR: system_prompt is set once at construction; the run_sync argument changes every call.
Agent(model, system_prompt=...) — fixed instructions the model always seesagent.run_sync(text) — the variable content for this specific call| Changes per call? | Use |
|---|---|
| No — role, tone, format | system_prompt |
| Yes — today's text, query | run_sync argument |
Add "Return only the summary." to trim model preambles like "Here is a summary:" that would otherwise leak through.
You want the same agent to always behave a specific way — a summarizer, say, or a translator. Where would you put those instructions?
Every time in the prompt? Start each call with "Please summarize..."?
That works but is fragile. Agent(model, system_prompt=...) accepts a fixed instruction the model reads before every user message. The system prompt is baked in once, and run_sync carries only the variable content:
agent = Agent(model, system_prompt="Summarize the following text in 2 sentences. Return only the summary.")
result = agent.run_sync(long_text)System prompt says what the agent is. The run_sync argument says what to work on right now.
So system_prompt is the job description, and the run_sync input is the task for that run?
Exactly. The model concatenates them internally and treats the system prompt as instructions rather than content to process. That structural separation matters — it keeps the model from confusing your directions with the text you want summarized:
def summarize_text(text: str) -> str:
agent = Agent(model, system_prompt="Summarize the following text in 2 sentences. Return only the summary.")
return agent.run_sync(text).outputWhy "Return only the summary" in the prompt? Is that just being polite?
Without it the model may prefix its answer with "Here's a summary:" or ask a follow-up question. The explicit "return only" framing trims the preamble. Every production summarizer prompt has some version of that line.
So I can spin up a classifier, a translator, a tone-rewriter — each one is just a new Agent with a different system_prompt?
That is the pattern. Same model, same call shape, a different personality per agent. Now write summarize_text(text) — create the agent with the system prompt from the example, run it on the input, return .output as a string.
TL;DR: system_prompt is set once at construction; the run_sync argument changes every call.
Agent(model, system_prompt=...) — fixed instructions the model always seesagent.run_sync(text) — the variable content for this specific call| Changes per call? | Use |
|---|---|
| No — role, tone, format | system_prompt |
| Yes — today's text, query | run_sync argument |
Add "Return only the summary." to trim model preambles like "Here is a summary:" that would otherwise leak through.
Create a free account to get started. Paid plans unlock all tracks.