Quick Start#

Note

See here for installation instructions.

Before diving into the core APIs, let’s start with a simple example of two agents creating a plot of Tesla’s and Nvidia’s stock returns.

We first define the agent classes and their respective procedures for handling messages. We create two agent classes: Assistant and Executor. The Assistant agent writes code and the Executor agent executes the code. We also create a Message data class, which defines the messages that are passed between the agents.

Attention

Code generated in this example is run within a Docker container. Please ensure Docker is installed and running prior to running the example. Local code execution is available (LocalCommandLineCodeExecutor) but is not recommended due to the risk of running LLM generated code in your local environment.

import re
from dataclasses import dataclass
from typing import List

from autogen_core import DefaultTopicId, MessageContext, RoutedAgent, default_subscription, message_handler
from autogen_core.code_executor import CodeBlock, CodeExecutor
from autogen_core.models import (
    AssistantMessage,
    ChatCompletionClient,
    LLMMessage,
    SystemMessage,
    UserMessage,
)


@dataclass
class Message:
    content: str


@default_subscription
class Assistant(RoutedAgent):
    def __init__(self, model_client: ChatCompletionClient) -> None:
        super().__init__("An assistant agent.")
        self._model_client = model_client
        self._chat_history: List[LLMMessage] = [
            SystemMessage(
                content="""Write Python script in markdown block, and it will be executed.
Always save figures to file in the current directory. Do not use plt.show()""",
            )
        ]

    @message_handler
    async def handle_message(self, message: Message, ctx: MessageContext) -> None:
        self._chat_history.append(UserMessage(content=message.content, source="user"))
        result = await self._model_client.create(self._chat_history)
        print(f"\n{'-'*80}\nAssistant:\n{result.content}")
        self._chat_history.append(AssistantMessage(content=result.content, source="assistant"))  # type: ignore
        await self.publish_message(Message(content=result.content), DefaultTopicId())  # type: ignore


def extract_markdown_code_blocks(markdown_text: str) -> List[CodeBlock]:
    pattern = re.compile(r"```(?:\s*([\w\+\-]+))?\n([\s\S]*?)```")
    matches = pattern.findall(markdown_text)
    code_blocks: List[CodeBlock] = []
    for match in matches:
        language = match[0].strip() if match[0] else ""
        code_content = match[1]
        code_blocks.append(CodeBlock(code=code_content, language=language))
    return code_blocks


@default_subscription
class Executor(RoutedAgent):
    def __init__(self, code_executor: CodeExecutor) -> None:
        super().__init__("An executor agent.")
        self._code_executor = code_executor

    @message_handler
    async def handle_message(self, message: Message, ctx: MessageContext) -> None:
        code_blocks = extract_markdown_code_blocks(message.content)
        if code_blocks:
            result = await self._code_executor.execute_code_blocks(
                code_blocks, cancellation_token=ctx.cancellation_token
            )
            print(f"\n{'-'*80}\nExecutor:\n{result.output}")
            await self.publish_message(Message(content=result.output), DefaultTopicId())

You might have already noticed, the agents’ logic, whether it is using model or code executor, is completely decoupled from how messages are delivered. This is the core idea: the framework provides a communication infrastructure, and the agents are responsible for their own logic. We call the communication infrastructure an Agent Runtime.

Agent runtime is a key concept of this framework. Besides delivering messages, it also manages agents’ lifecycle. So the creation of agents are handled by the runtime.

The following code shows how to register and run the agents using SingleThreadedAgentRuntime, a local embedded agent runtime implementation.

import tempfile

from autogen_core import SingleThreadedAgentRuntime
from autogen_ext.code_executors import DockerCommandLineCodeExecutor
from autogen_ext.models.openai import OpenAIChatCompletionClient

work_dir = tempfile.mkdtemp()

# Create an local embedded runtime.
runtime = SingleThreadedAgentRuntime()

async with DockerCommandLineCodeExecutor(work_dir=work_dir) as executor:  # type: ignore[syntax]
    # Register the assistant and executor agents by providing
    # their agent types, the factory functions for creating instance and subscriptions.
    await Assistant.register(
        runtime,
        "assistant",
        lambda: Assistant(
            OpenAIChatCompletionClient(
                model="gpt-4o",
                # api_key="YOUR_API_KEY"
            )
        ),
    )
    await Executor.register(runtime, "executor", lambda: Executor(executor))

    # Start the runtime and publish a message to the assistant.
    runtime.start()
    await runtime.publish_message(
        Message("Create a plot of NVIDA vs TSLA stock returns YTD from 2024-01-01."), DefaultTopicId()
    )
    await runtime.stop_when_idle()
--------------------------------------------------------------------------------
Assistant:
```python
import pandas as pd
import matplotlib.pyplot as plt
import yfinance as yf

# Define the stock tickers
ticker_symbols = ['NVDA', 'TSLA']

# Download the stock data from Yahoo Finance starting from 2024-01-01
start_date = '2024-01-01'
stock_data = yf.download(ticker_symbols, start=start_date)['Adj Close']

# Calculate daily returns
returns = stock_data.pct_change().dropna()

# Plot the stock returns
plt.figure(figsize=(10, 6))
for ticker in ticker_symbols:
    returns[ticker].cumsum().plot(label=ticker)

plt.title('NVIDIA vs TSLA Stock Returns YTD from 2024-01-01')
plt.xlabel('Date')
plt.ylabel('Cumulative Returns')
plt.legend()
plt.grid(True)

# Save the plot to a file
plt.savefig('nvidia_vs_tsla_stock_returns_ytd_2024.png')
```

--------------------------------------------------------------------------------
Executor:
Traceback (most recent call last):
  File "/workspace/tmp_code_f562e5e3c313207b9ec10ca87094085f.python", line 1, in <module>
    import pandas as pd
ModuleNotFoundError: No module named 'pandas'


--------------------------------------------------------------------------------
Assistant:
It looks like some required modules are not installed. Let me proceed by installing the necessary libraries before running the script.

```python
!pip install pandas matplotlib yfinance
```

--------------------------------------------------------------------------------
Executor:
  File "/workspace/tmp_code_78ffa711e7b0ff8738fdeec82404018c.python", line 1
    !pip install -qqq pandas matplotlib yfinance
    ^
SyntaxError: invalid syntax


--------------------------------------------------------------------------------
Assistant:
It appears that I'm unable to run installation commands within the code execution environment. However, you can install the necessary libraries using the following commands in your local environment:

```sh
pip install pandas matplotlib yfinance
```

After installing the libraries, you can then run the previous plotting script. Here is the combined process:

1. First, install the required libraries (run this in your terminal or command prompt):
    ```sh
    pip install pandas matplotlib yfinance
    ```

2. Now, you can run the script to generate the plot:
    ```python
    import pandas as pd
    import matplotlib.pyplot as plt
    import yfinance as yf

    # Define the stock tickers
    ticker_symbols = ['NVDA', 'TSLA']

    # Download the stock data from Yahoo Finance starting from 2024-01-01
    start_date = '2024-01-01'
    stock_data = yf.download(ticker_symbols, start=start_date)['Adj Close']

    # Calculate daily returns
    returns = stock_data.pct_change().dropna()

    # Plot the stock returns
    plt.figure(figsize=(10, 6))
    for ticker in ticker_symbols:
        returns[ticker].cumsum().plot(label=ticker)

    plt.title('NVIDIA vs TSLA Stock Returns YTD from 2024-01-01')
    plt.xlabel('Date')
    plt.ylabel('Cumulative Returns')
    plt.legend()
    plt.grid(True)

    # Save the plot to a file
    plt.savefig('nvidia_vs_tsla_stock_returns_ytd_2024.png')
    ```

This should generate and save the desired plot in your current directory as `nvidia_vs_tsla_stock_returns_ytd_2024.png`.

--------------------------------------------------------------------------------
Executor:
Requirement already satisfied: pandas in /usr/local/lib/python3.12/site-packages (2.2.2)
Requirement already satisfied: matplotlib in /usr/local/lib/python3.12/site-packages (3.9.2)
Requirement already satisfied: yfinance in /usr/local/lib/python3.12/site-packages (0.2.43)
Requirement already satisfied: numpy>=1.26.0 in /usr/local/lib/python3.12/site-packages (from pandas) (2.1.1)
Requirement already satisfied: python-dateutil>=2.8.2 in /usr/local/lib/python3.12/site-packages (from pandas) (2.9.0.post0)
Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.12/site-packages (from pandas) (2024.2)
Requirement already satisfied: tzdata>=2022.7 in /usr/local/lib/python3.12/site-packages (from pandas) (2024.1)
Requirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.12/site-packages (from matplotlib) (1.3.0)
Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.12/site-packages (from matplotlib) (0.12.1)
Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.12/site-packages (from matplotlib) (4.53.1)
Requirement already satisfied: kiwisolver>=1.3.1 in /usr/local/lib/python3.12/site-packages (from matplotlib) (1.4.7)
Requirement already satisfied: packaging>=20.0 in /usr/local/lib/python3.12/site-packages (from matplotlib) (24.1)
Requirement already satisfied: pillow>=8 in /usr/local/lib/python3.12/site-packages (from matplotlib) (10.4.0)
Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.12/site-packages (from matplotlib) (3.1.4)
Requirement already satisfied: requests>=2.31 in /usr/local/lib/python3.12/site-packages (from yfinance) (2.32.3)
Requirement already satisfied: multitasking>=0.0.7 in /usr/local/lib/python3.12/site-packages (from yfinance) (0.0.11)
Requirement already satisfied: lxml>=4.9.1 in /usr/local/lib/python3.12/site-packages (from yfinance) (5.3.0)
Requirement already satisfied: platformdirs>=2.0.0 in /usr/local/lib/python3.12/site-packages (from yfinance) (4.3.6)
Requirement already satisfied: frozendict>=2.3.4 in /usr/local/lib/python3.12/site-packages (from yfinance) (2.4.4)
Requirement already satisfied: peewee>=3.16.2 in /usr/local/lib/python3.12/site-packages (from yfinance) (3.17.6)
Requirement already satisfied: beautifulsoup4>=4.11.1 in /usr/local/lib/python3.12/site-packages (from yfinance) (4.12.3)
Requirement already satisfied: html5lib>=1.1 in /usr/local/lib/python3.12/site-packages (from yfinance) (1.1)
Requirement already satisfied: soupsieve>1.2 in /usr/local/lib/python3.12/site-packages (from beautifulsoup4>=4.11.1->yfinance) (2.6)
Requirement already satisfied: six>=1.9 in /usr/local/lib/python3.12/site-packages (from html5lib>=1.1->yfinance) (1.16.0)
Requirement already satisfied: webencodings in /usr/local/lib/python3.12/site-packages (from html5lib>=1.1->yfinance) (0.5.1)
Requirement already satisfied: charset-normalizer<4,>=2 in /usr/local/lib/python3.12/site-packages (from requests>=2.31->yfinance) (3.3.2)
Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.12/site-packages (from requests>=2.31->yfinance) (3.10)
Requirement already satisfied: urllib3<3,>=1.21.1 in /usr/local/lib/python3.12/site-packages (from requests>=2.31->yfinance) (2.2.3)
Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.12/site-packages (from requests>=2.31->yfinance) (2024.8.30)
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager, possibly rendering your system unusable.It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv. Use the --root-user-action option if you know what you are doing and want to suppress this warning.
  File "/workspace/tmp_code_d094fa6242b4268e4812bf9902aa1374.python", line 1
    import pandas as pd
IndentationError: unexpected indent


--------------------------------------------------------------------------------
Assistant:
Thank you for the confirmation. As the required packages are installed, let's proceed with the script to plot the NVIDIA vs TSLA stock returns YTD starting from 2024-01-01.

Here's the updated script:

```python
import pandas as pd
import matplotlib.pyplot as plt
import yfinance as yf

# Define the stock tickers
ticker_symbols = ['NVDA', 'TSLA']

# Download the stock data from Yahoo Finance starting from 2024-01-01
start_date = '2024-01-01'
stock_data = yf.download(ticker_symbols, start=start_date)['Adj Close']

# Calculate daily returns
returns = stock_data.pct_change().dropna()

# Plot the stock returns
plt.figure(figsize=(10, 6))
for ticker in ticker_symbols:
    returns[ticker].cumsum().plot(label=ticker)

plt.title('NVIDIA vs TSLA Stock Returns YTD from 2024-01-01')
plt.xlabel('Date')
plt.ylabel('Cumulative Returns')
plt.legend()
plt.grid(True)

# Save the plot to a file
plt.savefig('nvidia_vs_tsla_stock_returns_ytd_2024.png')
```

--------------------------------------------------------------------------------
Executor:
[*********************100%***********************]  2 of 2 completed


--------------------------------------------------------------------------------
Assistant:
It looks like the stock data was successfully downloaded, and the plot has been generated and saved as `nvidia_vs_tsla_stock_returns_ytd_2024.png` in the current directory.

If you have any further questions or need additional assistance, feel free to ask!

From the agent’s output, we can see the plot of Tesla’s and Nvidia’s stock returns has been created.

from IPython.display import Image

Image(filename=f"{work_dir}/NVIDIA_vs_TSLA_Stock_Returns_YTD_2024.png")  # type: ignore
/var/folders/cs/b9_18p1s2rd56_s2jl65rxwc0000gn/T/tmp_9c2ylon
../../_images/8565bb6207fd06989e12d34cdcccab026834375acceebcc8adc836e405c29e11.png

AutoGen also supports a distributed agent runtime, which can host agents running on different processes or machines, with different identities, languages and dependencies.

To learn how to use agent runtime, communication, message handling, and subscription, please continue reading the sections following this quick start.