Skip to content

Commit cb8d9d1

Browse files
committed
Address feedback
1 parent b6d1e93 commit cb8d9d1

6 files changed

Lines changed: 64 additions & 12 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ limitations under the License.
4848
## ✨ Key Features
4949

5050
- 🛠️ **Building Agents**: Accelerate your agent development with tools that make it easier to get your agent into production.
51-
- 🧩 [**Framework Agnostic:**](./docs/source/components/integrations/frameworks.md) Work side-by-side with agentic frameworks to add the instrumentation necessary for observing, profiling, and optimizing your agents. Use the toolkit with popular frameworks such as [LangChain](https://www.langchain.com/), [LlamaIndex](https://www.llamaindex.ai/), [CrewAI](https://www.crewai.com/), [AG2](https://docs.ag2.ai), [Microsoft Semantic Kernel](https://learn.microsoft.com/en-us/semantic-kernel/), and [Google ADK](https://google.github.io/adk-docs/), as well as custom enterprise agentic frameworks and simple Python agents.
51+
- 🧩 [**Framework Agnostic:**](./docs/source/components/integrations/frameworks.md) Work side-by-side with agentic frameworks to add the instrumentation necessary for observing, profiling, and optimizing your agents. Use the toolkit with popular frameworks such as [LangChain](https://www.langchain.com/), [LlamaIndex](https://www.llamaindex.ai/), [CrewAI](https://www.crewai.com/), [Microsoft Semantic Kernel](https://learn.microsoft.com/en-us/semantic-kernel/), and [Google ADK](https://google.github.io/adk-docs/), as well as custom enterprise agentic frameworks and simple Python agents.
5252
- 🔁 [**Reusability:**](./docs/source/components/sharing-components.md) Build components once and use them multiple times to maximize the value from development effort.
5353
-[**Customization:**](docs/source/get-started/tutorials/customize-a-workflow.md) Start with a pre-built agent, tool, or workflow, and customize it to your needs.
5454
- 💬 [**Built-In User Interface:**](./docs/source/run-workflows/launching-ui.md) Use the NeMo Agent Toolkit UI chat interface to interact with your agents, visualize output, and debug workflows.

examples/frameworks/nat_ag2_demo/README.md

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ A quick example using the AG2 framework (formerly AutoGen), showcasing a multi-a
3434
- [Run the Workflow](#run-the-workflow)
3535
- [Set up the MCP Server](#set-up-the-mcp-server)
3636
- [Expected Output](#expected-output)
37+
- [Async Workflow](#async-workflow)
38+
- [Research Team Example](#research-team-example)
3739
- [Observability with Phoenix](#observability-with-phoenix)
3840
- [Start Phoenix Server](#start-phoenix-server)
3941
- [Run with Tracing Enabled](#run-with-tracing-enabled)
@@ -43,15 +45,18 @@ A quick example using the AG2 framework (formerly AutoGen), showcasing a multi-a
4345
- [Run the Evaluation](#run-the-evaluation)
4446
- [Understanding Evaluation Results](#understanding-evaluation-results)
4547
- [Architecture](#architecture)
48+
- [Async Execution](#async-execution)
4649
- [Tool Integration](#tool-integration)
50+
- [Available Configs](#available-configs)
4751

4852
## Key Features
4953

5054
- **AG2 Framework Integration:** Demonstrates NVIDIA NeMo Agent Toolkit support for AG2 (formerly AutoGen) alongside other frameworks like LangChain/LangGraph and Semantic Kernel.
55+
- **Native Async Support:** All workflows use AG2's `a_initiate_group_chat` for non-blocking async execution, with tools awaited natively via `async`/`await`.
5156
- **Multi-Agent Collaboration:** Shows two specialized agents working together — a TrafficAgent for data retrieval and a FinalResponseAgent for response formatting.
5257
- **Time-Aware Traffic Status:** Provides realistic traffic information that varies based on time of day (morning rush, evening rush, off-peak hours).
5358
- **Unified Tool Integration:** Uses the unified abstraction provided by the toolkit to integrate both local tools (traffic status) and MCP tools (time service) without framework-specific code.
54-
- **AutoPattern Group Chat:** Uses AG2's `ConversableAgent` with `AutoPattern` and `initiate_group_chat` for structured agent communication.
59+
- **AutoPattern Group Chat:** Uses AG2's `ConversableAgent` with `AutoPattern` and `a_initiate_group_chat` for structured agent communication.
5560

5661
## Prerequisites
5762

@@ -126,6 +131,28 @@ Workflow Result:
126131
["The current traffic conditions on the 405 South are as follows:\n\n* Segment: Mulholland Drive to LAX\n* Traffic Conditions: Light\n\nIt appears that traffic is relatively clear on the 405 South.\n\nAPPROVE"]
127132
```
128133

134+
## Async Workflow
135+
136+
The `config-async.yml` config demonstrates the same traffic workflow using a dedicated async workflow type (`ag2_async_team`). This config is functionally identical to the default but uses a separate workflow registration to clearly distinguish the async execution path:
137+
138+
```bash
139+
nat run --config_file examples/frameworks/nat_ag2_demo/configs/config-async.yml \
140+
--input "What is the current traffic on the 405 South?"
141+
```
142+
143+
Both `config.yml` and `config-async.yml` use AG2's `a_initiate_group_chat` for async execution. The async config exists as an explicit example of the async pattern for reference.
144+
145+
## Research Team Example
146+
147+
The `config-research.yml` config demonstrates a different agent pattern — a researcher and writer agent collaborate to produce a structured research summary:
148+
149+
```bash
150+
nat run --config_file examples/frameworks/nat_ag2_demo/configs/config-research.yml \
151+
--input "What are the latest advances in quantum computing?"
152+
```
153+
154+
This config uses the `ag2_research_team` workflow type which wraps the AG2 research agents as a NAT tool, invoked by a `react_agent` orchestrator.
155+
129156
## Observability with Phoenix
130157

131158
This section demonstrates how to enable distributed tracing using Phoenix to monitor and analyze the AG2 workflow execution.
@@ -222,7 +249,17 @@ The AG2 workflow consists of two main agents:
222249
- Provides clear, concise answers to user queries
223250
- Terminates the conversation with "APPROVE"
224251

225-
The agents communicate through AG2's `AutoPattern` with `initiate_group_chat`. A `ConversableAgent` with `human_input_mode="NEVER"` serves as both the user initiator and tool executor — tool calls from TrafficAgent are routed to it for execution, keeping the group chat flow self-contained.
252+
The agents communicate through AG2's `AutoPattern` with `a_initiate_group_chat`. A `ConversableAgent` with `human_input_mode="NEVER"` serves as both the user initiator and tool executor — tool calls from TrafficAgent are routed to it for execution, keeping the group chat flow self-contained.
253+
254+
### Async Execution
255+
256+
All AG2 demo workflows use native async execution:
257+
258+
- **`a_initiate_group_chat`** orchestrates agent turns without blocking the event loop
259+
- **Tool functions** are async coroutines (`await fn.acall_invoke(...)`) executed natively by AG2's `a_execute_function`, which checks `is_coroutine_callable(func)` and awaits the result
260+
- **Streaming tools** collect results into a single response since AG2 tools return a single value
261+
262+
This replaces the previous approach of running async tool calls through a `ThreadPoolExecutor`, eliminating unnecessary thread overhead.
226263

227264
### Tool Integration
228265

@@ -232,3 +269,12 @@ This example demonstrates the unified approach to tool integration provided by N
232269
- **MCP tools** (like `current_datetime`) are configured in YAML using the `mcp_client` function group provided by the toolkit
233270

234271
Both types of tools are passed to AG2 agents through the `builder.get_tools()` method, which automatically wraps them for the AG2 framework. This eliminates the need for framework-specific MCP integration code and provides a consistent interface across all supported frameworks (AG2, AutoGen, LangChain, Semantic Kernel, and others).
272+
273+
## Available Configs
274+
275+
| Config | Workflow Type | Description |
276+
|--------|--------------|-------------|
277+
| `config.yml` | `ag2_team` | Default traffic workflow with async group chat |
278+
| `config-async.yml` | `ag2_async_team` | Explicit async variant of the traffic workflow |
279+
| `config-research.yml` | `ag2_research_team` | Research team with researcher + writer agents |
280+
| `config-eval.yml` | `ag2_team` | Traffic workflow with Phoenix tracing and evaluation |

examples/frameworks/nat_ag2_demo/src/nat_ag2_demo/ag2_async_team.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,9 @@ async def _ag2_async_team_workflow(user_input: str) -> str:
125125

126126
return "The workflow finished but no output was generated."
127127

128-
except Exception as e:
128+
except Exception:
129129
logger.exception("Error in AG2 async team workflow")
130-
return f"Error occurred during AG2 async team workflow: {e!s}"
130+
return "An internal error occurred during the AG2 async team workflow."
131131

132132
yield FunctionInfo.from_fn(_ag2_async_team_workflow)
133133

examples/frameworks/nat_ag2_demo/src/nat_ag2_demo/ag2_research_team.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ async def ag2_research_team(
6565
FunctionInfo wrapping the research team callable.
6666
"""
6767
from autogen import ConversableAgent
68-
from autogen.agentchat import initiate_group_chat
68+
from autogen.agentchat import a_initiate_group_chat
6969
from autogen.agentchat.group.patterns import AutoPattern
7070

7171
llm_config = await builder.get_llm(config.llm_name, wrapper_type=LLMFrameworkEnum.AG2)
@@ -102,7 +102,7 @@ async def _ag2_research_team(task: str) -> str:
102102
group_manager_args={"llm_config": llm_config},
103103
)
104104

105-
result, _ctx, _last = initiate_group_chat(
105+
result, _ctx, _last = await a_initiate_group_chat(
106106
pattern=pattern,
107107
messages=task,
108108
max_rounds=config.max_rounds,

examples/frameworks/nat_ag2_demo/src/nat_ag2_demo/ag2_team.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ async def ag2_team(config: AG2TeamConfig, builder: Builder) -> AsyncIterator[Fun
5252
5353
A query-processing agent retrieves data using tools while a final response
5454
agent formats the result. The user ConversableAgent acts as the initiator
55-
and tool executor. AutoPattern with initiate_group_chat orchestrates turns.
55+
and tool executor. AutoPattern with a_initiate_group_chat orchestrates turns.
5656
5757
Args:
5858
config: Configuration for the AG2 team.
@@ -62,7 +62,7 @@ async def ag2_team(config: AG2TeamConfig, builder: Builder) -> AsyncIterator[Fun
6262
FunctionInfo wrapping the workflow callable.
6363
"""
6464
from autogen import ConversableAgent
65-
from autogen.agentchat import initiate_group_chat
65+
from autogen.agentchat import a_initiate_group_chat
6666
from autogen.agentchat.group.patterns import AutoPattern
6767

6868
try:
@@ -110,7 +110,7 @@ async def _ag2_team_workflow(user_input: str) -> str:
110110
group_manager_args={"llm_config": llm_config},
111111
)
112112

113-
result, _ctx, _last = initiate_group_chat(
113+
result, _ctx, _last = await a_initiate_group_chat(
114114
pattern=pattern,
115115
messages=user_input,
116116
max_rounds=config.max_rounds,
@@ -123,9 +123,9 @@ async def _ag2_team_workflow(user_input: str) -> str:
123123

124124
return "The workflow finished but no output was generated."
125125

126-
except Exception as e:
126+
except Exception:
127127
logger.exception("Error in AG2 team workflow")
128-
return f"Error occurred during AG2 team workflow: {e!s}"
128+
return "An internal error occurred during the AG2 team workflow."
129129

130130
yield FunctionInfo.from_fn(_ag2_team_workflow)
131131

examples/frameworks/nat_ag2_demo/src/nat_ag2_demo/traffic_status_tool.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,12 @@ async def _traffic_status(hwy: str, hour: int) -> str:
125125
f"Supported highways: 405-south, 405-north, 110-south, 110-north, "
126126
f"10-east, 10-west, 210-east, 210-west.")
127127

128+
if not isinstance(hour, int):
129+
try:
130+
hour = int(hour)
131+
except (ValueError, TypeError):
132+
return f"Invalid hour '{hour}'. Please provide an hour between 0 and 23."
133+
128134
if not 0 <= hour <= 23:
129135
return f"Invalid hour '{hour}'. Please provide an hour between 0 and 23."
130136

0 commit comments

Comments
 (0)