É possível fornecer código Python inline como uma ferramenta para seu agente, o que oferece flexibilidade para ampliar os recursos dele. Esse código pode aceitar entradas fornecidas pelo agente e retornar um resultado usado pelo agente na conversa. É possível implementar qualquer lógica personalizada, conectar-se a APIs ou bancos de dados proprietários e garantir resultados deterministas para tarefas que exigem precisão.
Nome e descrição
Ao criar a ferramenta, o nome dela e o nome da função principal a ser chamada precisam ser iguais em snake case.
As docstrings são uma parte essencial da definição de uma ferramenta em Python. A docstring da função é usada como descrição da ferramenta, que é fornecida aos agentes que a utilizam. Pense nas docstrings como uma extensão da solicitação. Uma docstring clara, descritiva e bem estruturada influencia diretamente a capacidade do modelo de entender o que sua ferramenta faz, quando usá-la e quais argumentos fornecer. Essa é a chave para uma seleção de ferramentas confiável e precisa.
Ambiente
No código da ferramenta Python, você tem acesso a determinadas classes e funções que ajudam a escrever o código. Para mais informações, consulte a referência do ambiente de execução do Python.
Por exemplo, o objeto context é uma variável disponível globalmente que fornece um snapshot do estado atual da conversa.
Não é necessário importar ou definir como um parâmetro. Você pode acessar diretamente.
Ele contém informações valiosas para executar lógicas complexas.
Confira abaixo um resumo das chaves disponíveis no objeto de contexto:
function_call_id: um ID exclusivo para a chamada de função específica que está sendo executada.user_content: um dicionário que contém a mensagem mais recente do usuário, incluindo o texto e a função. Esse é um dos atributos mais usados.state: um dicionário que representa o estado da sessão. Você pode usar isso para armazenar e recuperar variáveis que precisam persistir em vários turnos de uma conversa (perfil do usuário, conteúdo do carrinho de compras etc.).events: uma lista de todos os eventos no histórico de conversas até este ponto, permitindo que você crie ferramentas com uma percepção contextual mais complexa.session_id: o identificador exclusivo de toda a sessão de conversa.invocation_id: um identificador exclusivo da vez atual da conversa.agent_name: o nome do agente que está executando a ferramenta.
Ferramentas do Python chamando outras ferramentas
Ao definir ferramentas de código Python,
você pode chamar explicitamente outras ferramentas definidas no aplicativo do agente.
Por exemplo, se você tiver uma ferramenta OpenAPI chamada crm_service_get_cart_information, poderá chamar essa ferramenta com o seguinte 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({})
Amostras de código
As seções a seguir fornecem exemplos.
Receber a última entrada do usuário
Esta amostra demonstra uma capacidade fundamental: acessar a mensagem mais recente do usuário.
A ferramenta inspeciona o objeto context.user_content e extrai o texto da última vez que o usuário falou.
Esse padrão é essencial para qualquer ferramenta que precise realizar uma ação
com base diretamente no que o usuário acabou de dizer.
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
Receber e atualizar variáveis
Os modelos de linguagem não podem modificar diretamente o estado da sessão. Isso é intencional, já que garante que as mudanças de estado sejam processadas de maneira controlada e previsível. O estado só pode ser modificado por dois mecanismos: ferramentas do Python ou callbacks.
Este exemplo mostra como uma ferramenta Python pode gerenciar o estado.
Primeiro, a ferramenta lê o customer_profile atual de context.state.
Em seguida, ele executa a lógica de negócios (adicionando pontos)
e grava o perfil atualizado de volta em context.state.
Esse novo estado fica disponível para o agente e outras ferramentas durante o restante da sessão.
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"]
Solicitações de rede externa
As ferramentas do Python podem fazer solicitações de rede externa, o que é útil para buscar dados em tempo real ou integrar com serviços de terceiros que não têm uma especificação OpenAPI. Isso oferece uma alternativa flexível ao uso de ferramentas baseadas em OpenAPI. O exemplo usa a biblioteca de solicitações padrão (disponível no ambiente) para chamar uma API pública e recuperar um fato aleatório.
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