## Problem
When using GraphFlow with a termination condition, the second task
execution would immediately terminate without running any agents. The
first task would run successfully, but subsequent tasks would skip all
agents and go directly to the stop agent.
This was demonstrated by the following issue:
```python
# First task runs correctly
result1 = await team.run(task="First task") # ✅ Works fine
# Second task fails immediately
result2 = await team.run(task="Second task") # ❌ Only user + stop messages
```
## Root Cause
The `GraphFlowManager` was not resetting its execution state when
termination occurred. After the first task completed:
1. The `_ready` queue was empty (all nodes had been processed)
2. The `_remaining` and `_enqueued_any` tracking structures remained in
"completed" state
3. The `_message_thread` retained history from the previous task
This left the graph in a "completed" state, causing subsequent tasks to
immediately trigger the stop agent instead of executing the workflow.
## Solution
Added an override of the `_apply_termination_condition` method in
`GraphFlowManager` to automatically reset the graph execution state when
termination occurs:
```python
async def _apply_termination_condition(
self, delta: Sequence[BaseAgentEvent | BaseChatMessage], increment_turn_count: bool = False
) -> bool:
# Call the base implementation first
terminated = await super()._apply_termination_condition(delta, increment_turn_count)
# If terminated, reset the graph execution state and message thread for the next task
if terminated:
self._remaining = {target: Counter(groups) for target, groups in self._graph.get_remaining_map().items()}
self._enqueued_any = {n: {g: False for g in self._enqueued_any[n]} for n in self._enqueued_any}
self._ready = deque([n for n in self._graph.get_start_nodes()])
# Clear the message thread to start fresh for the next task
self._message_thread.clear()
return terminated
```
This ensures that when a task completes (termination condition is met),
the graph is automatically reset to its initial state ready for the next
task.
## Testing
Added a comprehensive test case
`test_digraph_group_chat_multiple_task_execution` that validates:
- Multiple tasks can be run sequentially without explicit reset calls
- All agents are executed the expected number of times
- Both tasks produce the correct number of messages
- The fix works with various termination conditions
(MaxMessageTermination, TextMentionTermination)
## Result
GraphFlow now works like SelectorGroupChat where multiple tasks can be
run sequentially without explicit resets between them:
```python
# Both tasks now work correctly
result1 = await team.run(task="First task") # ✅ 5 messages, all agents called
result2 = await team.run(task="Second task") # ✅ 5 messages, all agents called again
```
Fixes#6746.
> [!WARNING]
>
> <details>
> <summary>Firewall rules blocked me from connecting to one or more
addresses</summary>
>
> #### I tried to connect to the following addresses, but was blocked by
firewall rules:
>
> - `esm.ubuntu.com`
> - Triggering command: `/usr/lib/apt/methods/https` (dns block)
>
> If you need me to access, download, or install something from one of
these locations, you can either:
>
> - Configure [Actions setup
steps](https://gh.io/copilot/actions-setup-steps) to set up my
environment, which run before the firewall is enabled
> - Add the appropriate URLs or hosts to my [firewall allow
list](https://gh.io/copilot/firewall-config)
>
> </details>
<!-- START COPILOT CODING AGENT TIPS -->
---
💬 Share your feedback on Copilot coding agent for the chance to win a
$200 gift card! Click
[here](https://survey.alchemer.com/s3/8343779/Copilot-Coding-agent) to
start the survey.
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: ekzhu <320302+ekzhu@users.noreply.github.com>
Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com>
## Why are these changes needed?
The existing run_stream methods used fragile count-based logic (count <=
len(task)) to skip task messages during streaming. This approach was
brittle and broke when team structure changed or task composition
varied, particularly affecting SocietyOfMindAgent's ability to properly
encapsulate inner team messages.
This PR adds an output_task_messages parameter to run_stream methods to
provide explicit control over task message inclusion in streams,
replacing the fragile count-based logic with robust message filtering.
## Related issue number
Closes#6150
## Checks
- [ ] I've included any doc changes needed for
<https://microsoft.github.io/autogen/>. See
<https://github.com/microsoft/autogen/blob/main/CONTRIBUTING.md> to
build and test documentation locally.
- [x] I've added tests corresponding to the changes introduced in this
PR.
- [x] I've made sure all auto checks have passed.
---------
Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com>
## Summary
Implements the `tool_choice` parameter for `ChatCompletionClient`
interface as requested in #6696. This allows users to restrict which
tools the model can choose from when multiple tools are available.
## Changes
### Core Interface
- Core Interface: Added `tool_choice: Tool | Literal["auto", "required",
"none"] = "auto"` parameter to `ChatCompletionClient.create()` and
`create_stream()` methods
- Model Implementations: Updated client implementations to support the
new parameter, for now, only the following model clients are supported:
- OpenAI
- Anthropic
- Azure AI
- Ollama
- `LlamaCppChatCompletionClient` currently not supported
Features
- "auto" (default): Let the model choose whether to use tools, when
there is no tool, it has no effect.
- "required": Force the model to use at least one tool
- "none": Disable tool usage completely
- Tool object: Force the model to use a specific tool
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: ekzhu <320302+ekzhu@users.noreply.github.com>
Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com>
## Why are these changes needed?
This PR addresses critical issues in the AssistantAgent that affect tool
handling:
**Lack of tool call loop functionality**: The agent could not perform
multiple consecutive tool calls in a single turn, limiting its ability
to complete complex multi-step tasks that require chaining tool
operations.
These changes enhance the agent's robustness and capability while
maintaining full backward compatibility through feature flags.
## Related issue number
Closes #6268
## Checks
- [x] I've included any doc changes needed for
<https://microsoft.github.io/autogen/>. See
<https://github.com/microsoft/autogen/blob/main/CONTRIBUTING.md> to
build and test documentation locally.
- [x] I've added tests corresponding to the changes introduced in this
PR.
- [x] I've made sure all auto checks have passed.
---------
Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com>