-
Notifications
You must be signed in to change notification settings - Fork 21
feat: Add utilities for converting tools into human-in-the-loop tools #368
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Pull Request Test Coverage Report for Build 17762784085Details
💛 - Coveralls |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the overall idea and left a few comments.
About where to add this: maybe experimental + a notebook in cookbook (your example + explanations) might work while we get feedback and refine the design.
|
||
from typing import TYPE_CHECKING, Any, Protocol | ||
|
||
if TYPE_CHECKING: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is done to avoid circular imports or for other reasons?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah circular imports. I'll double check it's actually needed and leave a comment if it is
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The idea makes sense to me on the higher level. As Haystack users will rarely use tools with HITL without an Agent, I still wonder if users would like it more if they could do the HITL settings in the Agent instead of each tool. As an alternative to your implementation.
One could argue that a user doesn't really want to change the tool but they want to change how the agent is allowed to use the tool.
agent = Agent(
chat_generator=OpenAIChatGenerator(model="gpt-4.1"),
tools=[balance_tool, some_other_tool],
hitl=[HITLSettings(
confirmation_strategy=ConsoleInput(),
confirmation_policy=AlwaysAsk(),
),
HITLSettings(
confirmation_strategy=ConsoleInput(),
confirmation_policy=AskOnce(),
)],
system_prompt="""...""",
)
or, assuming for a moment that an agent never needs multiples confirmation strategies:
agent = Agent(
chat_generator=OpenAIChatGenerator(model="gpt-4.1"),
tools=[balance_tool, some_other_tool, a_third_tool],
confirmation_strategy=ConsoleInput(),
confirmation_policies=[AlwaysAsk, AskOnce, NeverAsk],
system_prompt="""...""",
)
|
||
class DefaultPolicy: | ||
""" | ||
Default execution policy: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I read policy, I first thought this is a choice between AlwaysAsk, AskOnce, NeverAsk. Here, the user is always asked.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I gotcha, would a rename to AlwaysAskPolicy help make it more clear?
@julian-risch I was just thinking about this as an alternative this morning. This would also solve the other issue I was having which is how could we also support serialization which isn't really easily doable with the approach I have currently. This would definitely solve that. I'll give a look over your idea! |
Closing in favor of #369 |
Related Issues
Proposed Changes:
This PR introduces a human-in-the-loop (HITL) mechanism for tool execution in Haystack, allowing users to confirm, reject, or modify tool invocations interactively.
haystack_experimental/tools/human_in_the_loop.py
ConfirmationResult
dataclass to capture user decisions.RichConsolePrompt
andSimpleInputPrompt
for interactive confirmation via Rich or standard input.DefaultPolicy
andAutoConfirmPolicy
for handling user responses.confirmation_wrapper
to wrap any tool with HITL logic.haystack_experimental/tools/types/protocol.py
ConfirmationPrompt
andExecutionPolicy
protocols to allow users to easily customize how their HITL Tools should work.How did you test it?
Provided an example script called
hitl_example.py
which shows how to use these new utility functions to convert existing tools into ones that ask for confirmation. I've also reproduced it hereNotes for the reviewer
I'd appreciate some guidance on the best place to add this to Haystack. I'm unsure if this should become a part of the main library or if this would be better served in a cookbook or a tutorial.
The nature of Human in the Loop confirmations I believe can become quite custom which is why I found it difficult to create a generic pattern. I attempted to do this by creating the Protocols
ConfirmationPrompt
andExecutionPolicy
so users could easily customize how their Human in the Loop tools would work.Checklist
fix:
,feat:
,build:
,chore:
,ci:
,docs:
,style:
,refactor:
,perf:
,test:
.