feat: Add Agent Hooks#11747
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Coverage reportClick to see where and how coverage changed
This report was generated by python-coverage-comment-action |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Defaults to 4. Set to 1 to disable parallel tool execution. | ||
| :param tool_streaming_callback_passthrough: If True, pass the streaming callback to tools that accept it. | ||
| :param confirmation_strategies: A dictionary mapping tool names to ConfirmationStrategy instances. | ||
| :param hooks: A dictionary mapping a lifecycle event to a list of hooks the Agent runs at that point. Valid |
There was a problem hiding this comment.
I see we refer to lifecycle events here and there. Since this might be confused with the warm_up/close topic (also in docs), could we find another option?
I am thinking of something like agent event, hook point, ..
There was a problem hiding this comment.
Done in 1c847d1
I've decided to go with hook point. Will mull over it over the weekend to see if I still like it or something else :D
| count_before = len(exe_context.state.data.get("messages") or []) | ||
| _run_hooks(self.hooks, ON_EXIT, exe_context.state) | ||
| new_messages = (exe_context.state.data.get("messages") or [])[count_before:] | ||
| return bool(new_messages) and not self._messages_trigger_exit(new_messages) |
There was a problem hiding this comment.
the exit part is the most difficult one and I am not sure I got it right (we might want to do something to simplify the code; not this function but the whole handling).
My impression is that this logic assumes that hooks append only, while they might also rewrite history.
One idea could be documenting this or implementing a different mechanism (a continue_run State key?).
There was a problem hiding this comment.
My impression is that this logic assumes that hooks append only, while they might also rewrite history.
Ahh right good catch. An explicit key would make it easier and more declarative. And I was already thinking about adding other flow control keys like this like a should_exit: bool if a hook (i.e. a BudgetHook) decides that the Agent should stop since a budget has been exceeded. Or if we were to add an after_llm hook adding something like a rerun_llm: bool key could be useful if the user wants to trigger the LLM again if the reply was unsatisfactory for some reason.
So I'd probably lean towards adding the continue_run key. Maybe nest it under a flow_control or loop_control State entry so it's easier for us to add more keys like this in the future. WDYT?
There was a problem hiding this comment.
Ok to add it if it makes the behavior simpler and more robust.
|
@sjrl I was wondering about Tool result offloading (hooks can work for this?), then I found https://github.com/deepset-ai/haystack-private/issues/405#issuecomment-4797946676 🙂 Also, since I'll be off next week, feel free to merge this PR once Julian approves it. |
Related Issues
Proposed Changes:
Added lifecycle hooks to the
Agent. Passhooksas a dictionary mapping a lifecycle event to a list of hooks the Agent runs at that point:before_llm(before each chat-generator call),before_tool(after the model requests tool calls, before they run), andon_exit(when the Agent is about to stop). Each hook receives the liveStateand influences the run by mutating it in place; hooks for an event run in list order, and the same hook can be registered under multiple events.A hook is any object with a
run(state)method (optionallyrun_async(state)); use the@hookdecorator to build one from a function. This enables patterns such as building run-time system context, retrieving memories, and requiring a tool to be called before finishing. Anon_exithook can keep the Agent running by appending a message that is no longer a valid exit, since the exit condition is re-evaluated after the hooks run.The example below registers one hook at each placement to show what each can do:
Class-based hooks may also implement the optional lifecycle methods
warm_up/warm_up_asyncandclose/close_async. The Agent calls them from its ownwarm_up/warm_up_asyncandclose/close_async, so a hook can defer opening clients or reading credentials until warm-up and release them on close. For example, anon_exithook can grade the Agent's answer with its own LLM and ask it to improve a weak answer before finishing, warming the judge's client during the Agent's warm-up:How did you test it?
New tests
Notes for the reviewer
Checklist
fix:,feat:,build:,chore:,ci:,docs:,style:,refactor:,perf:,test:and added!in case the PR includes breaking changes.