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.