Desenvolvendo Agentes de IA com ADK-Go

Este artigo explora a utilização do Agent Development Kit (ADK) para a linguagem Go (adk-go) na criação de agentes de inteligência artificial. Abordaremos desde a configuração do ambinete até a implementação de diferentes tipos de agentes, incluindo a integração com ferramentas e modelos.

Ambiente de Desenvolvimento e Configuração

Para começar, adicione a dependência do ADK ao seu projeto Go:

go get google.golang.org/adk

Requisitos: Go versão 1.24.4 ou superior e o ADK v0.2. A configuração básica envolve a obtenção de uma chave de API, por exemplo, através do Google AI Studio. Atualmente, a versão Go do ADK suporta primariamente os modelos Gemini.

Implementando um Agente LLM Básico

O exemplo a seguir demonstra a criação de um agente simples que utiliza um modelo Gemini. O agente é configurado com um nome, descrição, instruções e ferramentas.

package main

import (
	"context"
	"fmt"
	"log"
	"os"
	"time"

	"google.golang.org/adk/agent"
	"google.golang.org/adk/agent/llmagent"
	"google.golang.org/adk/cmd/launcher"
	"google.golang.org/adk/cmd/launcher/full"
	"google.golang.org/adk/model/gemini"
	"google.golang.org/adk/tool"
	"google.golang.org/adk/tool/geminitool"
	"google.golang.org/genai"
)

func ExecuteAgent() {
	ctx := context.Background()
	apiKey := os.Getenv("GEMINI_API_KEY")

	llmModel, modelErr := gemini.NewModel(ctx, "gemini-2.5-pro", &genai.ClientConfig{
		APIKey: apiKey,
	})
	if modelErr != nil {
		log.Fatalf("Falha ao instanciar o modelo: %v", modelErr)
	}

	assistantAgent, agentErr := llmagent.New(llmagent.Config{
		Name:        "tempo_atual_agente",
		Model:       llmModel,
		Description: "Agente que informa a hora atual em uma cidade específica.",
		Instruction: "Você é um assistente prestativo que fornece a hora atual. Responda apenas sobre horários.",
		Tools: []tool.Tool{
			geminitool.GoogleSearch{},
		},
	})
	if agentErr != nil {
		log.Fatalf("Falha ao criar o agente: %v", agentErr)
	}

	launcherCfg := &launcher.Config{
		AgentLoader: agent.NewSingleLoader(assistantAgent),
	}

	agentLauncher := full.NewLauncher()
	if execErr := agentLauncher.Execute(ctx, launcherCfg, os.Args[1:]); execErr != nil {
		log.Fatalf("Execução falhou: %v\n\nSintaxe: %s", execErr, agentLauncher.CommandLineSyntax())
	}
}

func main() {
	ExecuteAgent()
}

Os campos Name, Model e Instruction são cruciais. As instruções devem ser claras sobre o objetivo, personalidade, restrições e uso esperado das ferramentas.

Consultando Modelos Disponíveis

A API do Gemini (pacote genai) permite listar os modelos acessíveis com sua chave de API.

func ListAvailableModels() {
	client, err := genai.NewClient(context.Background(), &genai.ClientConfig{
		APIKey: "SUA_CHAVE_API",
	})
	if err != nil {
		log.Fatalf("Falha ao criar cliente: %v", err)
	}

	for model, iterErr := range client.Models.All(context.Background()) {
		if iterErr != nil {
			log.Printf("Erro no iterador: %v\n", iterErr)
			continue
		}
		fmt.Printf("Modelo disponível: %s\n", model.Name)
	}
}

Existem limitações de uso (RPM, TPM, RPD) e custos associados a certos modelos e funcionalidades, como o Google Search.

Criando Agente com Ferramentas Personalizadas (Function Tools)

Além das ferramentas nativas do Gemini (como Google Search), é possível definir ferramentas customizadas para o agente. O exemplo abaixo combina duas feramentas: uma para obter a hora e outra para obter uma previsão do tempo (simulada).

package main

import (
	"context"
	"log"
	"os"
	"strings"
	"time"

	"google.golang.org/adk/agent"
	"google.golang.org/adk/agent/llmagent"
	"google.golang.org/adk/cmd/launcher"
	"google.golang.org/adk/cmd/launcher/full"
	"google.golang.org/adk/model/gemini"
	"google.golang.org/adk/tool"
	"google.golang.org/adk/tool/functiontool"
	"google.golang.org/genai"
)

// Estruturas de entrada e saída para as ferramentas
type CityInput struct {
	Cidade string `json:"cidade"`
}

type ToolResult struct {
	Sucesso bool   `json:"sucesso"`
	Dado    string `json:"dado"`
}

func CriarFerramentaClima() (tool.Tool, error) {
	handler := func(ctx tool.Context, input CityInput) (ToolResult, error) {
		if strings.EqualFold(input.Cidade, "são paulo") {
			return ToolResult{
				Sucesso: true,
				Dado:    "O tempo em São Paulo está ensolarado com 28°C.",
			}, nil
		}
		return ToolResult{
			Sucesso: false,
			Dado:    "Dados climáticos indisponíveis para " + input.Cidade + ".",
		}, nil
	}

	return functiontool.New(functiontool.Config{
		Name:        "ObterClima",
		Description: "Fornece uma previsão do tempo simplificada para uma cidade.",
	}, handler)
}

func CriarFerramentaHorario() (tool.Tool, error) {
	handler := func(ctx tool.Context, input CityInput) (ToolResult, error) {
		if strings.EqualFold(input.Cidade, "são paulo") {
			return ToolResult{
				Sucesso: true,
				Dado:    "A hora atual em São Paulo é: " + time.Now().Format("15:04:05"),
			}, nil
		}
		return ToolResult{
			Sucesso: false,
			Dado:    "Fuso horário não configurado para " + input.Cidade + ".",
		}, nil
	}

	return functiontool.New(functiontool.Config{
		Name:        "ObterHorario",
		Description: "Retorna a hora atual para uma cidade especificada.",
	}, handler)
}

func main() {
	ctx := context.Background()
	apiKey := os.Getenv("GEMINI_API_KEY")

	model, _ := gemini.NewModel(ctx, "gemini-2.5-flash", &genai.ClientConfig{APIKey: apiKey})
	climaTool, _ := CriarFerramentaClima()
	horarioTool, _ := CriarFerramentaHorario()

	agenteMultiTool, _ := llmagent.New(llmagent.Config{
		Name:        "assistente_multi_ferramenta",
		Model:       model,
		Description: "Agente que responde sobre clima e horário.",
		Instruction: "Use suas ferramentas para responder perguntas sobre clima e hora de uma cidade.",
		Tools:       []tool.Tool{climaTool, horarioTool},
	})

	launcherCfg := &launcher.Config{
		AgentLoader: agent.NewSingleLoader(agenteMultiTool),
	}

	l := full.NewLauncher()
	l.Execute(ctx, launcherCfg, os.Args[1:])
}

Observe que o agente decide quando invocar cada ferramenta com base nas instruções e na pergunta do usuário.

Agentes de Fluxo de Trabalho (Workflow Agents)

O ADK oferece agentes para orquestrar sub-agentes em diferentes padrões de execução.

Agente Sequencial (SequentialAgent)

Executa uma lista de sub-agentes em ordem definida. Compartilha o mesmo contexto de invocação, permitindo que a saída de um agente seja a entrada do próximo (via estado ou OutputKey). Ideal para pipelines, como: geração de código -> revisão -> refatoração.

Agente em Loop (LoopAgent)

Executa iterativamente uma série de sub-agentes. Requer um mecanismo de terminação definido (ex: max_iterations ou um sinal de conclusão de um sub-agente). Útil para tarefas iterativas como refinamento de imagem ou melhoria de documentos.

Agente Paralelo (ParallelAgent)

Executa múltiplos sub-agentes simultaneamente. Os sub-agentes operam de forma independente, sem compartilhamento automático de estado. Os resultados são coletados após a conclusão de todas as tarefas. Funciona bem para pesquisas ou processamentos paralelos.

É importante notar que a execução de fluxos de trabalho baseados em agentes envolve incertezas na interpretação e execução das tarefas semânticas.

O ADK fornece ainda a ferramenta GoogleSearch (Grounding com Google Search) para conectar o modelo a conteúdo da web em tempo real, aumentando a acurácia e fornecendo citações.

Tags: ADK-Go Agent Development Kit Gemini API LLM Agents Function Tools

Publicado em 7-11 20:26