Guía de referencia

Encuentra rápidamente información detallada sobre cada componente del Framework de agentes en esta referencia integral.

Estructura de carpetas

Para compilar un agente, crea una carpeta para ese agente, con el nombre del agente y que contenga al menos los siguientes archivos:

  • agent.py: Es el archivo principal del agente. Debes definir tu agente raíz en la variable global root_agent.
  • __init__.py: Es el archivo del módulo de Python. Debe contener al menos una línea from agents import Agent para importar la clase Agent.

De manera opcional, te recomendamos que agregues los siguientes archivos:

  • requirements.txt: Es el archivo de requisitos de Python para el agente.
  • README.md: Es el archivo readme del agente. Debe contener las instrucciones para configurar y ejecutar el agente.

El agente.py mínimo

La compilación de un agente comienza con la creación de una instancia de la clase Agent. El agente mínimo debe tener los siguientes atributos:

  • name: Es el nombre del agente.
  • model: Es el nombre del modelo de LLM que se usará.
  • instruction: Instrucciones en lenguaje natural para el agente.

Por ejemplo:

from agents import Agent

root_agent = Agent(
    model='gemini-1.5-flash',
    name='root_agent',
    instruction="Be polite and answer all users' questions.",
)

Para crear un agente mínimo, puedes copiar la carpeta _empty_agent y modificar el archivo agent.py.

Atributos

nombre

  name: str

El nombre del agente.

  • Identificador

    • El nombre debe seguir la convención de nombres de identificadores.
    • Una cadena se considera un identificador válido si solo contiene letras alfanuméricas (a-z) y (0-9), o guiones bajos (_). Un identificador válido no puede comenzar con un número ni contener espacios.
  • Único

    • El nombre debe ser único en todo el árbol de agentes.
  • Agente raíz

    • Si bien la variable del agente raíz debe llamarse root_agent, puedes establecer un atributo de nombre más significativo para el agente raíz.

modelo

  model: str

Es el nombre del modelo de LLM que se usará.

  • Obligatorio para el agente de LLM

    • El atributo model solo es obligatorio para el agente de LLM.
    • No es necesario que configures el atributo del modelo para Sequential, Loop o cualquier otro agente que no sea de LLM.
  • Agente superior

    • Puedes omitir el atributo del modelo. En este caso, el agente usará el atributo de modelo del agente superior o ancestral.
  • Formato

    • El formato del nombre del modelo varía según el proveedor del LLM.
    • En el caso de Gemini, se ve como gemini-1.5-flash o gemini-2.0-flash-exp.
    • Para Anthropic en Vertex, se ve como claude-3-5-sonnet-v2@20241022.
    • Si bien el diseño del framework permite cualquier proveedor de modelos, actualmente solo admitimos Gemini y Anthropic en Vertex.

instrucción

  instruction: str | InstructionProvider

Las instrucciones en lenguaje natural para el agente.

  • Obligatorio para el agente de LLM

    • La instrucción solo es necesaria para el agente de LLM.
    • No es necesario que configures el atributo de instrucción para Sequential, Loop o otros agentes que no sean de LLM.
  • Tipo de datos

    • La instrucción puede ser una cadena.
    • La instrucción también puede ser un InstructionProvider que se pueda llamar.
  • InstructionProvider

    • Un InstructionProvider se define como Callable[[InvocationContext], str].
    • Te permite proporcionar una función para generar de forma dinámica la instrucción según el contexto de invocación.
  • Estado

    • La instrucción es una plantilla de cadena. Puedes usar la sintaxis {var} para insertar valores dinámicos en la instrucción.

    var

    se usa para insertar el valor de la variable de estado llamada var.

    artifact.var

    se usa para insertar el contenido de texto del artefacto llamado var.
    • Si la variable de estado o el artefacto no existen, el agente mostrará un error. Si quieres ignorar el error, puedes agregar un ? al nombre de la variable, p.ej., {var?}.
  • Lineamientos

    • Comienza por indicar quién es el agente, qué puede hacer y qué no puede hacer.
    • Puedes usar el formato Markdown para que los lineamientos sean más legibles, tanto para las personas como para el modelo.
    • Si el agente puede realizar varias tareas, proporciónale una lista de tareas y crea secciones separadas para cada una.
    • Si una tarea tiene varios pasos, proporciona una lista de pasos y instrucciones detalladas para cada uno.
    • Si el agente puede usar herramientas, indícalas en el atributo tools. La definición de la herramienta tiene instrucciones sobre cómo usarlas, pero se pueden agregar instrucciones detalladas sobre cuándo usarlas a la instrucción del agente para mejorar el rendimiento.
    • En el caso de un sistema de múltiples agentes, describe cuándo debe transferir el control al otro agente.
    • Puedes incluir ejemplos de entrada y salida esperada en la instrucción. También puedes usar el atributo examples para proporcionar ejemplos.
    • Sé detallado y específico en la instrucción. Trata al agente como un empleado nuevo que está pasando por el proceso de capacitación.
    • No confíes en las instrucciones sobre las reglas que se deben seguir el 100% del tiempo. El modelo tiene intrínsecamente cierto grado de libertad y puede cometer errores. Usa herramientas y devoluciones de llamada para aplicar reglas estrictas.

descripción

  description: str

Describe lo que puede hacer este agente. Esta descripción se envía al modelo como parte de las instrucciones del sistema para lo siguiente:

  1. El agente comprende sus propias capacidades en función de la descripción.

  2. Un agente comprende lo que pueden hacer otros agentes y decide si realizar la transferencia en función de sus descripciones.

global_instruction

  global_instruction: str | InstructionProvider

Es la instrucción global para todo el árbol de agentes.

Mientras que la instrucción le indica a un agente en particular qué hacer y cómo hacerlo, la instrucción global se aplica a todos los agentes del árbol de agentes.

El uso de la instrucción global es similar al atributo de instrucción, incluido el tipo de datos, la compatibilidad con InstructionProvider y la capacidad de acceder a variables y artefactos de estado.

  • Identificación y comportamiento
    • Usas la instrucción global para establecer la identidad y el comportamiento o estándar para todo el árbol de agentes, en lugar de cómo realizar una tarea específica para un agente en particular.

generate_content_config

  generate_content_config: google.genai.types.GenerateContentConfig

Configuración de modelo adicional para el agente. Estos se combinarán en la solicitud al modelo.

Hay algunos atributos que no debes configurar en este campo porque el framework los administra: - tools - system_instruction - response_schema

examples

  examples: list[Example] | BaseExampleProvider

Los ejemplos con muestras para el agente. Las investigaciones demuestran que proporcionar ejemplos de pocas fotos puede mejorar el rendimiento del agente.

  • Ejemplos estáticos
    • Puedes proporcionar una lista de ejemplos estáticos. Un ejemplo se define de la siguiente manera, en la que input es el contenido de entrada y output es el contenido de salida esperado.
class Example(BaseModel):
  input: types.Content
  output: list[types.Content]
  • Lista de salidas

    • El resultado puede ser una lista de Content.
    • Por lo tanto, puedes definir una secuencia de contenido como el resultado esperado. Por ejemplo, el modelo primero debe realizar una llamada a función y, luego, generar texto.
  • BaseExampleProvider

    • También puedes proporcionar una instancia de la clase BaseExampleProvider.
    • La clase BaseExampleProvider tiene un método get_examples(query: str) y muestra una lista de Example.
    • Con BaseExampleProvider, puedes generar de forma dinámica los ejemplos según la consulta.

greeting_prompt

  greeting_prompt: str

Puedes establecer una instrucción que se enviará al modelo para generar un mensaje de saludo. La instrucción de saludo se usará cuando llames al agente con una sesión vacía y una entrada del usuario vacía.

Planificación

  planning: bool

Si estableces planning como verdadero, se habilitará el modo de planificación para el agente. En el modo de planificación, el agente primero generará un plan para abordar la consulta del usuario y, luego, lo ejecutará paso a paso.

code_executor

  code_executor: BaseCodeExecutor

El agente que creaste tiene la capacidad de resolver problemas escribiendo código y ejecutándolo.

Hay dos maneras de habilitar la ejecución de código:

  1. Algunos modelos pueden ejecutar código directamente. Por ejemplo, el modelo Gemini 2.0 en modo activo genera y ejecuta código automáticamente, sin necesidad de una herramienta de ejecución de código independiente.

  2. Puedes establecer el atributo code_executor en una instancia de la clase BaseCodeExecutor para habilitar la ejecución de código. Actualmente, tenemos una clase VertexCodeExecutor y UnsafeLocalCodeExecutor (como los códigos generados por LLM pueden ser devastadores, solo usa UnsafeLocalCodeExecutor para el prototipado) que puedes usar para ejecutar código en Vertex AI. Se agregarán más ejecutores de código en el futuro.

input_schema

  input_schema: type[BaseModel]

El agente aplicará el esquema de entrada cuando especifiques un modelo de Pydantic como input_schema. El contenido de entrada debe ser una cadena JSON que cumpla con el esquema.

output_schema

  output_schema: type[BaseModel]

El agente aplicará el esquema de salida cuando especifiques un modelo de Pydantic como output_schema. El contenido de salida siempre será una cadena JSON que cumpla con el esquema.

output_key

  output_key: str

El agente almacenará su salida en la variable de estado con el nombre que especifique el atributo output_key.

include_contents

  include_contents: Literal['default', 'none']

El agente incluirá el contenido del historial de la sesión (historial de chat) de forma predeterminada. Puedes establecer el atributo include_contents en none para inhabilitar este comportamiento, en cuyo caso el agente específico no verá el historial de chat. Esto es útil cuando el agente no necesita saber sobre el historial de chat.

Herramientas

La capacidad de usar herramientas diferencia a los agentes del modelo. Del mismo modo, la habilidad para usar herramientas de manera compleja y versátil se considera una característica definitoria de los seres humanos.

En el framework de agentes, le proporcionas herramientas a tu agente a través del atributo tools. El atributo tools es una lista de herramientas, cada una de las cuales puede ser:

  • Una función de Python.
  • Una clase que implemente la clase BaseTool.

Herramienta de función de Python

Puedes definir una función de Python como una herramienta.

  • Parámetros

    • Tu función puede tener cualquier cantidad de parámetros.
    • Cada parámetro puede ser de cualquier tipo, siempre que el tipo sea serializable en JSON.
    • No establezcas un valor predeterminado para tus parámetros, ya que el modelo no los admite.
  • Tipo de datos que se muestra

    • El tipo de datos que se muestra debe ser un diccionario.
    • Si devuelves algo que no sea un diccionario, el framework lo unirá en un diccionario con una sola clave result.
    • Intenta ser descriptivo en el valor que se muestra. Por ejemplo, en lugar de mostrar un código de error numérico, muestra un error_message: str con un mensaje de error legible por humanos. Recuerda que este valor que se muestra es para que el modelo lo lea y comprenda, en lugar de que lo ejecute un fragmento de código.
    • Es recomendable tener una clave status para indicar success, error, pending, etc., de modo que el modelo comprenda el estado general de la operación.
  • Cadena de documentos

    • La cadena de documentos de la función se usará como descripción de la herramienta y se enviará al modelo. Por lo tanto, cuanto mejor sea la docstring, mejor podrá usar la herramienta el modelo.
  • Simplicidad

    • Aunque tienes mucha libertad para definir tu función, debes mantenerla simple y fácil para que el modelo pueda usarla con mayor precisión.
    • Tener menos parámetros es mejor que tener muchos.
    • Usa tipos de datos simples tanto como sea posible, p.ej., str, int, en lugar de clases personalizadas.
    • El nombre de la función y los parámetros son muy importantes. Si tienes una función llamada do_stuff(), incluso si le dices al modelo que se usa para cancelar un vuelo, es posible que el modelo se niegue a usarla.
    • Separa las funciones complejas en otras más pequeñas. Por ejemplo, separa update_profile(profile: Profile) en update_name(name: str), update_age(age: int), etcétera.
  • Referencia en la instrucción

    • Puedes hacer referencia a la herramienta en la instrucción con su nombre.
    • Si el nombre y la docstring de la función son lo suficientemente detallados, puedes enfocarte solo en cuándo usar la herramienta en la instrucción.
    • Indícale al agente cómo manejar los diferentes valores que se muestran. p.ej., si la herramienta muestra un mensaje de error, ¿debe el agente renunciar, reintentarlo o solicitar más información?
    • Las herramientas se pueden usar en secuencia, y una puede depender del resultado de otra. Describe la secuencia en la instrucción.

Contexto de la herramienta

En la función de la herramienta, puedes agregar un parámetro especial tool_context: ToolContext para obtener información adicional sobre el contexto en el que se llama a la herramienta.

La clase ToolContext está en el módulo agents.types y tiene los siguientes atributos:

  • function_call_event_id: str
    • Es el ID del evento en el que se activa la llamada a la herramienta.
  • function_call_id: str
    • El ID de la llamada a función.
  • state: State
    • Un objeto similar a un diccionario para leer y actualizar las variables de estado.
  • actions: EventActions
    • Son acciones adicionales que puede realizar la herramienta.

La clase EventActions se encuentra en el módulo agents.events y tiene los siguientes atributos para permitir que la herramienta realice acciones adicionales:

  • skip_summarization: bool
    • Si se establece como "True", el framework omitirá el paso de resumen del evento en el que se llama a la herramienta.
  • transfer_to_agent: str
    • Si se configura, el framework se transferirá al agente con el nombre que especifique el atributo transfer_to_agent.
  • escalate: bool
    • Si se establece como "True", el agente derivará la consulta a su agente superior. La derivación de un agente secundario dentro de un LoopFlow significa el final del bucle.

AsyncFunctionTool

AsyncFunctionTool es una subclase de FunctionTool. Está diseñado para herramientas que tardan mucho tiempo en completarse.

Para crear una AsyncFunctionTool, debes definir una función de Python normal y unirla a la clase AsyncFunctionTool. De la siguiente manera: AsyncFunctionTool(func=your_function)

AsyncFunctionTool seguirá llamando a tu función de Python, en la que puedes iniciar la tarea que podría tardar mucho tiempo. Puedes mostrar un resultado intermedio al modelo para informarle que la tarea aún no está completa. Agregar información como status: 'pending', progress: 20, estimated_completion_time: '...', etcétera, ayudará al modelo a proporcionar una respuesta significativa al usuario.

Más adelante, cuando finalice la operación, puedes llamar al agente con una nueva FunctionResponse para proporcionar el resultado final. En ese momento, el agente generará una respuesta final para el usuario.

AgentTool

AgentTool te permite llamar a otro agente para que realice una tarea. Esto equivale a crear una función de Python, llamar a otro agente con los argumentos de la función y usar la respuesta de ese agente como el valor que se muestra de la función.

Una AgentTool es diferente de un agente secundario:

  • Cuando el agente A llama al agente B como una AgentTool, la respuesta del agente B se pasa al agente A, que resumirá la respuesta y generará una respuesta para el usuario. El agente A seguirá respondiendo las entradas del usuario en el futuro.
  • Cuando el agente A llama al agente B como agente secundario, la responsabilidad de responder al usuario se transfiere por completo al agente B. El agente A no estará en la imagen. En este caso, el agente B responderá las entradas futuras del usuario.

Para usar un agente como herramienta, puedes usar la clase AgentTool para unirlo. Por ejemplo: tools=[AgentTool(agent=agent_b)].

AgentTool tiene los siguientes atributos para personalizar su comportamiento:

  • skip_summarization
    • Si se establece como verdadero, el framework omitirá llamar al LLM para resumir la respuesta del agente de herramientas.

Devoluciones de llamada

Tipos de devolución de llamada

Puedes definir devoluciones de llamada para personalizar aún más el comportamiento del agente. Admitimos dos tipos de devoluciones de llamada:

  • Se llama a BeforeCallbacks antes de que el agente realice una acción. Puedes modificar la acción, omitirla o realizar acciones adicionales.
  • Se llama a AfterCallbacks después de que el agente realiza una acción. Puedes usar esta devolución de llamada para modificar el resultado de la acción o realizar acciones adicionales.

Acciones admitidas

Tenemos BeforeCallbacks y AfterCallbacks para las siguientes acciones:

  • Llamar a un agente
  • Llamar a un LLM
  • Llamar a una herramienta

Lista de devoluciones de llamada

Como resultado, tenemos las siguientes 6 devoluciones de llamada, que son atributos de la clase Agent:

before_agent_callback

def before_agent_callback(invocation_context: InvocationContext) -> Content | None
  • Una invocación puede incluir varias llamadas al agente. Por lo tanto, se podría llamar a esta devolución de llamada varias veces.
  • Si devuelves un Content desde esta devolución de llamada, el agente omitirá la llamada del agente actual y usará el Content que se devolvió como respuesta.

after_agent_callback

def after_agent_callback(invocation_context: InvocationContext) -> Content | None
  • Una invocación puede incluir varias llamadas a agentes. Por lo tanto, se podría llamar a esta devolución de llamada varias veces.
  • Si devuelves un Content desde esta devolución de llamada, el agente adjuntará el Content que se muestra después de su propia respuesta.

before_model_callback

def before_model_callback(
    invocation_context: InvocationContext,
    llm_request: LlmRequest) -> LlmResponse | None
  • Una llamada de agente puede incluir varias llamadas a LLM. Por lo tanto, se podría llamar a esta devolución de llamada varias veces.
  • Si devuelves un LlmResponse desde esta devolución de llamada, el agente usará el LlmResponse que se devuelve como la respuesta y omitirá llamar al modelo.

before_model_callback

def after_model_callback(
    invocation_context: InvocationContext,
    llm_response: LlmResponse) -> LlmResponse | None
  • Una llamada de agente puede incluir varias llamadas a LLM. Por lo tanto, se podría llamar a esta devolución de llamada varias veces.
  • Si devuelves un LlmResponse desde esta devolución de llamada, el agente usará el LlmResponse que se muestra como la respuesta, en lugar de la respuesta que genera el modelo.

before_tool_callback

def before_tool_callback(
    invocation_context: InvocationContext,
    tool: BaseTool,
    args: dict[str, Any],
    tool_context: ToolContext) -> dict | None
  • Una llamada de modelo puede incluir varias llamadas de herramientas. Por lo tanto, se podría llamar a esta devolución de llamada varias veces.
  • Si devuelves un dict desde esta devolución de llamada, el agente usará el dict que se devuelve como la respuesta y omitirá llamar a la herramienta.

after_tool_callback

def after_tool_callback(
    invocation_context: InvocationContext,
    tool: BaseTool,
    args: dict[str, Any],
    tool_context: ToolContext,
    response: dict) -> dict | None
  • Una llamada de modelo puede incluir varias llamadas de herramientas. Por lo tanto, se podría llamar a esta devolución de llamada varias veces.
  • Si devuelves un dict desde esta devolución de llamada, el agente usará el dict que se devuelve como la respuesta, en lugar de la respuesta que genera la herramienta.

Sesiones

No tienes que manipular directamente el objeto de sesión cuando compilas un agente. El framework administrará el objeto de sesión por ti. Sin embargo, es útil comprender qué es y cómo funciona la sesión.

Una sesión en el Framework de agentes tiene dos componentes principales:

  • Eventos: Es una lista de eventos.
  • Estado: Es un objeto similar a un diccionario de variables de estado.

Eventos

Events es solo una lista simple de objetos de evento. Puedes pensar en él como un historial de chat, ya sea entre un usuario y un agente, o entre diferentes agentes. No solo registra las palabras del usuario o del modelo, sino también todas las acciones que realiza el agente, como llamar a una herramienta, la respuesta de la herramienta, llamar a otro agente, etcétera.

La lista de eventos es una lista de solo inserción. Solo puedes agregar eventos a la lista, pero no puedes quitar ni modificar ningún evento. Cuando ocurre un evento, no hay forma de cambiarlo. Lo diseñamos de esta manera para que el sistema sea simple y podamos volver a un momento específico para ver la instantánea exacta del sistema.

Estado

El estado es un objeto similar a un diccionario que contiene todas las variables de estado. Puedes acceder a ella desde los siguientes lugares:

  • Desde la instrucción, puedes usar la sintaxis {var} para insertar el valor de la variable de estado llamada var.
  • Desde las devoluciones de llamada, puedes acceder a la variable de estado con invocation_context.state['key']. También puedes actualizar la variable de estado con invocation_context.state['key'] = value.
  • Desde las herramientas, puedes acceder a la variable de estado con tool_context.state['key']. También puedes actualizar la variable de estado con tool_context.state['key'] = value.

El estado está asociado con una sesión en particular. Por lo tanto, es el lugar ideal para almacenar información útil en el contexto de esta sesión.

Todos los agentes del árbol de agentes pueden acceder al estado, lo que lo convierte en un lugar ideal para la comunicación entre agentes. Un agente puede realizar una acción y almacenar su resultado en el estado. Luego, otro agente puede leer el resultado del estado y continuar el trabajo.

Artefactos

Cuando el modelo o tu herramienta crean un archivo, ya sea una imagen, un video, un documento o cualquier otro formato, puedes almacenarlo como un artefacto. Un artefacto es un archivo asociado con una sesión en particular al que pueden acceder los agentes o tu propio código.

Casos de uso

  • Cuando tu agente trabaja con el usuario para crear o modificar un archivo. p. ej., un agente que ayuda al usuario a generar y editar una imagen
  • Cuando quieras que el agente responda preguntas sobre un archivo o lo edite según las instrucciones del usuario.

Beneficios de rendimiento

Otra forma de controlar archivos grandes es almacenarlos como bytes en el historial de chat. Sin embargo, este enfoque tiene algunas desventajas:

  • Esto ralentiza el historial de la sesión.
  • Es difícil recuperar el archivo del historial de chat.
  • Los bytes se enviarán al modelo para todas las solicitudes, incluso si la conversación no tiene nada que ver con esos archivos.

Cómo acceder a artefactos

Existen varias formas de acceder a los artefactos:

  • En la instrucción, puedes usar la sintaxis {artifact.var} para insertar el contenido de texto del artefacto llamado var. Aún no se admiten artefactos binarios.
  • En las devoluciones de llamada, puedes acceder al artefacto con invocation_context.get_artifact('key'). Puedes actualizar el artefacto con invocation_context.set_artifact('key', value).
  • En las herramientas, puedes acceder al artefacto con tool_context.get_artifact('key'). Puedes actualizar el artefacto con tool_context.set_artifact('key', value).

Sistemas de múltiples agentes

Un solo agente y una herramienta de lista pueden ser muy útiles para compilar un sistema complejo. Sin embargo, a veces, separar la lógica en varios agentes puede mejorar el rendimiento y la capacidad de mantenimiento del sistema en general.

Estas son las ocasiones en las que puedes considerar usar varios agentes:

  • Cuando la instrucción del agente se hace demasiado larga, con varias tareas y pasos para cada una.
  • Cuando tienes un flujo de trabajo más determinístico para ejecutar. p.ej., para un agente de investigación, siempre genera un plan, luego lo ejecuta y, luego, resume los hallazgos.

Árbol de agentes jerárquico

  children: list[BaseAgent]

Para crear un sistema multiagente, debes crear un árbol de agentes jerárquico. El agente raíz es el punto de entrada del sistema y puede llamar a otros agentes según su configuración.

Un agente puede tener varios agentes secundarios. Los agentes secundarios también pueden tener sus propios agentes secundarios. El árbol de agentes puede ser arbitrariamente profundo, pero por motivos de rendimiento, te recomendamos que uses un árbol menos profundo.

Para formar el árbol de agentes, colocas otros agentes como secundarios de un agente superior.

Flows

  flow: str | BaseFlow | FlowCallable

Cuando un agente recibe una consulta del usuario, puede controlarla él mismo o pasarla a otro agente. Esto se define por su atributo flow.

Hay algunos flujos predefinidos, y también puedes definir los tuyos.

  • sequential: El agente llamará a sus agentes secundarios uno por uno en secuencia.
  • loop: El agente llamará a sus agentes secundarios en un bucle. Hasta que cualquiera de los agentes secundarios establezca tool_context.actions.escalate como verdadero.
  • single: Este es un flujo basado en LLM. El agente llamará al LLM para responder la consulta del usuario y llamará a sus herramientas cuando sea necesario.
  • auto: Este es un flujo basado en LLM. El agente llamará al LLM para responder la consulta del usuario y llamará a sus herramientas cuando sea necesario. También puede transferir la consulta a sus elementos secundarios, a sus hermanos o a su elemento superior.
  • Flujos personalizados: Puedes definir tus propios flujos implementando la clase BaseFlow o simplemente definiendo una función de Python siguiendo la interfaz.