You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs-website/docs/concepts/pipelines.mdx
+44-3Lines changed: 44 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -42,11 +42,52 @@ See [Pipeline Loops](pipelines/pipeline-loops.mdx) for a deeper explanation of h
42
42
43
43
<ClickableImagesrc="/img/2390eea-Pipeline_Illustrations_1_2.png"alt="Pipeline architecture diagram illustrating a feedback loop where output from later components loops back to earlier components"size="large" />
44
44
45
-
### Async Pipelines
45
+
### Async Execution and Streaming
46
46
47
-
The AsyncPipeline enables parallel execution of Haystack components when their dependencies allow it. This improves performance in complex pipelines with independent operations. For example, it can run multiple Retrievers or LLM calls simultaneously, execute independent pipeline branches in parallel, and efficiently handle I/O-bound operations that would otherwise cause delays. Through concurrent execution, the AsyncPipeline significantly reduces total processing time compared to sequential execution.
47
+
Pipelines execute components in parallel when their dependencies allow it. This improves performance in complex pipelines with independent operations. For example, a pipeline can run multiple Retrievers or LLM calls simultaneously, execute independent pipeline branches in parallel, and efficiently handle I/O-bound operations that would otherwise cause delays. You can cap the number of components running at the same time with the `concurrency_limit` init parameter.
48
48
49
-
Find out more in our [AsyncPipeline](pipelines/asyncpipeline.mdx) documentation.
49
+
Besides the blocking `run` method, every pipeline offers three ways to run asynchronously:
50
+
51
+
-`run_async`: Executes the pipeline in a single non-blocking call, ideal for integrating a pipeline into a larger async application or service.
52
+
-`run_async_generator`: Yields partial outputs as components complete their tasks, which is useful for monitoring progress, debugging, and handling outputs incrementally.
53
+
-`stream`: Runs the pipeline and returns a handle that streams [`StreamingChunk`](/reference/data-classes-api#streamingchunk) objects as they are produced — a convenient way to stream LLM output from an async application, such as an API endpoint. Iterate the handle with `async for` to consume the chunks; after iteration ends, `handle.result` holds the final pipeline output (the same dictionary returned by `run_async`).
54
+
55
+
```python
56
+
import asyncio
57
+
58
+
from haystack import Pipeline
59
+
from haystack.components.builders import ChatPromptBuilder
60
+
from haystack.components.generators.chat import OpenAIChatGenerator
61
+
from haystack.dataclasses import ChatMessage
62
+
63
+
pipe = Pipeline()
64
+
pipe.add_component(
65
+
"prompt_builder",
66
+
ChatPromptBuilder(template=[ChatMessage.from_user("Tell me about {{topic}}")]),
By default, chunks from every streaming-capable component are forwarded; pass `streaming_components` with a list of component names to stream only specific components. If the consumer abandons iteration, the underlying pipeline run is cancelled automatically; pass `cancel_on_abandon=False` to let it run to completion instead.
83
+
84
+
If a `streaming_callback` is set on a component (at init or at runtime through `data`), it is still invoked for each chunk in addition to the chunks being pushed to the handle. When streaming, components accept a sync `streaming_callback` in `run_async` too — see the [Choosing the Right Generator guide](../pipeline-components/generators/guides-to-generators/choosing-the-right-generator.mdx#sync-and-async-callbacks) for details.
85
+
86
+
#### Error Handling and Task Cancellation
87
+
88
+
If a component raises an error while sibling components are still running concurrently, the pipeline cancels and drains those in-flight tasks before re-raising the original error, so no tasks keep running in the background. The same cleanup applies when you stop iterating `run_async_generator` early (for example, by breaking out of the loop and closing the generator) or when the run itself is cancelled.
89
+
90
+
Note that cancellation only interrupts components that run natively async. Sync components are offloaded to a worker thread, which cannot be interrupted and runs to completion in the background. Their outputs are discarded, so the pipeline state stays consistent, but the component's side effects still complete.
Copy file name to clipboardExpand all lines: docs-website/docs/concepts/pipelines/pipeline-loops.mdx
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -37,7 +37,7 @@ There are two main ways a loop ends:
37
37
The pipeline finishes when the work queue is empty and no component can run again (for example, the router stops feeding inputs back into the loop).
38
38
39
39
2.**Reaching the maximum run count**
40
-
Every pipeline has a per-component run limit, controlled by the `max_runs_per_component` parameter of the `Pipeline`(or `AsyncPipeline`) constructor, which is `100` by default. If any component exceeds this limit, Haystack raises a `PipelineMaxComponentRuns` error.
40
+
Every pipeline has a per-component run limit, controlled by the `max_runs_per_component` parameter of the `Pipeline` constructor, which is `100` by default. If any component exceeds this limit, Haystack raises a `PipelineMaxComponentRuns` error.
Copy file name to clipboardExpand all lines: docs-website/docs/pipeline-components/builders/chatpromptbuilder.mdx
+26Lines changed: 26 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -117,6 +117,32 @@ This template format allows you to define `ChatMessage` sequences using Jinja2 s
117
117
118
118
Compared to using a list of `ChatMessage`s, this format is more flexible and allows including structured parts like images in the templatized `ChatMessage`; to better understand this use case, check out the [multimodal example](#multimodal) in the Usage section below.
119
119
120
+
#### The `insert` Tag
121
+
122
+
String templates also support an `{% insert %}` tag. It is a placeholder that evaluates an expression to a `ChatMessage` or a list of `ChatMessage` objects and expands it into the prompt, so messages provided at runtime can be interleaved with literal `{% message %}` blocks. For example, you can wrap the runtime messages with a system message above and a templated user message below, then pass the messages (and any template variables) at run time:
123
+
124
+
```python
125
+
from haystack.components.builders import ChatPromptBuilder
126
+
from haystack.dataclasses import ChatMessage
127
+
128
+
template ="""
129
+
{% message role="system" %}You are a helpful assistant.{% endmessage %}
# result["prompt"] -> [system, user "Hi", assistant "Hello!", user "What's the weather?"]
140
+
```
141
+
142
+
All content types (tool calls, tool call results, images, reasoning, `name`, and `meta`) round trip without loss. A missing or empty value expands to nothing.
143
+
144
+
The expression can be a plain variable (`{% insert messages %}`), a slice or index (`{% insert messages[-1:] %}`, `{% insert messages[-1] %}`), or a combination of variables (`{% insert previous + current %}`). Multiple `{% insert %}` tags can be used in a single template, so the runtime messages can be split, reordered, or repeated across different positions.
145
+
120
146
### Jinja2 Time Extension
121
147
122
148
`PromptBuilder` supports the Jinja2 TimeExtension, which allows you to work with datetime formats.
Copy file name to clipboardExpand all lines: docs-website/docs/tools/pipelinetool.mdx
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -27,11 +27,11 @@ It replaces the older workflow of first wrapping a pipeline in a `SuperComponent
27
27
`ComponentTool`.
28
28
29
29
`PipelineTool` builds the tool parameter schema from the pipeline’s input sockets and uses the underlying components’ docstrings for input descriptions. You can choose which pipeline inputs and outputs to expose with
30
-
`input_mapping` and `output_mapping`. It works with both `Pipeline` and `AsyncPipeline` and can be used in a pipeline with `ToolInvoker` or directly with the `Agent` component.
30
+
`input_mapping` and `output_mapping`. It can be used in a pipeline with `ToolInvoker` or directly with the `Agent` component.
31
31
32
32
### Parameters
33
33
34
-
-`pipeline` is mandatory and must be a `Pipeline`or `AsyncPipeline`instance.
34
+
-`pipeline` is mandatory and must be a `Pipeline` instance.
35
35
-`name` is mandatory and specifies the tool name.
36
36
-`description` is mandatory and explains what the tool does.
37
37
-`input_mapping` is optional. It maps tool input names to pipeline input socket paths. If omitted, a default mapping is created from all pipeline inputs.
Copy file name to clipboardExpand all lines: docs-website/docs/tools/searchabletoolset.mdx
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -110,7 +110,7 @@ toolset = SearchableToolset(
110
110
111
111
### Reusing the toolset across multiple agent runs
112
112
113
-
When reusing the same `SearchableToolset` instance across multiple agent runs, you can call `clear()` to reset any tools discovered in the previous run:
113
+
You can safely reuse the same `SearchableToolset` instance across multiple agent runs, including concurrent ones. Each `Agent` run operates on an isolated, run-scoped copy of the toolset (created with [`spawn()`](toolset.mdx#run-scoped-copies-and-tool-selection)), so tools discovered in one run do not persist into, or collide with, other runs — every run starts fresh from the catalog:
114
114
115
115
```python
116
116
agent = Agent(
@@ -120,8 +120,8 @@ agent = Agent(
120
120
121
121
result1 = agent.run(messages=[ChatMessage.from_user("What's the weather in Milan?")])
122
122
123
-
# Reset discovered tools before the next run
124
-
toolset.clear()
125
-
123
+
# The next run starts fresh: tools discovered in the previous run are not carried over
126
124
result2 = agent.run(messages=[ChatMessage.from_user("Search for news about AI.")])
127
125
```
126
+
127
+
If you drive the toolset directly (outside an `Agent`), you can call `clear()` to reset the discovered tools yourself.
A `Toolset` is never mutated in place during an [`Agent`](../pipeline-components/agents-1/agent.mdx) run. Each run operates on an isolated, run-scoped copy of the configured `Toolset`, created with the `spawn()` method. This makes concurrent runs that share the same `Toolset` instance safe: per-run state, such as an active tool-name selection or a [`SearchableToolset`](searchabletoolset.mdx)'s discovered tools, cannot leak or collide across runs.
84
+
85
+
You can also restrict an `Agent` to a subset of tools at runtime by passing tool names, for example `agent.run(tools=["tool_a", "tool_b"])`. When a `Toolset` is configured, the selection is applied to the live (run-scoped) `Toolset` rather than flattening it into a static list, so dynamic behavior like a `SearchableToolset`'s search and lazy loading keeps working over the selected subset.
86
+
87
+
Two methods support this and can be overridden when subclassing:
88
+
89
+
-`get_selectable_tools()`: Returns every tool available for name-based selection, ignoring any active selection restriction. Override it if your subclass's iteration does not surface every selectable tool.
90
+
-`spawn()`: Returns an isolated, run-scoped copy of the `Toolset`. Override it if your subclass holds additional run-scoped state.
91
+
81
92
## Usage
82
93
83
94
You can use `Toolset` wherever you can use Tools in Haystack.
0 commit comments