Skip to content

Commit 72ee2d2

Browse files
committed
Add AgentRun.{all,new}_messages
This allows convenient access to these even if the run didn't end, at which point they would not be available via `AgentRun.result`.
1 parent 4cc4f35 commit 72ee2d2

File tree

2 files changed

+75
-0
lines changed

2 files changed

+75
-0
lines changed

pydantic_ai_slim/pydantic_ai/run.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,36 @@ def result(self) -> AgentRunResult[OutputDataT] | None:
135135
self._traceparent(required=False),
136136
)
137137

138+
def all_messages(self) -> list[_messages.ModelMessage]:
139+
"""Return all messages for the run so far.
140+
141+
Messages from older runs are included.
142+
"""
143+
return self.ctx.state.message_history
144+
145+
def all_messages_json(self, *, output_tool_return_content: str | None = None) -> bytes:
146+
"""Return all messages from [`all_messages`][pydantic_ai.agent.AgentRun.all_messages] as JSON bytes.
147+
148+
Returns:
149+
JSON bytes representing the messages.
150+
"""
151+
return _messages.ModelMessagesTypeAdapter.dump_json(self.all_messages())
152+
153+
def new_messages(self) -> list[_messages.ModelMessage]:
154+
"""Return new messages for the run so far.
155+
156+
Messages from older runs are excluded.
157+
"""
158+
return self.all_messages()[self.ctx.deps.new_message_index :]
159+
160+
def new_messages_json(self) -> bytes:
161+
"""Return new messages from [`new_messages`][pydantic_ai.agent.AgentRun.new_messages] as JSON bytes.
162+
163+
Returns:
164+
JSON bytes representing the new messages.
165+
"""
166+
return _messages.ModelMessagesTypeAdapter.dump_json(self.new_messages())
167+
138168
def __aiter__(
139169
self,
140170
) -> AsyncIterator[_agent_graph.AgentNode[AgentDepsT, OutputDataT] | End[FinalResult[OutputDataT]]]:

tests/test_agent.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5807,3 +5807,48 @@ def test_agent_builtin_tools_runtime_vs_agent_level():
58075807
MCPServerTool(id='example', url='https://mcp.example.com/mcp'),
58085808
]
58095809
)
5810+
5811+
5812+
async def test_message_history():
5813+
def llm(messages: list[ModelMessage], _info: AgentInfo) -> ModelResponse:
5814+
return ModelResponse(parts=[TextPart('ok here is text')])
5815+
5816+
agent = Agent(FunctionModel(llm))
5817+
5818+
async with agent.iter(
5819+
message_history=[
5820+
ModelRequest(parts=[UserPromptPart(content='Hello')]),
5821+
],
5822+
) as run:
5823+
async for _ in run:
5824+
pass
5825+
assert run.new_messages() == snapshot(
5826+
[
5827+
ModelResponse(
5828+
parts=[TextPart(content='ok here is text')],
5829+
usage=RequestUsage(input_tokens=51, output_tokens=4),
5830+
model_name='function:llm:',
5831+
timestamp=IsDatetime(),
5832+
),
5833+
]
5834+
)
5835+
assert run.new_messages_json().startswith(b'[{"parts":[{"content":"ok here is text",')
5836+
assert run.all_messages() == snapshot(
5837+
[
5838+
ModelRequest(
5839+
parts=[
5840+
UserPromptPart(
5841+
content='Hello',
5842+
timestamp=IsDatetime(),
5843+
)
5844+
]
5845+
),
5846+
ModelResponse(
5847+
parts=[TextPart(content='ok here is text')],
5848+
usage=RequestUsage(input_tokens=51, output_tokens=4),
5849+
model_name='function:llm:',
5850+
timestamp=IsDatetime(),
5851+
),
5852+
]
5853+
)
5854+
assert run.all_messages_json().startswith(b'[{"parts":[{"content":"Hello",')

0 commit comments

Comments
 (0)