From 98ccfa11bfee71e7f5784d03b8875221c818f1b2 Mon Sep 17 00:00:00 2001 From: Abbas Asad <168946441+Abbas-Asad@users.noreply.github.com> Date: Sun, 7 Sep 2025 04:13:44 +0500 Subject: [PATCH 1/2] Reorder hooks into chronological lifecycle order MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary This PR defines correct lifecycle order of hooks for both `RunHooksBase` and `AgentHooksBase`, aligning with the logical execution flow of an agent run. ## Changes Made I have simply **reordered the hooks** to reflect their chronological execution sequence during an agent run. ### RunHooksBase ``` on_agent_start on_llm_start on_llm_end on_tool_start on_tool_end on_handoff on_agent_end ``` ### AgentHooksBase ``` on_start on_llm_start on_llm_end on_tool_start on_tool_end on_handoff on_end ``` ## Enhancement - Establishes a clear and **logical sequence** for hook execution. - Improves developer understanding by reflecting the **actual lifecycle**: - **Start → LLM Call → Tool Call → Handoff (if any) → End** This ordering provides consistency and clarity to understand the correct agent execution flow. --- src/agents/lifecycle.py | 74 ++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/src/agents/lifecycle.py b/src/agents/lifecycle.py index 438f25d7a..396b90a92 100644 --- a/src/agents/lifecycle.py +++ b/src/agents/lifecycle.py @@ -15,6 +15,10 @@ class RunHooksBase(Generic[TContext, TAgent]): override the methods you need. """ + async def on_agent_start(self, context: RunContextWrapper[TContext], agent: TAgent) -> None: + """Called before the agent is invoked. Called each time the current agent changes.""" + pass + async def on_llm_start( self, context: RunContextWrapper[TContext], @@ -34,17 +38,23 @@ async def on_llm_end( """Called immediately after the LLM call returns for this agent.""" pass - async def on_agent_start(self, context: RunContextWrapper[TContext], agent: TAgent) -> None: - """Called before the agent is invoked. Called each time the current agent changes.""" + async def on_tool_start( + self, + context: RunContextWrapper[TContext], + agent: TAgent, + tool: Tool, + ) -> None: + """Called concurrently with tool invocation.""" pass - async def on_agent_end( + async def on_tool_end( self, context: RunContextWrapper[TContext], agent: TAgent, - output: Any, + tool: Tool, + result: str, ) -> None: - """Called when the agent produces a final output.""" + """Called after a tool is invoked.""" pass async def on_handoff( @@ -56,23 +66,13 @@ async def on_handoff( """Called when a handoff occurs.""" pass - async def on_tool_start( - self, - context: RunContextWrapper[TContext], - agent: TAgent, - tool: Tool, - ) -> None: - """Called concurrently with tool invocation.""" - pass - - async def on_tool_end( + async def on_agent_end( self, context: RunContextWrapper[TContext], agent: TAgent, - tool: Tool, - result: str, + output: Any, ) -> None: - """Called after a tool is invoked.""" + """Called when the agent produces a final output.""" pass @@ -88,24 +88,24 @@ async def on_start(self, context: RunContextWrapper[TContext], agent: TAgent) -> agent.""" pass - async def on_end( + async def on_llm_start( self, context: RunContextWrapper[TContext], - agent: TAgent, - output: Any, + agent: Agent[TContext], + system_prompt: Optional[str], + input_items: list[TResponseInputItem], ) -> None: - """Called when the agent produces a final output.""" + """Called immediately before the agent issues an LLM call.""" pass - async def on_handoff( + async def on_llm_end( self, context: RunContextWrapper[TContext], - agent: TAgent, - source: TAgent, + agent: Agent[TContext], + response: ModelResponse, ) -> None: - """Called when the agent is being handed off to. The `source` is the agent that is handing - off to this agent.""" - pass + """Called immediately after the agent receives the LLM response.""" + pass async def on_tool_start( self, @@ -126,23 +126,23 @@ async def on_tool_end( """Called after a tool is invoked.""" pass - async def on_llm_start( + async def on_handoff( self, context: RunContextWrapper[TContext], - agent: Agent[TContext], - system_prompt: Optional[str], - input_items: list[TResponseInputItem], + agent: TAgent, + source: TAgent, ) -> None: - """Called immediately before the agent issues an LLM call.""" + """Called when the agent is being handed off to. The `source` is the agent that is handing + off to this agent.""" pass - async def on_llm_end( + async def on_end( self, context: RunContextWrapper[TContext], - agent: Agent[TContext], - response: ModelResponse, + agent: TAgent, + output: Any, ) -> None: - """Called immediately after the agent receives the LLM response.""" + """Called when the agent produces a final output.""" pass From cbfcabbd459fc20fd0dddea4ee2d7a8a589c28f4 Mon Sep 17 00:00:00 2001 From: Abbas Asad <168946441+Abbas-Asad@users.noreply.github.com> Date: Wed, 10 Sep 2025 01:34:30 +0500 Subject: [PATCH 2/2] Fix lint errors and update branch Resolved all CI linting errors in lifecycle.py to comply with project style guidelines and unblock the failing lint check in CI. --- src/agents/lifecycle.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/agents/lifecycle.py b/src/agents/lifecycle.py index 396b90a92..324a401af 100644 --- a/src/agents/lifecycle.py +++ b/src/agents/lifecycle.py @@ -17,8 +17,8 @@ class RunHooksBase(Generic[TContext, TAgent]): async def on_agent_start(self, context: RunContextWrapper[TContext], agent: TAgent) -> None: """Called before the agent is invoked. Called each time the current agent changes.""" - pass - + pass + async def on_llm_start( self, context: RunContextWrapper[TContext], @@ -105,7 +105,7 @@ async def on_llm_end( response: ModelResponse, ) -> None: """Called immediately after the agent receives the LLM response.""" - pass + pass async def on_tool_start( self,