Limitations of Combining Streaming with max_turns in AISuite: Why They Are Mutually Exclusive
AISuite treats streaming and automatic tool execution via max_turns as mutually exclusive modes, raising a ValueError as soon as both parameters are supplied to client.chat.completions.create().
The aisuite library by Andrew Ng's team provides a unified interface for multiple LLM providers, but it imposes a strict architectural boundary between real-time streaming responses and iterative tool-calling loops. Understanding the limitations of combining streaming with max_turns in aisuite is essential when building applications that require both interactive output and autonomous function execution.
Why Streaming and max_turns Cannot Be Combined
AISuite follows two distinct internal paths depending on whether stream=True or max_turns is provided. The client explicitly prevents their intersection because the streaming API returns an iterator of chunks directly from the provider, leaving no hook for the client-side loop that manages tool calls across multiple turns.
The Streaming Path Disables Automatic Tool Execution
When stream=True is set, the client follows the manual tool-calling path. The request is routed directly to the provider's chat_completions_create_stream method, and the client does not run the internal tool-execution loop that max_turns would trigger. Because partial LLM responses are yielded as chunks in real time, there is no mechanism to pause the stream, execute a tool, append the result, and resume the conversation for another turn.
The max_turns Path Requires Non-Streaming Mode
When max_turns is supplied, the client prepares a normal non-streaming chat request and runs the tool-execution loop for up to the specified number of turns. It returns only the final LLM response after all tool calls resolve. If stream=True is also present, the guard aborts early because the iterative tool-execution logic cannot interleave with a live chunk iterator.
Where AISuite Enforces This Limitation
The enforcement happens in aisuite/client.py, which contains the core client logic validating the stream and max_turns combination. Before any network request is dispatched, the client checks for the incompatible pair and raises ValueError.
The provider-side streaming contract is defined in aisuite/provider.py, where the base provider class establishes the streaming interface. This file delineates which features are unsupported when operating in streaming mode.
How the Test Suite Locks In the Behavior
The AISuite test suite codifies this rule explicitly. In tests/client/test_streaming.py, the test test_create_stream_with_max_turns_raises confirms that a ValueError is thrown when both parameters are supplied:
with pytest.raises(ValueError, match="max_turns"):
client.chat.completions.create(
model="openai:gpt-4o",
messages=[{"role": "user", "content": "hi"}],
tools=[{"type": "function", "function": {"name": "t", "parameters": {}}}],
max_turns=3,
stream=True,
)
This validation covers lines 70‑82 of tests/client/test_streaming.py.
The asynchronous client enforces the identical restriction before iteration begins. The test test_acreate_stream_with_max_turns_raises_eagerly in tests/client/test_async_client.py validates the guard on lines 44‑55, raising the same ValueError eagerly.
Correct Usage Patterns
To avoid runtime errors, keep these two modes entirely separate.
Streaming Without Automatic Tool Execution
Use stream=True when you need real-time output and will handle tool calls manually outside the client:
# ✅ Correct usage – streaming without automatic tool execution
client.chat.completions.create(
model="openai:gpt-4o",
messages=[{"role": "user", "content": "Explain quantum tunneling"}],
stream=True,
)
Automatic Tool Execution Without Streaming
Use max_turns when you want AISuite to manage multi-turn tool execution autonomously:
# ✅ Correct usage – automatic tool execution (max_turns) without streaming
client.chat.completions.create(
model="openai:gpt-4o",
messages=[{"role": "user", "content": "What's the weather?"}],
tools=[weather_tool],
max_turns=3, # run up to 3 tool‑execution turns
)
Invalid Combination
Passing both parameters triggers an immediate exception:
# ❌ Invalid combination – raises ValueError
client.chat.completions.create(
model="openai:gpt-4o",
messages=[{"role": "user", "content": "Run a script"}],
tools=[script_tool],
max_turns=2,
stream=True, # ❌ cannot be combined
)
Summary
- Streaming and
max_turnsare mutually exclusive in AISuite by design. - When
stream=True, the client routes tochat_completions_create_streamand skips the tool-execution loop. - When
max_turnsis set, the client expects a non-streaming request to run its iterative tool loop. - The guard lives in
aisuite/client.pyand raisesValueErrorimmediately. - Tests in
tests/client/test_streaming.py(lines 70‑82) andtests/client/test_async_client.py(lines 44‑55) lock in this behavior.
Frequently Asked Questions
What happens if I pass both stream=True and max_turns to AISuite?
AISuite raises a ValueError before sending any request. The guard in aisuite/client.py detects the incompatible combination and aborts immediately.
Can I still use tools when streaming is enabled?
Yes, but you must handle tool calling manually. When stream=True, AISuite follows the manual tool-calling path, so you are responsible for intercepting tool requests, executing functions, and re-sending the results in subsequent messages.
Is there an async version of this limitation?
Yes. The async client enforces the same restriction eagerly. The test test_acreate_stream_with_max_turns_raises_eagerly in tests/client/test_async_client.py (lines 44‑55) verifies that ValueError is raised before async iteration begins.
Will AISuite support streaming with max_turns in the future?
The current architecture does not support this combination because streaming yields raw provider chunks without a client-side hook for multi-turn tool execution. Implementing it would require complex interleaving of partial responses with tool calls, which the codebase does not currently provide.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →