# AG2 Compatibility

The `autogen.beta.Agent` is designed to be fully compatible with existing AG2 architectures, including [Group Chats](https://docs.ag2.ai/0.13.1/docs/user-guide/advanced-concepts/orchestration/group-chat/introduction/) and [sequential workflows](https://docs.ag2.ai/0.13.1/docs/user-guide/advanced-concepts/orchestration/sequential-chat/). By calling the `as_conversable()` method, you can seamlessly integrate beta agents with traditional `ConversableAgent` instances.

This guide explains how to use the new Beta Agents across various chat topologies.

## One-to-one chats

You can initiate a standard chat between a `ConversableAgent` and a Beta `Agent` by converting the beta agent into a conversable format. This enables direct, two-way communication.

|     |     |
| --- | --- |
| ```<br> 1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br>10<br>11<br>12<br>13<br>14<br>15<br>16<br>17<br>18<br>19<br>20<br>21<br>22<br>23<br>``` | ```<br>from autogen import ConversableAgent, LLMConfig<br>from autogen.beta import Agent, config<br># Define the beta agent<br>beta_agent = Agent(<br>    "beta_agent",<br>    config=config.OpenAIConfig(model="gpt-4o"),<br>)<br># Define a traditional local agent<br>local_agent = ConversableAgent(<br>    "local_agent",<br>    llm_config=LLMConfig({"model": "gpt-4o"}),<br>)<br># Initiate one-to-one chat<br>result = await local_agent.a_run(<br>    recipient=beta_agent.as_conversable(),<br>    message="Hello beta agent!",<br>    max_turns=2,<br>)<br>await result.process()<br>``` |

## Sequential chats

You can chain multiple chats together sequentially using `a_initiate_chats` (see the [Sequential Chat](https://docs.ag2.ai/0.13.1/docs/user-guide/advanced-concepts/orchestration/sequential-chat/) guide). The beta agents handle their respective tasks in order, acting as recipients in the chat sequence.

|     |     |
| --- | --- |
| ```<br> 1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br>10<br>11<br>12<br>13<br>14<br>15<br>16<br>17<br>18<br>19<br>20<br>21<br>22<br>23<br>24<br>25<br>26<br>``` | ```<br>from autogen import ConversableAgent, LLMConfig<br>from autogen.beta import Agent, config<br>model_config = config.OpenAIConfig(model="gpt-4o")<br>agent1 = Agent("agent1", config=model_config)<br>agent2 = Agent("agent2", config=model_config)<br>local_agent = ConversableAgent(<br>    "local_manager",<br>    llm_config=LLMConfig({"model": "gpt-4o"}),<br>)<br>chat_results = await local_agent.a_initiate_chats([<br>    {<br>        "recipient": agent1.as_conversable(),<br>        "message": "Analyze this data.",<br>        "max_turns": 1,<br>        "chat_id": "analysis-chat",<br>    },<br>    {<br>        "recipient": agent2.as_conversable(),<br>        "message": "Summarize the analysis.",<br>        "max_turns": 1,<br>        "chat_id": "summary-chat",<br>    },<br>])<br>``` |

## Handoffs

Beta agents fully support AG2's pattern-based [handoff mechanisms](https://docs.ag2.ai/0.13.1/docs/user-guide/advanced-concepts/orchestration/group-chat/handoffs/). You can use `AgentTarget` to explicitly dictate which agent should take over when the current agent completes its work.

|     |     |
| --- | --- |
| ```<br> 1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br>10<br>11<br>12<br>13<br>14<br>15<br>16<br>17<br>18<br>19<br>20<br>21<br>22<br>23<br>24<br>25<br>26<br>27<br>28<br>29<br>30<br>31<br>32<br>33<br>34<br>35<br>36<br>37<br>``` | ```<br>from autogen import ConversableAgent, LLMConfig<br>from autogen.agentchat.group.multi_agent_chat import a_run_group_chat<br>from autogen.agentchat.group import AgentTarget<br>from autogen.agentchat.group.patterns import DefaultPattern<br>from autogen.beta import Agent, config<br>original_agent = ConversableAgent(<br>    "manager", llm_config=LLMConfig({"model": "gpt-4o"})<br>)<br>model_config = config.OpenAIConfig(model="gpt-4o")<br>agent1 = Agent(<br>    "researcher", config=model_config<br>).as_conversable()<br>agent2 = Agent(<br>    "reviewer", config=model_config<br>).as_conversable()<br># Define handoffs<br>original_agent.handoffs.set_after_work(AgentTarget(agent1))<br>agent1.handoffs.set_after_work(AgentTarget(agent2))<br>agent2.handoffs.set_after_work(AgentTarget(original_agent))<br>pattern = DefaultPattern(<br>    initial_agent=original_agent,<br>    agents=[original_agent, agent1, agent2],<br>)<br>result = await a_run_group_chat(<br>    pattern=pattern,<br>    messages="Start the research process.",<br>    max_rounds=5,<br>)<br>await result.process()<br>``` |

## Tool-driven handoffs

Beta agent tools can trigger a handoff directly from inside a tool by returning a `ToolResult` with a `target` in its `metadata`. When a `ConversableAdapter` detects this, it forwards the target to the group manager, which routes execution to the specified agent on the next turn. See the [AG2 handoffs guide](https://docs.ag2.ai/0.13.1/docs/user-guide/advanced-concepts/orchestration/group-chat/handoffs/) for the full list of available targets.

Use `final=True` alongside the target to end the agent's turn immediately after the tool runs, without invoking the LLM again for a follow-up reply.

|     |     |
| --- | --- |
| ```<br> 1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br>10<br>11<br>12<br>13<br>14<br>15<br>16<br>17<br>18<br>19<br>20<br>21<br>22<br>23<br>24<br>25<br>26<br>27<br>28<br>29<br>30<br>31<br>32<br>33<br>34<br>35<br>36<br>37<br>38<br>39<br>40<br>41<br>``` | ```<br>from autogen import ConversableAgent, LLMConfig<br>from autogen.agentchat import a_run_group_chat<br>from autogen.agentchat.group import AgentTarget<br>from autogen.agentchat.group.patterns import RoundRobinPattern<br>from autogen.beta import Agent, ToolResult, config<br>model_config = config.OpenAIConfig(model="gpt-4o")<br>reviewer = Agent("reviewer", config=model_config).as_conversable()<br>writer = Agent("writer", config=model_config).as_conversable()<br>router = Agent("router", config=model_config)<br>@router.tool<br>def submit_for_review(content: str) -> ToolResult[str]:<br>    """Submit the draft content for review."""<br>    return ToolResult(<br>        f"Draft submitted: {content}",<br>        metadata={"target": AgentTarget(reviewer)},<br>        final=True,<br>    )<br>conversable_agent = ConversableAgent("coordinator", llm_config=LLMConfig({"model": "gpt-4o"}))<br>pattern = RoundRobinPattern(<br>    initial_agent=conversable_agent,<br>    agents=[<br>        conversable_agent,<br>        router.as_conversable(),<br>        writer,<br>        reviewer,<br>    ],<br>)<br>result = await a_run_group_chat(<br>    pattern=pattern,<br>    messages="Write and review a short summary.",<br>    max_rounds=6,<br>)<br>await result.process()<br>``` |

## Group chats (autopattern)

You can build dynamic [group chats](https://docs.ag2.ai/0.13.1/docs/user-guide/advanced-concepts/orchestration/group-chat/introduction/) using `AutoPattern`, where multiple beta agents and standard agents participate in a shared environment.

|     |     |
| --- | --- |
| ```<br> 1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br>10<br>11<br>12<br>13<br>14<br>15<br>16<br>17<br>18<br>19<br>20<br>21<br>22<br>23<br>24<br>25<br>26<br>27<br>28<br>29<br>``` | ```<br>from autogen.agentchat.group.multi_agent_chat import a_run_group_chat<br>from autogen.agentchat.group.patterns import AutoPattern<br>from autogen.llm_config.config import LLMConfig<br>from autogen.beta import Agent, config<br># Create beta agents<br>model_config = config.OpenAIConfig(model="gpt-4o")<br>researcher = Agent(<br>    "researcher", config=model_config<br>).as_conversable()<br>writer = Agent(<br>    "writer", config=model_config<br>).as_conversable()<br>pattern = AutoPattern(<br>    initial_agent=researcher,<br>    agents=[researcher, writer],<br>    group_manager_args={"llm_config": LLMConfig({"model": "gpt-4o"})},<br>)<br>result = await a_run_group_chat(<br>    pattern=pattern,<br>    messages="Research quantum computing and write a summary.",<br>    max_rounds=10,<br>)<br>await result.process()<br>``` |

## Context Variables support

Beta agents deeply integrate with AG2's [`ContextVariables`](https://docs.ag2.ai/0.13.1/docs/user-guide/advanced-concepts/orchestration/group-chat/context-variables/), allowing state to be shared effortlessly across group chats and seamlessly accessed inside beta agent tools.

You can inject global variables into the group chat pattern, and read/modify them within any tool via the `Context` object or `Variable()` annotations.

|     |     |
| --- | --- |
| ```<br> 1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br>10<br>11<br>12<br>13<br>14<br>15<br>16<br>17<br>18<br>19<br>20<br>21<br>22<br>23<br>24<br>25<br>26<br>27<br>28<br>29<br>30<br>31<br>32<br>33<br>34<br>35<br>36<br>37<br>38<br>39<br>40<br>41<br>42<br>43<br>44<br>45<br>46<br>47<br>``` | ```<br>from typing import Annotated<br>from autogen import ConversableAgent, LLMConfig<br>from autogen.agentchat.group import ContextVariables<br>from autogen.agentchat.group.multi_agent_chat import a_run_group_chat<br>from autogen.agentchat.group.patterns import RoundRobinPattern<br>from autogen.beta import Agent, Context, Variable, config<br>beta_agent = Agent(<br>    "tracker_agent",<br>    config=config.OpenAIConfig(model="gpt-4o"),<br>)<br># Define a tool that accesses and modifies ContextVariables<br>@beta_agent.tool<br>def issue_tracker(<br>    context: Context,<br>    issue_count: Annotated[int, Variable(default=0)]<br>) -> str:<br>    # Update the shared context variable<br>    issue_count += 1<br>    context.variables["issue_count"] = issue_count<br>    return f"Issue tracked. Total issues: {issue_count}"<br>local_agent = ConversableAgent(<br>    "local_agent",<br>    llm_config=LLMConfig({"model": "gpt-4o"),<br>)<br># Initialize the pattern with ContextVariables<br>pattern = RoundRobinPattern(<br>    initial_agent=local_agent,<br>    agents=[local_agent, beta_agent.as_conversable()],<br>    context_variables=ContextVariables({"issue_count": 0}),<br>)<br>async def main():<br>    result = await a_run_group_chat(<br>        pattern=pattern,<br>        messages="Please track this new issue.",<br>        max_rounds=3,<br>    )<br>    await result.process()<br>    # context_variables["issue_count"] will now be updated globally!<br>    context_variables = await result.context_variables<br>    print("Final issue count:", context_variables.data["issue_count"])<br>``` |
