Repository navigation
Releases
v2.31.1
v2.31.1-rc1
Release Notes
v2.31.1-rc1
Bug Fixes
- THIS WILL LAND IN 2.31.1
v3.1.0
Release Notes
v3.1.0
New Features
- NEW SHINY FEATURE FOR HAYSTACK 3.1.0
Bug Fixes
- BUGFIX THAT GOES INTO RC2
- BOOM! NEW IMPORTANT BUGFIX TO INCLUDE IN 3.0.1
v3.1.0-rc1
Release Notes
v3.1.0-rc1
New Features
- NEW SHINY FEATURE FOR HAYSTACK 3.1.0
Bug Fixes
- BUGFIX THAT GOES INTO RC2
- BOOM! NEW IMPORTANT BUGFIX TO INCLUDE IN 3.0.1
v3.0.1
Release Notes
v3.0.1
Bug Fixes
- BOOM! NEW IMPORTANT BUGFIX TO INCLUDE IN 3.0.1
v3.0.1-rc1
Release Notes
v3.0.1-rc1
Bug Fixes
- BOOM! NEW IMPORTANT BUGFIX TO INCLUDE IN 3.0.1
v3.0.0
Release Notes
v3.0.0
Upgrade Notes
-
AsyncPipelinehas been removed. Its asynchronous capabilities are now part of the singlePipelineclass, which provides both a synchronousrunmethod and the asynchronousrun_async,run_async_generator, andstreammethods (mirroring how components exposerunandrun_async).To migrate, replace
AsyncPipelinewithPipeline:# Before from haystack import AsyncPipeline pipeline = AsyncPipeline() result = await pipeline.run_async(data) # After from haystack import Pipeline pipeline = Pipeline() result = await pipeline.run_async(data)
Serialized pipelines,
SuperComponents, andPipelineTools are loaded asPipelineinstances.Pipeline.runruns synchronously and blocks until completion; in an async context useawait pipeline.run_async(...). The formerAsyncPipeline.runwas a synchronous wrapper around the concurrent engine, so to preserve that behavior useasyncio.run(pipeline.run_async(...)). Note thatPipeline.runexecutes components sequentially and does not acceptconcurrency_limit.Both synchronous and asynchronous runs are traced under a single
haystack.pipeline.runoperation name, distinguished by ahaystack.pipeline.execution_modetag (syncorasync). Previously, asynchronous runs used thehaystack.async_pipeline.runoperation name. -
continue_runis now a reserved key inAgent.state_schema(set by anon_exithook to keep the Agent running). Passing it via thestate_schemaargument now raisesValueError. Rename any conflicting state key (e.g.my_continue_run) to migrate. -
DocumentNDCGEvaluatornow matches documents by theircontentfield by default instead of their auto-generatedid. Previously, ground truth and retrieved documents were matched only if they had identicalidvalues, which rarely happened in practice since IDs are generated independently for each Document instance. As a result, NDCG scores computed with this evaluator may change for existing pipelines. To keep the previousid-based matching behavior, passdocument_comparison_field="id"when constructing the evaluator. -
Agentno longer validatesexit_conditionsagainst tool names at initialization. Exit conditions are now evaluated at runtime, so a condition naming a tool that is loaded later — e.g. a tool passed at runtime or one discovered bySearchableToolset— works as expected. Consequently, an unknown exit-condition name no longer raises aValueErrorat construction. -
Tool support is now validated against the tools resolved for each run, not only the tools provided at initialization. Passing tools at runtime via
run(tools=...)to a chat generator that does not support tools now raises aTypeErrorinstead of silently ignoring them. -
Components in Haystack that use external resources now consistently create those resources during warm-up rather than in
__init__. As a result, some components that previously raised errors during initialization (for example, because of a missing API key) now raise them duringwarm_upinstead. Similar changes will be rolled out to components in Haystack Core Integrations in the future. -
step_count,token_usage, andtool_call_countsare now reserved keys inAgent.state_schema. Passing any of them via thestate_schemaargument now raisesValueError. Rename the conflicting state key (e.g.my_token_usage) to migrate. -
GeneratedAnswerandExtractedAnswernow serialize to the same flat format as all other Haystack dataclasses (Document,ChatMessage, etc.). This is a breaking change:to_dict()no longer wraps the fields in the{"type": "...", "init_parameters": {...}}envelope and instead returns the fields at the top level. Any code or stored artifact that reads the serialized output and expects thetype/init_parameterskeys must be updated to read the fields directly. Deserialization is backward compatible:from_dict()accepts both the new flat format and the old wrapped{"type": "...", "init_parameters": {...}}format, so existing pipeline snapshots, breakpoints, andStateobjects keep loading without any changes. -
Confirmation strategies now receive the model-requested tool arguments in
tool_paramsrather than the fully-prepared arguments. Values injected fromStatevia a tool'sinputs_from_statemapping (and theStateobject injected intoState-typed parameters) are no longer included in what is presented for confirmation — that injection now happens only at tool execution time. If yourConfirmationUIorConfirmationPolicydisplayed or inspected those state-injected values, it will now see only the arguments the model provided. -
The hash used to auto-generate
Document.idis now computed from a canonical (key-sorted) JSON serialization ofmeta. Documents with emptymetaare unaffected, but most other documents will get different IDs than they did before:- documents with non-empty
meta(the serialization changes fromdict's repr to JSON); - documents whose
metacontains non-JSON-serializable values such asdatetimeor custom classes (these are now serialized viastr(...)rather thanrepr(...), e.g."2024-01-01 00:00:00"instead of"datetime.datetime(2024, 1, 1, 0, 0)").
If you rely on auto-generated IDs to match documents already persisted in a
DocumentStore, you will need to re-ingest the affected documents (or pass the previousidexplicitly when constructing theDocument). - documents with non-empty
-
Pipeline deserialization (
Pipeline.load/Pipeline.loads/Pipeline.from_dict) now refuses to import classes from modules outside a trusted-module allowlist. By default the allowlist containshaystack,haystack_integrations,haystack_experimental,builtins,typing, andcollections. Pipelines that reference custom components or callables in other packages will fail to load with aDeserializationErroruntil the additional modules are added to the allowlist.To restore loading of such pipelines, extend the allowlist via one of:
- per-call kwarg:
Pipeline.load(fp, allowed_modules=["mypkg.*"]); - process-wide programmatic API:
from haystack.core.serialization import allow_deserialization_module; - environment variable:
HAYSTACK_DESERIALIZATION_ALLOWLIST="mypkg.*,otherpkg.*"; - or, if the source of the serialized data is fully trusted, bypass the allowlist with
Pipeline.load(fp, unsafe=True).
- per-call kwarg:
-
During pipeline deserialization,
default_from_dictnow validates the keys ofinit_parametersagainst the parent class's__init__signature before recursing into any nested{"type": "...", "init_parameters": {...}}dictionary. A nested dict whose key is not an accepted parameter name on the parent class is rejected with aDeserializationErrorbefore the nested type is imported. Classes whose constructor takes**kwargsare exempt, since their accepted parameter set cannot be statically determined.This may surface pre-existing YAML bugs — e.g. typos, leftovers from renamed or removed parameters, or stale snapshots from older Haystack versions. The fix is to update the YAML so each nested-component key matches a real
__init__parameter on the parent class. -
PromptBuilderandChatPromptBuildernow treat every Jinja2 template variable as required by default. Previously, variables were optional by default unless explicitly listed inrequired_variables.To check if you're affected: look for
PromptBuilder(...)orChatPromptBuilder(...)calls in your code that do not passrequired_variables. If those components relied on missing variables being silently rendered as empty strings, the behavior depends on how the missing variable was reaching the builder:- Calling
builder.run()directly without providing a required variable now raisesValueError. - In a pipeline, if a required variable is neither provided as a user input nor connected from another component,
Pipeline.runraisesValueError("Missing mandatory input '<var>' for component '<name>'."). - In a pipeline, if a required variable is connected to a sender that never produces output on a given run (for example, a loop-fed input on the first iteration or a conditional branch that isn't taken), the pipeline cannot make progress and raises
PipelineComponentsBlockedError.
Migration options:
- To require only a subset of variables, pass
required_variables=["var1", "var2"]. - To preserve the previous "all optional" behavior, explicitly pass
required_variables=None. - To require everything (the new default), no change is needed.
- Calling
-
Human-in-the-Loop tool confirmation on
Agentis now expressed as abefore_toolhook instead of a dedicated concept. Theconfirmation_strategiesandconfirmation_strategy_contextparameters have been removed fromAgent.__init__,Agent.run, andAgent.run_async. To migrate, wrap your confirmation strategies in the newConfirmationHook, register it under thebefore_toolhook point, and pass any request-scoped resources through the generichook_contextrun argument instead ofconfirmation_strategy_context. The Human-in-the-Loop module has also moved fromhaystack.human_in_the_looptohaystack.hooks.human_in_the_loop, so that it lives alongside the other built-in hooks (such as tool result offloading); update your imports to the new location:from haystack.components.agents import Agent from haystack.hooks.human_in_the_loop import ( AlwaysAskPolicy, BlockingConfirmationStrategy, ConfirmationHook, RichConsoleUI, ) confirmation_hook = ConfirmationHook( confirmation_strategies={ "my_tool": BlockingConfirmationStrategy( confirmation_policy=AlwaysAskPolicy(), confirmation_ui=RichConsoleUI() ) } ) agent = Agent(chat_generator=..., tools=[...], hooks={"before_tool": [confirmation_hook]})...
v3.0.0-rc2
Release Notes
v3.0.0-rc2
Bug Fixes
- BUGFIX THAT GOES INTO RC2
v3.0.0-rc1
Upgrade Notes
-
AsyncPipelinehas been removed. Its asynchronous capabilities are now part of the singlePipelineclass, which provides both a synchronousrunmethod and the asynchronousrun_async,run_async_generator, andstreammethods (mirroring how components exposerunandrun_async).To migrate, replace
AsyncPipelinewithPipeline:# Before from haystack import AsyncPipeline pipeline = AsyncPipeline() result = await pipeline.run_async(data) # After from haystack import Pipeline pipeline = Pipeline() result = await pipeline.run_async(data)
Serialized pipelines,
SuperComponents, andPipelineTools are loaded asPipelineinstances.Pipeline.runruns synchronously and blocks until completion; in an async context useawait pipeline.run_async(...). The formerAsyncPipeline.runwas a synchronous wrapper around the concurrent engine, so to preserve that behavior useasyncio.run(pipeline.run_async(...)). Note thatPipeline.runexecutes components sequentially and does not acceptconcurrency_limit.Both synchronous and asynchronous runs are traced under a single
haystack.pipeline.runoperation name, distinguished by ahaystack.pipeline.execution_modetag (syncorasync). Previously, asynchronous runs used thehaystack.async_pipeline.runoperation name. -
continue_runis now a reserved key inAgent.state_schema(set by anon_exithook to keep the Agent running). Passing it via thestate_schemaargument now raisesValueError. Rename any conflicting state key (e.g.my_continue_run) to migrate. -
DocumentNDCGEvaluatornow matches documents by theircontentfield by default instead of their auto-generatedid. Previously, ground truth and retrieved documents were matched only if they had identicalidvalues, which rarely happened in practice since IDs are generated independently for each Document instance. As a result, NDCG scores computed with this evaluator may change for existing pipelines. To keep the previousid-based matching behavior, passdocument_comparison_field="id"when constructing the evaluator. -
Agentno longer validatesexit_conditionsagainst tool names at initialization. Exit conditions are now evaluated at runtime, so a condition naming a tool that is loaded later — e.g. a tool passed at runtime or one discovered bySearchableToolset— works as expected. Consequently, an unknown exit-condition name no longer raises aValueErrorat construction. -
Tool support is now validated against the tools resolved for each run, not only the tools provided at initialization. Passing tools at runtime via
run(tools=...)to a chat generator that does not support tools now raises aTypeErrorinstead of silently ignoring them. -
Components in Haystack that use external resources now consistently create those resources during warm-up rather than in
__init__. As a result, some components that previously raised errors during initialization (for example, because of a missing API key) now raise them duringwarm_upinstead. Similar changes will be rolled out to components in Haystack Core Integrations in the future. -
step_count,token_usage, andtool_call_countsare now reserved keys inAgent.state_schema. Passing any of them via thestate_schemaargument now raisesValueError. Rename the conflicting state key (e.g.my_token_usage) to migrate. -
Confirmation strategies now receive the model-requested tool arguments in
tool_paramsrather than the fully-prepared arguments. Values injected fromStatevia a tool'sinputs_from_statemapping (and theStateobject injected intoState-typed parameters) are no longer included in what is presented for confirmation — that injection now happens only at tool execution time. If yourConfirmationUIorConfirmationPolicydisplayed or inspected those state-injected values, it will now see only the arguments the model provided. -
The hash used to auto-generate
Document.idis now computed from a canonical (key-sorted) JSON serialization ofmeta. Documents with emptymetaare unaffected, but most other documents will get different IDs than they did before:- documents with non-empty
meta(the serialization changes fromdict's repr to JSON); - documents whose
metacontains non-JSON-serializable values such asdatetimeor custom classes (these are now serialized viastr(...)rather thanrepr(...), e.g."2024-01-01 00:00:00"instead of"datetime.datetime(2024, 1, 1, 0, 0)").
If you rely on auto-generated IDs to match documents already persisted in a
DocumentStore, you will need to re-ingest the affected documents (or pass the previousidexplicitly when constructing theDocument). - documents with non-empty
-
Pipeline deserialization (
Pipeline.load/Pipeline.loads/Pipeline.from_dict) now refuses to import classes from modules outside a trusted-module allowlist. By default the allowlist containshaystack,haystack_integrations,haystack_experimental,builtins,typing, andcollections. Pipelines that reference custom components or callables in other packages will fail to load with aDeserializationErroruntil the additional modules are added to the allowlist.To restore loading of such pipelines, extend the allowlist via one of:
- per-call kwarg:
Pipeline.load(fp, allowed_modules=["mypkg.*"]); - process-wide programmatic API:
from haystack.core.serialization import allow_deserialization_module; - environment variable:
HAYSTACK_DESERIALIZATION_ALLOWLIST="mypkg.*,otherpkg.*"; - or, if the source of the serialized data is fully trusted, bypass the allowlist with
Pipeline.load(fp, unsafe=True).
- per-call kwarg:
-
During pipeline deserialization,
default_from_dictnow validates the keys ofinit_parametersagainst the parent class's__init__signature before recursing into any nested{"type": "...", "init_parameters": {...}}dictionary. A nested dict whose key is not an accepted parameter name on the parent class is rejected with aDeserializationErrorbefore the nested type is imported. Classes whose constructor takes**kwargsare exempt, since their accepted parameter set cannot be statically determined.This may surface pre-existing YAML bugs — e.g. typos, leftovers from renamed or removed parameters, or stale snapshots from older Haystack versions. The fix is to update the YAML so each nested-component key matches a real
__init__parameter on the parent class. -
PromptBuilderandChatPromptBuildernow treat every Jinja2 template variable as required by default. Previously, variables were optional by default unless explicitly listed inrequired_variables.To check if you're affected: look for
PromptBuilder(...)orChatPromptBuilder(...)calls in your code that do not passrequired_variables. If those components relied on missing variables being silently rendered as empty strings, the behavior depends on how the missing variable was reaching the builder:- Calling
builder.run()directly without providing a required variable now raisesValueError. - In a pipeline, if a required variable is neither provided as a user input nor connected from another component,
Pipeline.runraisesValueError("Missing mandatory input '<var>' for component '<name>'."). - In a pipeline, if a required variable is connected to a sender that never produces output on a given run (for example, a loop-fed input on the first iteration or a conditional branch that isn't taken), the pipeline cannot make progress and raises
PipelineComponentsBlockedError.
Migration options:
- To require only a subset of variables, pass
required_variables=["var1", "var2"]. - To preserve the previous "all optional" behavior, explicitly pass
required_variables=None. - To require everything (the new default), no change is needed.
- Calling
-
Human-in-the-Loop tool confirmation on
Agentis now expressed as abefore_toolhook instead of a dedicated concept. Theconfirmation_strategiesandconfirmation_strategy_contextparameters have been removed fromAgent.__init__,Agent.run, andAgent.run_async. To migrate, wrap your confirmation strategies in the newConfirmationHook, register it under thebefore_toolhook point, and pass any request-scoped resources through the generichook_contextrun argument instead ofconfirmation_strategy_context. The Human-in-the-Loop module has also moved fromhaystack.human_in_the_looptohaystack.hooks.human_in_the_loop, so that it lives alongside the other built-in hooks (such as tool result offloading); update your imports to the new location:from haystack.components.agents import Agent from haystack.hooks.human_in_the_loop import ( AlwaysAskPolicy, BlockingConfirmationStrategy, ConfirmationHook, RichConsoleUI, ) confirmation_hook = ConfirmationHook( confirmation_strategies={ "my_tool": BlockingConfirmationStrategy( confirmation_policy=AlwaysAskPolicy(), confirmation_ui=RichConsoleUI() ) } ) agent = Agent(chat_generator=..., tools=[...], hooks={"before_tool": [confirmation_hook]}) agent.run(messages=[...], hook_context={"websocket": ws})
-
The agent-specific breakpoint API has been removed. The
AgentBreakpoint,ToolBreakpoint, andAgentSnapshotdataclasses are no longer exported fromhaystack.dataclasses, and thebreak_point,snapshot, andsnapshot_callbackparameters have been removed fromAgent.runandAgent.run_async.Pipeline.runno longer acceptsAgentBreakpointfor itsbreak_pointargument, and theagent_snapshotfield has been removed fromPipelineSnapshot. Pipeline-level breakpoints viaBreakpointandPipelineSnapshotcontinue to work as before, but pausing and resuming execution inside an A...
v3.0.0-rc1
Release Notes
v3.0.0-rc1
Upgrade Notes
-
AsyncPipelinehas been removed. Its asynchronous capabilities are now part of the singlePipelineclass, which provides both a synchronousrunmethod and the asynchronousrun_async,run_async_generator, andstreammethods (mirroring how components exposerunandrun_async).To migrate, replace
AsyncPipelinewithPipeline:# Before from haystack import AsyncPipeline pipeline = AsyncPipeline() result = await pipeline.run_async(data) # After from haystack import Pipeline pipeline = Pipeline() result = await pipeline.run_async(data)
Serialized pipelines,
SuperComponents, andPipelineTools are loaded asPipelineinstances.Pipeline.runruns synchronously and blocks until completion; in an async context useawait pipeline.run_async(...). The formerAsyncPipeline.runwas a synchronous wrapper around the concurrent engine, so to preserve that behavior useasyncio.run(pipeline.run_async(...)). Note thatPipeline.runexecutes components sequentially and does not acceptconcurrency_limit.Both synchronous and asynchronous runs are traced under a single
haystack.pipeline.runoperation name, distinguished by ahaystack.pipeline.execution_modetag (syncorasync). Previously, asynchronous runs used thehaystack.async_pipeline.runoperation name. -
continue_runis now a reserved key inAgent.state_schema(set by anon_exithook to keep the Agent running). Passing it via thestate_schemaargument now raisesValueError. Rename any conflicting state key (e.g.my_continue_run) to migrate. -
DocumentNDCGEvaluatornow matches documents by theircontentfield by default instead of their auto-generatedid. Previously, ground truth and retrieved documents were matched only if they had identicalidvalues, which rarely happened in practice since IDs are generated independently for each Document instance. As a result, NDCG scores computed with this evaluator may change for existing pipelines. To keep the previousid-based matching behavior, passdocument_comparison_field="id"when constructing the evaluator. -
Agentno longer validatesexit_conditionsagainst tool names at initialization. Exit conditions are now evaluated at runtime, so a condition naming a tool that is loaded later — e.g. a tool passed at runtime or one discovered bySearchableToolset— works as expected. Consequently, an unknown exit-condition name no longer raises aValueErrorat construction. -
Tool support is now validated against the tools resolved for each run, not only the tools provided at initialization. Passing tools at runtime via
run(tools=...)to a chat generator that does not support tools now raises aTypeErrorinstead of silently ignoring them. -
Components in Haystack that use external resources now consistently create those resources during warm-up rather than in
__init__. As a result, some components that previously raised errors during initialization (for example, because of a missing API key) now raise them duringwarm_upinstead. Similar changes will be rolled out to components in Haystack Core Integrations in the future. -
step_count,token_usage, andtool_call_countsare now reserved keys inAgent.state_schema. Passing any of them via thestate_schemaargument now raisesValueError. Rename the conflicting state key (e.g.my_token_usage) to migrate. -
Confirmation strategies now receive the model-requested tool arguments in
tool_paramsrather than the fully-prepared arguments. Values injected fromStatevia a tool'sinputs_from_statemapping (and theStateobject injected intoState-typed parameters) are no longer included in what is presented for confirmation — that injection now happens only at tool execution time. If yourConfirmationUIorConfirmationPolicydisplayed or inspected those state-injected values, it will now see only the arguments the model provided. -
The hash used to auto-generate
Document.idis now computed from a canonical (key-sorted) JSON serialization ofmeta. Documents with emptymetaare unaffected, but most other documents will get different IDs than they did before:- documents with non-empty
meta(the serialization changes fromdict's repr to JSON); - documents whose
metacontains non-JSON-serializable values such asdatetimeor custom classes (these are now serialized viastr(...)rather thanrepr(...), e.g."2024-01-01 00:00:00"instead of"datetime.datetime(2024, 1, 1, 0, 0)").
If you rely on auto-generated IDs to match documents already persisted in a
DocumentStore, you will need to re-ingest the affected documents (or pass the previousidexplicitly when constructing theDocument). - documents with non-empty
-
Pipeline deserialization (
Pipeline.load/Pipeline.loads/Pipeline.from_dict) now refuses to import classes from modules outside a trusted-module allowlist. By default the allowlist containshaystack,haystack_integrations,haystack_experimental,builtins,typing, andcollections. Pipelines that reference custom components or callables in other packages will fail to load with aDeserializationErroruntil the additional modules are added to the allowlist.To restore loading of such pipelines, extend the allowlist via one of:
- per-call kwarg:
Pipeline.load(fp, allowed_modules=["mypkg.*"]); - process-wide programmatic API:
from haystack.core.serialization import allow_deserialization_module; - environment variable:
HAYSTACK_DESERIALIZATION_ALLOWLIST="mypkg.*,otherpkg.*"; - or, if the source of the serialized data is fully trusted, bypass the allowlist with
Pipeline.load(fp, unsafe=True).
- per-call kwarg:
-
During pipeline deserialization,
default_from_dictnow validates the keys ofinit_parametersagainst the parent class's__init__signature before recursing into any nested{"type": "...", "init_parameters": {...}}dictionary. A nested dict whose key is not an accepted parameter name on the parent class is rejected with aDeserializationErrorbefore the nested type is imported. Classes whose constructor takes**kwargsare exempt, since their accepted parameter set cannot be statically determined.This may surface pre-existing YAML bugs — e.g. typos, leftovers from renamed or removed parameters, or stale snapshots from older Haystack versions. The fix is to update the YAML so each nested-component key matches a real
__init__parameter on the parent class. -
PromptBuilderandChatPromptBuildernow treat every Jinja2 template variable as required by default. Previously, variables were optional by default unless explicitly listed inrequired_variables.To check if you're affected: look for
PromptBuilder(...)orChatPromptBuilder(...)calls in your code that do not passrequired_variables. If those components relied on missing variables being silently rendered as empty strings, the behavior depends on how the missing variable was reaching the builder:- Calling
builder.run()directly without providing a required variable now raisesValueError. - In a pipeline, if a required variable is neither provided as a user input nor connected from another component,
Pipeline.runraisesValueError("Missing mandatory input '<var>' for component '<name>'."). - In a pipeline, if a required variable is connected to a sender that never produces output on a given run (for example, a loop-fed input on the first iteration or a conditional branch that isn't taken), the pipeline cannot make progress and raises
PipelineComponentsBlockedError.
Migration options:
- To require only a subset of variables, pass
required_variables=["var1", "var2"]. - To preserve the previous "all optional" behavior, explicitly pass
required_variables=None. - To require everything (the new default), no change is needed.
- Calling
-
Human-in-the-Loop tool confirmation on
Agentis now expressed as abefore_toolhook instead of a dedicated concept. Theconfirmation_strategiesandconfirmation_strategy_contextparameters have been removed fromAgent.__init__,Agent.run, andAgent.run_async. To migrate, wrap your confirmation strategies in the newConfirmationHook, register it under thebefore_toolhook point, and pass any request-scoped resources through the generichook_contextrun argument instead ofconfirmation_strategy_context. The Human-in-the-Loop module has also moved fromhaystack.human_in_the_looptohaystack.hooks.human_in_the_loop, so that it lives alongside the other built-in hooks (such as tool result offloading); update your imports to the new location:from haystack.components.agents import Agent from haystack.hooks.human_in_the_loop import ( AlwaysAskPolicy, BlockingConfirmationStrategy, ConfirmationHook, RichConsoleUI, ) confirmation_hook = ConfirmationHook( confirmation_strategies={ "my_tool": BlockingConfirmationStrategy( confirmation_policy=AlwaysAskPolicy(), confirmation_ui=RichConsoleUI() ) } ) agent = Agent(chat_generator=..., tools=[...], hooks={"before_tool": [confirmation_hook]}) agent.run(messages=[...], hook_context={"websocket": ws})
-
The agent-specific breakpoint API has been removed. The
AgentBreakpoint,ToolBreakpoint, andAgentSnapshotdataclasses are no longer exported fromhaystack.dataclasses, and thebreak_point,snapshot, andsnapshot_callbackparameters have been removed fromAgent.runandAgent.run_async.Pipeline.runno longer acceptsAgentBreakpointfor itsbreak_pointargument, and theagent_snapshotfield has been removed fromPipelineSnapshot. Pipeline-level breakpoints viaBreakpointandPipelineSnapshotcontinue to work as before, but pausing and resuming execution inside an Agent (at the chat generator or tool invoker) is no longer s...