In-Depth Analysis of Microsoft’s Agent Development Framework AutoGen 0.4: Introduction to AutoGen-Core

As one of the earliest LLM application development frameworks alongside LangChain and LlamaIndex, Microsoft’s AutoGen has undergone a complete redesign and restructuring after a series of personnel changes last year, launching the completely revamped AutoGen 0.4 version (the previous version was 0.2), with the latest stable version 0.4.2 released in early 2025.
In-Depth Analysis of Microsoft's Agent Development Framework AutoGen 0.4: Introduction to AutoGen-Core
You may have seen some superficial introductions, but after research and practice, we will bring you a more comprehensive and in-depth analysis of the new version.

This is a completely rewritten version of AutoGen that is not backward compatible, so this learning does not rely on the learning foundation of the old version v0.2. Additionally, since AutoGen focuses more on Agent applications, it can fully integrate with LangGraph/LlamaIndex Workflows, thus learning AutoGen will provide you with more flexible development combination choices.

We will gradually get to know the two different framework levels of the new version, AutoGen-Core and AutoGen-AgentChat. The content of AutoGen-Core includes:

  • Introduction to AutoGen 0.4 and AutoGen-Core
  • AutoGen-Core: Using Tools and Code Executors
  • AutoGen-Core: Multi-Agent Work Patterns and Examples
  • AutoGen-Core: Integration with LangGraph/LlamaIndex
This article will first introduce the first part.

1

Understanding the Overall Architecture of AutoGen 0.4

Compared to the general power of LangChain (which is also somewhat bulky and complex) and the data-centric focus of LlamaIndex, AutoGen has always focused more on multi-agent applications from its inception. In the old version, you could quickly build a multi-agent system using the pre-set upper-layer Agent components of AutoGen and complete input tasks through the “chat” mode. However, due to inherent architectural limitations, there were also issues such as limited collaboration modes, insufficient controllability, debugging difficulties, and poor scalability.
The brand new AutoGen 0.4 version adopts a layered, scalable modular architecture, which is a asynchronous, message-driven, scalable multi-agent framework (the red part is our research focus):

In-Depth Analysis of Microsoft's Agent Development Framework AutoGen 0.4: Introduction to AutoGen-Core

Image from Microsoft official
Its main feature is:providing multi-level reusable components from the underlying core framework (Core) to high-level APIs (AgentChat) to application layers (Apps), allowing developers to use the framework at different levels as needed. The higher the level used, the less development effort required, but the less flexibility; while using the lowest level Core framework represents higher complexity, but of course greater capability, capable of handling almost all LLM application development scenarios.
First, let’s establish a preliminary understanding of each level:
  • Core (Core Framework):Provides basic components and runtime environment.Includes basic abstractions such as message communication, message-driven Agents, Tools, logs, etc., as well as support for the operation of distributed Agent systems.
  • AgentChat (High-Level API Layer):High-level APIs built on top of Core.Includes various pre-built Agent types, Agent team types, Message types, etc. This is the level closest to the old version of AutoGen, making it convenient for migration from the old version.
  • Extensions:Third-party extension components to improve the ecosystem.For example, third-party LLM components, code executors, Tools, more pre-set Agents, etc. You can also develop your own Extensions and submit them to the community.
  • Magentic-One:A general-purpose multi-agent application.Can be used for web browsing, code execution, file processing, and other automated tasks. It is built on top of the magentic_one component in the Extensions layer.
In addition, AutoGen integrates two convenient development tools:
  • AutoGen Studio:A UI program for low-code development of multi-Agent applications.It can be imagined as Coze based on the underlying AutoGen framework.
  • AutoGen Bench:A tool for evaluating Agent performance and benchmarking suite.Part of the engineering platform.

Although AutoGen 0.4 has a clear layered design, it does not mean absolute isolation during use. For example, you may use components from the Extensions while developing with Core; or use a certain encapsulated Agent type from AgentChat, as will be seen in later examples.

2

AutoGen-Core: Core Concepts

The biggest difference between AutoGen 0.4 and the old version is: it provides a framework and components for rapidly building message-driven, distributed, scalable multi-Agent systems, namely AutoGen-core.
AutoGen-Core provides the basic management and runtime environment for multi-Agents. This is represented in the diagram below:

In-Depth Analysis of Microsoft's Agent Development Framework AutoGen 0.4: Introduction to AutoGen-Core

Understanding several core concepts in AutoGen-Core:
[Agent]
You can think of an Agent as a software object that can respond to messages.Agents can maintain their own state and data, and their response process can be any custom logic, such as calling APIs, sending messages to other Agents, executing Python code, etc. Thus, as shown in the diagram, you can also call Agent Workflows developed with LangGraph or LlamaIndex.
If this Agent is driven by LLM, then it is an AI Agent.
[Runtime]
You can think of Runtime as a server similar to a web container.The main functions of Runtime are:
  • Managing the registration, creation, and destruction of Agents, as well as lifecycle management
  • Providing a message communication mechanism between Agents
Runtime can run on a single machine or distribute across multiple machines. That is, multiple Runtimes run on different physical machines and coordinate communication and management through a primary Runtime.
[Agent ID]
You can think of Agent ID as the unique “identity card” of an Agent instance.An Agent ID consists of two parts:
  • Agent Type: Represents the type of this Agent instance.
  • Agent Key: Represents the identifier of this Agent instance.
Agent ID is also the “communication address” for message communication between Agent instances. For example, if you need to send a message to a certain Agent instance, you only need to know its Agent ID.
[Messages and Communication]
Messages represent the structured content of communication between Agent instances. The structure of messages can be fully customized, and there are two types of message communication mechanisms in AutoGen-Core:
  • Direct Messages:That is, sending messages directly to a certain Agent instance, where the sender can be either an Agent instance or the Runtime.
  • Broadcast and Subscribe:Broadcasters publish messages to a certain topic, and all Agent instances subscribed to that topic will receive the message.
Basically, understanding these basic concepts will allow you to develop controllable, message-driven Agent systems with AutoGen-Core (this system can even be unrelated to AI).

3

AutoGen-Core: Hello World!

We will use a simple application to understand the core concepts of AutoGen-Core mentioned above. In this scenario:
There are two Agents, ManagerAgent and WorkerAgent. After receiving the task message (Hello World), ManagerAgent will forward it to Worker to complete and receive feedback.

In-Depth Analysis of Microsoft's Agent Development Framework AutoGen 0.4: Introduction to AutoGen-Core

We will gradually create this application:
[Defining Message Type]
Use the dataclass decorator to customize the message type:
from dataclasses import dataclass

@dataclass
class MyTextMessage:
    content: str
[Defining WorkerAgent]
Derive from the basic abstract RoutedAgent provided by AutoGen-core to quickly create WorkerAgent; to handle messages, you can use the @message_handler decorator to implement your own message handling methods. Each message_handler will receive two input parameters: the message body and the message context.
Note that here, in order for ManagerAgent to receive feedback, we return a message.
from autogen_core import AgentId, MessageContext, RoutedAgent, message_handler

class MyWorkerAgent(RoutedAgent):
    def __init__(self) -> None:
        super().__init__("MyWorkerAgent")
        
    @message_handler
    async def handle_my_message(self, message: MyTextMessage, ctx: MessageContext) -> MyTextMessage:
        print(f"{self.id.key} received a message from {ctx.sender}: {message.content}\n")
        return MyTextMessage(content="OK, Got it!")
[Defining ManagerAgent]
ManagerAgent is different from Worker; since it needs to forward task messages to WorkerAgent, it retains a reference to WorkerAgent during initialization (just specify an AgentId, and the Agent instance will be automatically created by Runtime when necessary). The subsequent message processing process is as follows:
  • Receive the task message, usually sent by Runtime
  • Forward the message to WorkerAgent (using AgentId)
  • Wait for the response message from WorkerAgent and output
class MyManagerAgent(RoutedAgent):
    def __init__(self) -> None:
        super().__init__("MyManagerAgent")
        self.worker_agent_id = AgentId('my_worker_agent', 'worker')

    @message_handler
    async def handle_my_message(self, message: MyTextMessage, ctx: MessageContext) -> None:
        print(f"{self.id.key} received message: {message.content}\n")
        print(f"{self.id.key} sending message to {self.worker_agent_id}...\n")
        response = await self.send_message(message, self.worker_agent_id)
        print(f"{self.id.key} received a message from {self.worker_agent_id}: {response.content}\n")
Creating and Starting Runtime
After defining the Agents, you can create the Runtime and run it:
  • Create Runtime, responsible for starting and stopping
  • Register the defined Agent types and specify factory functions for instantiation
  • Send task messages to the entry Agent instance through Runtime, here it is ManagerAgent
The main program implementation is as follows:
from autogen_core import SingleThreadedAgentRuntime
import asyncio

async def main():

    # Create runtime and register agent types
    runtime = SingleThreadedAgentRuntime()
    await MyManagerAgent.register(runtime, "my_manager_agent", lambda: MyManagerAgent())
    await MyWorkerAgent.register(runtime, "my_worker_agent", lambda: MyWorkerAgent())

    # Start runtime, send messages, close runtime
    runtime.start() 

    # Create agent_id, send message
    agent_id = AgentId("my_manager_agent", "manager")
    await runtime.send_message(MyTextMessage(content="Hello World!"), agent_id)

    # Close runtime
    await runtime.stop_when_idle() 

asyncio.run(main())
In the above code:
  • Register Agents using the class method register(), setting the Agent class name and factory method during registration
  • The initial task message is sent via Runtime.send_message()
  • Sending a direct message with send_message only requires specifying the AgentId that receives the message, without having to worry about whether its real instance exists; Runtime will manage it automatically
Now running this simple application should yield the following output:

In-Depth Analysis of Microsoft's Agent Development Framework AutoGen 0.4: Introduction to AutoGen-Core

Now I believe you have some understanding of the core mechanisms of AutoGen-Core.
This just created a multi-Agent application that is unrelated to AI, asynchronous, and message-driven (not yet an AI Agent); now let’s introduce AI capabilities.

4

AutoGen-Core: The First AI Agent

We will create the simplest AI Agent: responding to tasks with LLM and supporting simple conversational context memory.
Since it only involves a simple Agent, the logic is simpler than the previous section’s “Hello World”, but it introduces LLM responses. Here is the core implementation:
......
@dataclass
class Message:
    content: str

class MyAgent(RoutedAgent):
    def __init__(self) -> None:
        super().__init__("A simple agent")
        self._system_messages = [SystemMessage(content="You are a helpful AI assistant. Please answer using Chinese.")]
        self._model_client = OpenAIChatCompletionClient(model="gpt-4o-mini")
        self._model_context = BufferedChatCompletionContext(buffer_size=5)

    @message_handler
    async def handle_user_message(self, message: Message, ctx: MessageContext) -> Message: 
        user_message = UserMessage(content=message.content, source="user")
        await self._model_context.add_message(user_message)
        response = await self._model_client.create(
            self._system_messages + (await self._model_context.get_messages()), cancellation_token=ctx.cancellation_token
        )
        await self._model_context.add_message(AssistantMessage(content=response.content, source=self.metadata["type"]))
        return Message(content=response.content)
In this code:
  • Using model_client to access LLM; using model_context to save conversational history;
  • Each time a new message is received, it adds the new message to the conversation history and passes it to LLM for output
  • After adding the LLM output message to the conversation history, it returns the response content
Using the same method as in the previous section to create Runtime, register, and start, after sending a task message to the Agent, you have completed a call to the above Agent:
...
    # Create agent_id, send message
    message = Message("What is the capital city of China?")
    response = await runtime.send_message(message, AgentId("my_agent", "default"))    print(response.content)

And thus, a minimalist version of an Agent based on AutoGen-Core is completed.

In fact, this is just a simple LLM application, without external tool usage, long-term memory, ReAct, and other capabilities. We will continue to introduce how to develop AI Agents with tool capabilities using AutoGen-Core in the next article.

end

Welfare Time

To help LLM developers learn RAG applications more systematically and in-depth, especially in enterprise-level RAG application scenarios, the current mainstream optimization methods and technical implementations, we have written “Development and Optimization of RAG Applications Based on Large Models – Building Enterprise-Level LLM Applications”, a 500-page development and optimization guide, to explore the new world of LLM application development together.

For more details, click the link to learn more In-Depth Analysis of Microsoft's Agent Development Framework AutoGen 0.4: Introduction to AutoGen-Core

Purchase here to enjoy a 50% discount

Please identify the following business card for communication
In-Depth Analysis of Microsoft's Agent Development Framework AutoGen 0.4: Introduction to AutoGen-Core

Leave a Comment