Skip to content

Conversation

@adtyavrdhn
Copy link
Contributor

@adtyavrdhn adtyavrdhn commented Dec 6, 2025

Add return_kind field and customizable prompt templates

This PR introduces two major changes to PydanticAI's messaging and agent configuration system:

1. return_kind field on ToolReturnPart

Added a new return_kind field to ToolReturnPart that disambiguates how a tool call was resolved:

  • 'tool-executed': Tool ran successfully and produced a return value
  • 'final-result-processed': An output tool produced the run's final result
  • 'output-tool-not-executed': An output tool was skipped because a final result already existed
  • 'function-tool-not-executed': A function tool was skipped due to early termination after a final result
  • 'tool-denied': The tool call was rejected by an approval handler

2. Customizable Prompt Templates

Introduced a new PromptTemplates class that allows users to customize system-injected messages that PydanticAI sends to models:

from pydantic_ai import Agent
from pydantic_ai.messages import PromptTemplates

agent = Agent(
    'openai:gpt-4',
    prompt_templates=PromptTemplates(
        retry_prompt="Please fix these errors: {errors}",
        final_result_processed="Result captured successfully",
        output_tool_not_executed="Skipped - result already found",
        function_tool_not_executed="Tool skipped - operation complete"
    )
)

Each template can be either:

  • A static string for simple customization
  • A callable (part, RunContext) -> str for dynamic, context-aware messages

Templates available:

  • retry_prompt: Sent after validation failures or invalid responses
  • final_result_processed: Confirmation when a final result is successfully processed
  • output_tool_not_executed: Message when an output tool call is skipped
  • function_tool_not_executed: Message when a function tool call is skipped

Integration points:

The prompt_templates parameter has been added throughout the agent system:

  • Agent constructor: Agent(..., prompt_templates=...)
  • Run methods: agent.run(..., prompt_templates=...) - allows per-run overrides
  • All execution modes: run(), run_sync(), run_stream(), run_stream_events(), iter()
  • Override context manager: agent.override(prompt_templates=...)
  • All agent types: Standard Agent, WrappedAgent, DBOSAgent, PrefectAgent, TemporalAgent

Templates are applied right before messages are sent to the model, with RetryPromptPart storing the compiled template in its new retry_template field.

@adtyavrdhn adtyavrdhn marked this pull request as ready for review December 6, 2025 11:42
@adtyavrdhn
Copy link
Contributor Author

@DouweM Please take a look whenever you get some time, I have not added a retry-kind on RetryPromptPart because regardless of the way we reach we do end up with the same default string at the end that is "Fix and try again". So I think covering this does the job for us.

Would you say knowing why this particular RetryPromptPart is being fired off(with a separate field) is worth it on its own as well, I can take that up as a separate PR or in this one as well if we think there is enough use case to warrant it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant