mirror of https://github.com/microsoft/autogen.git
Flesh out agent docs more (#71)
This commit is contained in:
parent
92d413e877
commit
c36ea487e0
|
@ -50,3 +50,9 @@ html_theme_options = {
|
|||
"source_branch": "main",
|
||||
"source_directory": "docs/src/",
|
||||
}
|
||||
|
||||
autodoc_default_options = {
|
||||
"members": True,
|
||||
"undoc-members": True,
|
||||
"private-members": True
|
||||
}
|
|
@ -2,23 +2,67 @@
|
|||
|
||||
An agent in AGNext is an entity that can react to, send, and publish
|
||||
messages. Messages are the only means through which agents can communicate
|
||||
with each others.
|
||||
with each other.
|
||||
|
||||
## TypeRoutedAgent
|
||||
Examples of agents include:
|
||||
|
||||
{py:class}`agnext.components.TypeRoutedAgent`
|
||||
is a base class for building custom agents. It provides
|
||||
a simple API for associating message types with message handlers.
|
||||
Here is an example of simple agent that reacts to `TextMessage`:
|
||||
- A chat completion agent that makes requests to an LLM in response to receiving messages.
|
||||
|
||||
```python
|
||||
from agnext.chat.types import TextMessage
|
||||
from agnext.components import TypeRoutedAgent, message_handler
|
||||
from agnext.core import AgentRuntime, CancellationToken
|
||||
## Messages
|
||||
|
||||
class MyAgent(TypeRoutedAgent):
|
||||
Messages are typed, and serializable (to JSON) objects that agents use to communicate. The type of a message is used to determine which agents a message should be delivered to, if an agent can handle a message and the handler that should be invoked when the message is received by an agent. If an agent is invoked with a message it is not able to handle, it must raise {py:class}`~agnext.core.exceptions.CantHandleException`.
|
||||
|
||||
@message_handler()
|
||||
async def on_text_message(self, message: TextMessage, cancellation_token: CancellationToken)) -> None:
|
||||
await self._publish(TextMessage(content=f"I received this message: ({message.content}) from {message.source}"))
|
||||
Generally, messages are one of:
|
||||
|
||||
- A subclass of Pydantic's {py:class}`pydantic.BaseModel`
|
||||
- A dataclass
|
||||
|
||||
Messages are purely data, and should not contain any logic.
|
||||
|
||||
### Required Message Types
|
||||
|
||||
At the core framework level there is *no requirement* of which message types are handled by an agent. However, some behavior patterns require agents understand certain message types. For an agent to participate in these patterns, it must understand any such required message types.
|
||||
|
||||
For example, the chat layer in AGNext has the following required message types:
|
||||
|
||||
- {py:class}`agnext.chat.types.PublishNow`
|
||||
- {py:class}`agnext.chat.types.Reset`
|
||||
|
||||
These are purely behavioral messages that are used to control the behavior of agents in the chat layer and do not represent any content.
|
||||
|
||||
Agents should document which message types they can handle. Orchestrating agents should document which message types they require.
|
||||
|
||||
```{tip}
|
||||
An important part of designing an agent or choosing which agents to use is understanding which message types are required by the agents you are using.
|
||||
```
|
||||
|
||||
## Communication
|
||||
|
||||
There are two forms of communication in AGNext:
|
||||
|
||||
- **Direct communication**: An agent sends a message to another agent.
|
||||
- **Broadcast communication**: An agent publishes a message to all agents.
|
||||
|
||||
### Message Handling
|
||||
|
||||
When an agent receives a message the runtime will invoke the agent's message handler ({py:meth}`agnext.core.Agent.on_message`) which should implement the agents message handling logic. If this message cannot be handled by the agent, the agent should raise a {py:class}`~agnext.core.exceptions.CantHandleException`. For the majority of custom agent's {py:meth}`agnext.core.Agent.on_message` will not be directly implemented, but rather the agent will use the {py:class}`~agnext.components.TypeRoutedAgent` base class which provides a simple API for associating message types with message handlers.
|
||||
|
||||
### Direct Communication
|
||||
|
||||
Direct communication is effectively an RPC call directly to another agent. When sending a direct message to another agent, the receiving agent can respond to the message with another message, or simply return `None`. To send a message to another agent, within a message handler use the {py:meth}`agnext.core.BaseAgent._send_message` method. Awaiting this call will return the response of the invoked agent. If the receiving agent raises an exception, this will be propagated back to the sending agent.
|
||||
|
||||
To send a message to an agent outside of agent handling a message the message should be sent via the runtime with the {py:meth}`agnext.core.AgentRuntime.send_message` method. This is often how an application might "start" a workflow or conversation.
|
||||
|
||||
### Broadcast Communication
|
||||
|
||||
As part of the agent's implementation it must advertise the message types that it would like to receive when published ({py:attr}`agnext.core.Agent.subscriptions`). If one of these messages is published, the agent's message handler will be invoked. The key difference between direct and broadcast communication is that broadcast communication is not a request/response pattern. When an agent publishes a message it is one way, it is not expecting a response from any other agent. In fact, they cannot respond to the message.
|
||||
|
||||
To publish a message to all agents, use the {py:meth}`agnext.core.BaseAgent._publish_message` method. This call must still be awaited to allow the runtime to deliver the message to all agents, but it will always return `None`. If an agent raises an exception while handling a published message, this will be logged but will not be propagated back to the publishing agent.
|
||||
|
||||
To publish a message to all agents outside of an agent handling a message, the message should be published via the runtime with the {py:meth}`agnext.core.AgentRuntime.publish_message` method.
|
||||
|
||||
If an agent publishes a message type for which it is subscribed it will not receive the message it published. This is to prevent infinite loops.
|
||||
|
||||
```{note}
|
||||
Currently an agent does not know if it is handling a published or direct message. So, if a response is given to a published message, it will be thrown away.
|
||||
```
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
# Cancellation
|
|
@ -0,0 +1 @@
|
|||
# Logging
|
|
@ -0,0 +1,50 @@
|
|||
# Using Type Routed Agent
|
||||
|
||||
To make it easier to implement agents that respond to certain message types there is a base class called {py:class}`~agnext.components.TypeRoutedAgent`. This class provides a simple decorator pattern for associating message types with message handlers.
|
||||
|
||||
The decorator {py:func}`agnext.components.message_handler` should be added to functions in the class that are intended to handle messages. These functions have a specific signature that needs to be followed for it to be recognized as a message handler.
|
||||
|
||||
- The function must be an `async` function.
|
||||
- The function must be decorated with the `message_handler` decorator.
|
||||
- The function must have exactly 3 arguments.
|
||||
- `self`
|
||||
- `message`: The message to be handled, this must be type hinted with the message type that it is intended to handle.
|
||||
- `cancellation_token`: A {py:class}`agnext.core.CancellationToken` object
|
||||
- The function must be type hinted with what message types it can return.
|
||||
|
||||
```{tip}
|
||||
Handlers can handle more than one message type by accepting a Union of the message types. It can also return more than one message type by returning a Union of the message types.
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
The following is an example of a simple agent that broadcasts the fact it received messages, and resets its internal counter when it receives a reset message.
|
||||
|
||||
One important thing to point out is that when an agent is constructed it must be passed a runtime object. This allows the agent to communicate with other agents via the runtime.
|
||||
|
||||
```python
|
||||
from agnext.chat.types import MultiModalMessage, Reset, TextMessage
|
||||
from agnext.components import TypeRoutedAgent, message_handler
|
||||
from agnext.core import AgentRuntime, CancellationToken
|
||||
|
||||
|
||||
class MyAgent(TypeRoutedAgent):
|
||||
def __init__(self, name: str, runtime: AgentRuntime):
|
||||
super().__init__(name, "I am a demo agent", runtime)
|
||||
self._received_count = 0
|
||||
|
||||
@message_handler()
|
||||
async def on_text_message(
|
||||
self, message: TextMessage | MultiModalMessage, cancellation_token: CancellationToken
|
||||
) -> None:
|
||||
await self._publish_message(
|
||||
TextMessage(
|
||||
content=f"I received a message from {message.source}. Message received #{self._received_count}",
|
||||
source=self.name,
|
||||
)
|
||||
)
|
||||
|
||||
@message_handler()
|
||||
async def on_reset(self, message: Reset, cancellation_token: CancellationToken) -> None:
|
||||
self._received_count = 0
|
||||
```
|
|
@ -27,12 +27,15 @@ common uses, such as chat completion agents, but also allows for fully custom ag
|
|||
core-concepts/patterns
|
||||
core-concepts/memory
|
||||
core-concepts/tools
|
||||
core-concepts/cancellation
|
||||
core-concepts/logging
|
||||
|
||||
.. toctree::
|
||||
:caption: Guides
|
||||
:hidden:
|
||||
|
||||
guides/azure_openai_with_aad_auth
|
||||
guides/type-routed-agent
|
||||
guides/azure-openai-with-aad-auth
|
||||
|
||||
|
||||
.. toctree::
|
||||
|
|
Loading…
Reference in New Issue