Agente de IA durável com Gemini e Temporal

Neste tutorial, você vai aprender a criar um loop de agente estilo ReAct que usa a API Gemini para raciocínio e o Temporal para durabilidade. O código-fonte completo deste tutorial está disponível no GitHub.

O agente pode chamar ferramentas, como pesquisar alertas de clima ou geolocalizar um endereço IP, e vai repetir o processo até ter informações suficientes para responder.

O que diferencia isso de uma demonstração típica de agente é a durabilidade. Cada chamada de LLM, cada invocação de ferramenta e cada etapa do loop do agente são mantidas pelo Temporal. Se o processo falhar, a rede cair ou uma API atingir o tempo limite, o Temporal vai tentar novamente e retomar automaticamente da última etapa concluída. Nenhum histórico de conversas é perdido, e nenhuma chamada de ferramenta é repetida incorretamente.

Arquitetura

A arquitetura consiste em três partes:

  • Fluxo de trabalho:o loop agêntico que orquestra a lógica de execução.
  • Atividades:unidades individuais de trabalho (chamadas de LLM, chamadas de ferramentas) que o Temporal torna duráveis.
  • Worker:o processo que executa os fluxos de trabalho e as atividades.

Neste exemplo, você vai colocar todas as três partes em um único arquivo (durable_agent_worker.py). Em uma implementação real, você as separaria para permitir várias vantagens de implantação e escalonabilidade. Você vai colocar o código que fornece um comando ao agente em um segundo arquivo (start_workflow.py).

Pré-requisitos

Para concluir este guia, você vai precisar do seguinte:

  • Uma chave da API Gemini. Você pode criar uma sem custo financeiro no Google AI Studio.
  • Python versão 3.10 ou mais recente.
  • A CLI do Temporal para executar um servidor de desenvolvimento local.

Configuração

Antes de começar, verifique se você tem um servidor de desenvolvimento do Temporal em execução localmente:

temporal server start-dev

Em seguida, instale as dependências necessárias:

pip install temporalio google-genai httpx pydantic python-dotenv

Crie um arquivo .env no diretório do projeto com sua chave de API Gemini. Você pode receber uma chave de API do Google AI Studio.

echo "GOOGLE_API_KEY=your-api-key-here" > .env

Implementação

O restante deste tutorial explica o durable_agent_worker.py de cima para baixo, criando o agente parte por parte. Crie o arquivo e acompanhe.

Importações e configuração de sandbox

Comece com as importações que precisam ser definidas antecipadamente. O bloco workflow.unsafe.imports_passed_through() instrui a sandbox de fluxo de trabalho do Temporal a permitir que determinados módulos passem sem restrições. Isso é necessário porque várias bibliotecas (principalmente httpx, que cria subclasses de urllib.request.Request) usam padrões que o sandbox bloquearia.

from temporalio import workflow

with workflow.unsafe.imports_passed_through():
    import pydantic_core  # noqa: F401
    import annotated_types  # noqa: F401

    import httpx
    from pydantic import BaseModel, Field
    from google import genai
    from google.genai import types

Instruções do sistema

Em seguida, defina a personalidade do agente. As instruções do sistema informam ao modelo como se comportar. O agente foi instruído a responder em haicais quando nenhuma ferramenta é necessária.

SYSTEM_INSTRUCTIONS = """
You are a helpful agent that can use tools to help the user.
You will be given an input from the user and a list of tools to use.
You may or may not need to use the tools to satisfy the user ask.
If no tools are needed, respond in haikus.
"""

Definições de ferramentas

Agora, defina as ferramentas que o agente pode usar. Cada ferramenta é uma função assíncrona com uma docstring descritiva. As ferramentas que usam parâmetros usam um modelo Pydantic como argumento único. Essa é uma prática recomendada do Temporal que mantém as assinaturas de atividade estáveis à medida que você adiciona campos opcionais ao longo do tempo.

import json

NWS_API_BASE = "https://api.weather.gov"
USER_AGENT = "weather-app/1.0"

class GetWeatherAlertsRequest(BaseModel):
    """Request model for getting weather alerts."""

    state: str =