word_count_of_output exposed something: the count varies wildly across calls. A 12-word answer. A 200-word answer. Same prompt, same model. Why?
Because the model is sampling, not looking something up. No instruction told it how long the answer should be.
Exactly. Agent(model).run_sync(text) is a blank brief — the model fills in length, tone, and structure itself. When you add a system prompt, you put your requirements at the top of that brief. The model must follow them:
agent = Agent(model, system_prompt="Summarize in 2 sentences.")
result = agent.run_sync(text)
return result.outputBut it's still a language model. What stops it from writing four sentences anyway?
Nothing guaranteed — that's an important point. System prompts are instructions, not hard constraints. For strict shapes, you'll use result_type later. For length and style guidance, a clear, direct system prompt is reliable enough for production triage work. Concise instructions work better than polite ones: "Summarize in 2 sentences" beats "Please try to keep your summary fairly short."
def summarize_text(text: str) -> str:
agent = Agent(model, system_prompt="Summarize in 2 sentences.")
result = agent.run_sync(text)
return result.outputIt wrote a full summary in one call? Of the whole meeting transcript — two sentences, right on spec?
That's the system prompt doing exactly what a good brief does: setting the constraint up front so the model doesn't have to guess what you want. The tab-and-paste workflow produces a different length every time. This produces a predictable shape every time.
So system_prompt= is literally the instruction line I used to put at the top of a ChatGPT message — except now it's code I can reuse across every summarisation call.
That's the entire pattern. Next, you'll use the same system prompt idea to return a single word instead of a paragraph — which is where classification starts.
Agent(model, system_prompt=...) sets a persistent instruction applied to every .run_sync() call on that agent. Think of it as the brief you send before handing off the task.
Effective system prompts are direct and specific. "Summarize in 2 sentences." works. "Please try to keep your response somewhat concise if possible." does not reliably constrain output length.
System prompts are strong guidance, not hard constraints. For values that must be exactly one of a fixed set (urgency labels, sentiment scores), use result_type=Literal[...] instead. System prompts are the right tool for length, tone, and format guidance.
Creating a new Agent(...) inside every call is correct and intentional — agents are lightweight and stateless in PydanticAI. There is no connection to close or pool to manage.
word_count_of_output exposed something: the count varies wildly across calls. A 12-word answer. A 200-word answer. Same prompt, same model. Why?
Because the model is sampling, not looking something up. No instruction told it how long the answer should be.
Exactly. Agent(model).run_sync(text) is a blank brief — the model fills in length, tone, and structure itself. When you add a system prompt, you put your requirements at the top of that brief. The model must follow them:
agent = Agent(model, system_prompt="Summarize in 2 sentences.")
result = agent.run_sync(text)
return result.outputBut it's still a language model. What stops it from writing four sentences anyway?
Nothing guaranteed — that's an important point. System prompts are instructions, not hard constraints. For strict shapes, you'll use result_type later. For length and style guidance, a clear, direct system prompt is reliable enough for production triage work. Concise instructions work better than polite ones: "Summarize in 2 sentences" beats "Please try to keep your summary fairly short."
def summarize_text(text: str) -> str:
agent = Agent(model, system_prompt="Summarize in 2 sentences.")
result = agent.run_sync(text)
return result.outputIt wrote a full summary in one call? Of the whole meeting transcript — two sentences, right on spec?
That's the system prompt doing exactly what a good brief does: setting the constraint up front so the model doesn't have to guess what you want. The tab-and-paste workflow produces a different length every time. This produces a predictable shape every time.
So system_prompt= is literally the instruction line I used to put at the top of a ChatGPT message — except now it's code I can reuse across every summarisation call.
That's the entire pattern. Next, you'll use the same system prompt idea to return a single word instead of a paragraph — which is where classification starts.
Agent(model, system_prompt=...) sets a persistent instruction applied to every .run_sync() call on that agent. Think of it as the brief you send before handing off the task.
Effective system prompts are direct and specific. "Summarize in 2 sentences." works. "Please try to keep your response somewhat concise if possible." does not reliably constrain output length.
System prompts are strong guidance, not hard constraints. For values that must be exactly one of a fixed set (urgency labels, sentiment scores), use result_type=Literal[...] instead. System prompts are the right tool for length, tone, and format guidance.
Creating a new Agent(...) inside every call is correct and intentional — agents are lightweight and stateless in PydanticAI. There is no connection to close or pool to manage.
Create a free account to get started. Paid plans unlock all tracks.