Puedes proporcionar código de Python intercalado como herramienta para tu agente, lo que te brinda flexibilidad para ampliar sus capacidades. Este código puede aceptar entradas proporcionadas por el agente y devolver un resultado que el agente usa en la conversación. Puedes implementar cualquier lógica personalizada, conectarte a bases de datos o APIs propietarias, y garantizar resultados determinísticos para las tareas que requieren precisión.
Nombre y descripción
Cuando crees la herramienta, el nombre de la herramienta y el nombre de la función principal que se llamará deben ser el mismo nombre en formato snake_case.
Las cadenas de documentación son una parte fundamental de la definición de una herramienta de Python. La cadena de documentación de la función se usa como la descripción de la herramienta, que se proporciona a los agentes que la usan. Debes considerar las cadenas de documentación como una extensión de las instrucciones. Una cadena de documentación clara, descriptiva y bien estructurada influye directamente en la forma en que el modelo comprende lo que hace tu herramienta, cuándo usarla y qué argumentos proporcionar. Esta es la clave para lograr una selección de herramientas confiable y precisa.
Entorno
En el código de tu herramienta de Python, tienes acceso a ciertas clases y funciones que te ayudan a escribir el código. Para obtener más información, consulta la referencia del entorno de ejecución de Python.
Por ejemplo, el objeto context es una variable disponible de forma global que proporciona una instantánea del estado actual de la conversación.
No es necesario que lo importes ni lo definas como un parámetro; puedes acceder a él directamente.
Contiene información valiosa para ejecutar lógica compleja.
A continuación, se muestra un desglose de las claves disponibles en el objeto de contexto:
function_call_id: Es un ID único para la llamada a la herramienta específica que se está ejecutando.user_content: Es un diccionario que contiene el mensaje más reciente del usuario, incluido el texto y el rol. Este es uno de los atributos más utilizados.state: Es un diccionario que representa el estado de la sesión. Puedes usarlo para almacenar y recuperar variables que deben persistir en varios turnos de una conversación (perfil del usuario, contenido del carrito de compras, etcétera).events: Es una lista de todos los eventos del historial de conversaciones hasta este punto, lo que te permite crear herramientas con una mayor conciencia contextual.session_id: Es el identificador único de toda la sesión de conversación.invocation_id: Es un identificador único del turno actual de la conversación.agent_name: Es el nombre del agente que ejecuta la herramienta.
Herramientas de Python que llaman a otras herramientas
Cuando definas herramientas de código de Python, puedes llamar de forma explícita a otras herramientas definidas en la aplicación del agente.
Por ejemplo, si tienes una herramienta de OpenAPI llamada crm_service_get_cart_information, puedes llamarla con el siguiente código:
# Deterministically call another tool from this tool.
# This syntax for OpenAPI spec tool is:
# tools.<tool_name>_<endpoint_name>({tool_args})
res = tools.crm_service_get_cart_information({})
Muestras de código
En las siguientes secciones, se proporcionan ejemplos.
Obtén la última entrada del usuario
En este ejemplo, se demuestra una capacidad fundamental: acceder al mensaje más reciente del usuario.
La herramienta inspecciona el objeto context.user_content y extrae el texto del último turno del usuario.
Este patrón es esencial para cualquier herramienta que necesite realizar una acción basada directamente en lo que acaba de decir el usuario.
from typing import Optional
# Docstrings in tools are important because they are directly
# sent to the model as the description for the tool. You should
# think of docstrings as an extension of prompting. Clear and
# descriptive docstrings will yield higher quality tool
# selection from the model.
def get_last_user_utterance() -> Optional[str]:
"""
Retrieves the most recent message sent by the user from the conversation history.
Returns:
The text of the last user message, or None if no user messages are found.
"""
# The 'context.user_content' contains the last input data
# provided by the user.
# We can filter it to find only the text input from the user.
user_messages = [
part["text"] for part in context.user_content["parts"]
if context.user_content["role"] == "user"
]
if user_messages:
# The most recent message is the first one in the list.
return user_messages[0]
return None
Obtén y actualiza variables
Los modelos de lenguaje no pueden modificar directamente el estado de la sesión. Esto es intencional, ya que garantiza que los cambios de estado se controlen de forma predecible. El estado solo se puede modificar a través de dos mecanismos: Herramientas de Python o devoluciones de llamada.
En este ejemplo, se muestra cómo una herramienta de Python puede administrar el estado.
Primero, la herramienta lee el customer_profile actual de context.state.
Luego, ejecuta su lógica empresarial (agregar puntos) y vuelve a escribir el perfil actualizado en context.state.
Luego, este nuevo estado estará disponible para el agente y otras herramientas durante el resto de la sesión.
from pydantic import BaseModel, Field
from typing import Optional, Dict, Any
# Using Pydantic defines the expected structure of your state variables. This makes your code more reliable and easier to
# debug.
class CustomerProfile(BaseModel):
email: Optional[str] = None
loyalty_points: int = Field(default=0, ge=0) # Must be >= 0
plan: str = "Standard"
# Docstrings in tools are important because they are directly
# sent to the model as the description for the tool. You should
# think of docstrings as an extension of prompting. Clear and
# descriptive docstrings will yield higher quality tool
# selection from the model.
def update_customer_loyalty_points(points_to_add: int) -> Dict[str, Any]:
"""
Adds loyalty points to the customer's profile and returns the updated profile.
Args:
points_to_add: The number of loyalty points to add to the existing total.
Returns:
A dictionary containing the customer's updated profile information.
"""
# 1. Get the current profile data from the session state.
# The .get() method safely returns an empty dict if
# 'customer_profile' doesn't exist.
current_profile_data = context.state.get("customer_profile", {})
# 2. Load the data into a Pydantic model for validation and easy access.
profile = CustomerProfile(**current_profile_data)
# 3. Perform the business logic.
# Print statements can be used for debugging and will show
# up in the tracing details.
profile.loyalty_points += points_to_add
print(f"Updated loyalty points to: {profile.loyalty_points}")
# 4. Save the updated data back into the session state.
# .model_dump() converts the Pydantic model back to a
# dictionary.
context.state["customer_profile"] = profile.model_dump()
return context.state["customer_profile"]
Solicitudes de red externas
Las herramientas de Python pueden realizar solicitudes de red externas, lo que resulta útil para recuperar datos en tiempo real o integrarse con servicios de terceros que no tienen una especificación de OpenAPI. Esto proporciona una alternativa flexible al uso de herramientas basadas en OpenAPI. En la muestra, se usa la biblioteca de solicitudes estándar (disponible en el entorno) para llamar a una API pública y recuperar un dato aleatorio.
from typing import Optional
# Docstrings in tools are important because they are directly sent to the model as the
# description for the tool. You should think of docstrings as an extension of prompting.
# Clear and descriptive docstrings will yield higher quality tool selection from the model.
def get_random_fact() -> Optional[str]:
"""
Fetches a random fact from a public API.
Returns:
A string containing the fact on success, or None if an error occurs.
"""
# The 'ces_requests' library is inspired by 'requests', a standard and powerful way in Python
# to make HTTP network calls to any external API, just like you would with `curl` or a web browser.
url = "https://uselessfacts.jsph.pl/api/v2/facts/random"
try:
# This example calls a public API that is completely open and requires no authentication
# (like an API key). Many other APIs for services like weather or e-commerce require you
# to send credentials, often as an API key in the request headers or parameters.
res = ces_requests.get(url=url, json=request_body, headers=headers)
# Example POST request
#res = ces_requests.post(url=url, json=request_body, headers=headers)
# This is a standard practice with 'ces_requests' to check if the call was successful. It will
# raise an error for statuses like 404 or 500.
res.raise_for_status()
fact_data = res.json()
return fact_data.get("text")
except:
return None