Comencemos con un ejemplo sencillo de dos agentes que hacen una cuenta regresiva del 10 al 1.
Primero definimos las clases de agentes y sus respectivos procedimientos para manejar mensajes. Creamos dos clases de agentes: Modifier y Checker. El agente Modifier modifica un número que se le proporciona, y el agente Checker verifica el valor según una condición. También creamos una clase de datos Message, que define los mensajes que se pasan entre los agentes.
from dataclasses import dataclass
from typing import Callable
from saptiva_agents.core import DefaultTopicId, MessageContext, RoutedAgent, default_subscription, message_handler
@dataclass
class Message:
content: int
@default_subscription
class Modifier(RoutedAgent):
def __init__(self, modify_val: Callable[[int], int]) -> None:
super().__init__("A modifier agent.")
self._modify_val = modify_val
@message_handler
async def handle_message(self, message: Message, ctx: MessageContext) -> None:
val = self._modify_val(message.content)
print(f"{'-'*80}\nModifier:\nModified {message.content} to {val}")
await self.publish_message(Message(content=val), DefaultTopicId()) # type: ignore
@default_subscription
class Checker(RoutedAgent):
def __init__(self, run_until: Callable[[int], bool]) -> None:
super().__init__("A checker agent.")
self._run_until = run_until
@message_handler
async def handle_message(self, message: Message, ctx: MessageContext) -> None:
if not self._run_until(message.content):
print(f"{'-'*80}\nChecker:\n{message.content} passed the check, continue.")
await self.publish_message(Message(content=message.content), DefaultTopicId())
else:
print(f"{'-'*80}\nChecker:\n{message.content} failed the check, stopping.")
Es posible que ya lo hayas notado: la lógica de los agentes, ya sea utilizando un modelo o un ejecutor de código, está completamente desacoplada de cómo se entregan los mensajes. Esta es la idea central: el framework proporciona una infraestructura de comunicación, y los agentes son responsables de su propia lógica. A esta infraestructura de comunicación la llamamos Agent Runtime.
Agent Runtime es un concepto clave de este framework. Además de entregar mensajes, también gestiona el ciclo de vida de los agentes. Por lo tanto, la creación de los agentes es gestionada por el runtime.
El siguiente código muestra cómo registrar y ejecutar los agentes utilizando SingleThreadedAgentRuntime, una implementación de runtime de agentes local y embebida.
Nota
Si estás utilizando VSCode u otro editor, recuerda importar asyncio y envolver el código con async def main() -> None: y ejecutar el código con la función asyncio.run(main()).
from saptiva_agents.core import AgentId, SingleThreadedAgentRuntime
# Crear un runtime embebido local.
runtime = SingleThreadedAgentRuntime()
# Registrar los agentes modifier y checker proporcionando
# sus tipos de agente, las funciones fábrica para crear instancias y suscripciones.
await Modifier.register(
runtime,
"modifier",
# Modificar el valor restando 1
lambda: Modifier(modify_val=lambda x: x - 1),
)
await Checker.register(
runtime,
"checker",
# Ejecutar hasta que el valor sea menor o igual a 1
lambda: Checker(run_until=lambda x: x <= 1),
)
# Iniciar el runtime y enviar un mensaje directo al checker.
runtime.start()
await runtime.send_message(Message(10), AgentId("checker", "default"))
await runtime.stop_when_idle()
Ejemplo de Interacción:
--------------------------------------------------------------------------------
Checker:
10 passed the check, continue.
--------------------------------------------------------------------------------
Modifier:
Modified 10 to 9
--------------------------------------------------------------------------------
Checker:
9 passed the check, continue.
--------------------------------------------------------------------------------
Modifier:
Modified 9 to 8
--------------------------------------------------------------------------------
Checker:
8 passed the check, continue.
--------------------------------------------------------------------------------
Modifier:
Modified 8 to 7
--------------------------------------------------------------------------------
Checker:
7 passed the check, continue.
--------------------------------------------------------------------------------
Modifier:
Modified 7 to 6
--------------------------------------------------------------------------------
Checker:
6 passed the check, continue.
--------------------------------------------------------------------------------
Modifier:
Modified 6 to 5
--------------------------------------------------------------------------------
Checker:
5 passed the check, continue.
--------------------------------------------------------------------------------
Modifier:
Modified 5 to 4
--------------------------------------------------------------------------------
Checker:
4 passed the check, continue.
--------------------------------------------------------------------------------
Modifier:
Modified 4 to 3
--------------------------------------------------------------------------------
Checker:
3 passed the check, continue.
--------------------------------------------------------------------------------
Modifier:
Modified 3 to 2
--------------------------------------------------------------------------------
Checker:
2 passed the check, continue.
--------------------------------------------------------------------------------
Modifier:
Modified 2 to 1
--------------------------------------------------------------------------------
Checker:
1 failed the check, stopping.
A partir de la salida del agente, podemos ver que el valor fue decrementado exitosamente de 10 a 1, tal como lo dictan las condiciones del modificador y del verificador.
Saptiva-Agents también admite un runtime de agentes distribuido, el cual puede alojar agentes que se ejecutan en diferentes procesos o máquinas, con diferentes identidades, lenguajes y dependencias.
Para aprender a usar el runtime de agentes, la comunicación, el manejo de mensajes y las suscripciones, por favor continúa leyendo las secciones siguientes a este inicio rápido.