

{"id":205378,"date":"2025-12-19T10:13:30","date_gmt":"2025-12-19T13:13:30","guid":{"rendered":"https:\/\/goias.gov.br\/ligo\/?p=205378"},"modified":"2025-12-22T11:21:40","modified_gmt":"2025-12-22T14:21:40","slug":"criando-agentes-inteligentes-com-google-adk-consumindo-modelos-llm-via-wso2","status":"publish","type":"post","link":"https:\/\/goias.gov.br\/ligo\/criando-agentes-inteligentes-com-google-adk-consumindo-modelos-llm-via-wso2\/","title":{"rendered":"Criando Agentes Inteligentes com Google ADK Consumindo Modelos LLM via WSO2"},"content":{"rendered":"<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img fetchpriority=\"high\" decoding=\"async\" width=\"960\" height=\"500\" src=\"https:\/\/goias.gov.br\/ligo\/wp-content\/uploads\/sites\/61\/2025\/12\/capatamanhocerto.jpg\" alt=\"\" class=\"wp-image-205380\" srcset=\"https:\/\/goias.gov.br\/ligo\/wp-content\/uploads\/sites\/61\/2025\/12\/capatamanhocerto.jpg 960w, https:\/\/goias.gov.br\/ligo\/wp-content\/uploads\/sites\/61\/2025\/12\/capatamanhocerto-300x156.jpg 300w, https:\/\/goias.gov.br\/ligo\/wp-content\/uploads\/sites\/61\/2025\/12\/capatamanhocerto-768x400.jpg 768w\" sizes=\"(max-width: 960px) 100vw, 960px\" \/><\/figure>\n<\/div>\n\n\n<p>Com o avan\u00e7o dos modelos de linguagem de grande porte (LLMs), cresce tamb\u00e9m a necessidade de utiliz\u00e1-los de forma <strong>segura, controlada e integrada<\/strong> aos ambientes corporativos e governamentais. Nesse cen\u00e1rio, apenas realizar chamadas diretas a um modelo de linguagem j\u00e1 n\u00e3o \u00e9 suficiente para atender requisitos como governan\u00e7a, rastreabilidade, controle de acesso e reutiliza\u00e7\u00e3o de l\u00f3gica de neg\u00f3cio.<\/p>\n\n\n\n<p>Este material apresenta, de forma gradual e pr\u00e1tica, como criar <strong>agentes inteligentes utilizando o Google ADK (Agent Development Kit)<\/strong>, consumindo modelos de linguagem disponibilizados por meio do <strong>WSO2<\/strong>, plataforma amplamente adotada para gerenciamento e exposi\u00e7\u00e3o de APIs no Estado de Goi\u00e1s. A proposta \u00e9 mostrar como sair de um uso simples de LLMs e evoluir para agentes capazes de tomar decis\u00f5es, utilizar ferramentas e interagir com sistemas externos de maneira estruturada.<\/p>\n\n\n\n<p>Ao longo do passo a passo, ser\u00e3o abordados conceitos fundamentais, arquitetura da solu\u00e7\u00e3o e exemplos pr\u00e1ticos de c\u00f3digo, sempre com foco em um cen\u00e1rio real: modelos de linguagem protegidos por um gateway corporativo, com autentica\u00e7\u00e3o, seguran\u00e7a e pol\u00edticas de uso. O objetivo \u00e9 fornecer uma base s\u00f3lida para desenvolvedores que desejam criar agentes mais robustos, previs\u00edveis e alinhados \u00e0s necessidades de ambientes institucionais.<\/p>\n\n\n\n<p>Antes de avan\u00e7ar para a parte pr\u00e1tica, \u00e9 importante estabelecer alguns <strong>conceitos fundamentais<\/strong> que servem de base para todo o restante do material. Termos como <em>LLM<\/em>, <em>agente<\/em>, <em>Google ADK<\/em> e <em>WSO2<\/em> aparecem com frequ\u00eancia ao longo do texto e, embora estejam relacionados, representam pap\u00e9is distintos dentro da arquitetura proposta.<\/p>\n\n\n\n<p>Nesta se\u00e7\u00e3o, ser\u00e1 apresentada uma vis\u00e3o geral sobre a diferen\u00e7a entre o uso de um modelo de linguagem simples e a constru\u00e7\u00e3o de um agente, al\u00e9m de uma explica\u00e7\u00e3o objetiva sobre o que \u00e9 o Google ADK e como o WSO2 se encaixa nesse contexto. O objetivo \u00e9 garantir um entendimento comum antes de partir para a implementa\u00e7\u00e3o pr\u00e1tica dos agentes.<\/p>\n\n\n\n<h2 class=\"wp-block-heading has-medium-font-size\"><strong>Diferen\u00e7a entre um LLM simples e um agente<\/strong><\/h2>\n\n\n\n<p>Um <strong>LLM simples<\/strong> \u00e9, basicamente, uma chamada direta a um modelo de linguagem:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Voc\u00ea envia um prompt<\/li>\n\n\n\n<li>O modelo gera uma resposta<\/li>\n\n\n\n<li>A intera\u00e7\u00e3o termina ali<\/li>\n<\/ul>\n\n\n\n<p>Esse modelo funciona bem para tarefas isoladas, como responder perguntas, resumir textos ou gerar conte\u00fado, mas ele <strong>n\u00e3o possui consci\u00eancia de contexto, objetivo ou capacidade de a\u00e7\u00e3o estruturada<\/strong>.<\/p>\n\n\n\n<p>J\u00e1 um <strong>agente<\/strong> \u00e9 uma entidade que utiliza um LLM como parte do seu funcionamento, mas vai al\u00e9m:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ele possui <strong>instru\u00e7\u00f5es claras de comportamento<\/strong><\/li>\n\n\n\n<li>Pode <strong>decidir quando usar ferramentas externas<\/strong><\/li>\n\n\n\n<li>Pode executar m\u00faltiplos passos para chegar a uma resposta<\/li>\n\n\n\n<li>Mant\u00e9m um fluxo l\u00f3gico mais controlado<\/li>\n<\/ul>\n\n\n\n<p>Em outras palavras:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>LLM<\/strong> \u2192 responde<\/li>\n\n\n\n<li><strong>Agente<\/strong> \u2192 analisa, decide, age e responde<\/li>\n<\/ul>\n\n\n\n<p>O Google ADK permite justamente essa evolu\u00e7\u00e3o: sair de chamadas simples a modelos e criar agentes que operam de forma mais pr\u00f3xima a um assistente inteligente real, especialmente quando integrados a APIs corporativas, sistemas internos e modelos protegidos por plataformas como o WSO2.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"alignright size-large is-resized\"><img decoding=\"async\" width=\"1024\" height=\"452\" src=\"https:\/\/goias.gov.br\/ligo\/wp-content\/uploads\/sites\/61\/2025\/12\/adk-1024x452.png\" alt=\"\" class=\"wp-image-205381\" style=\"width:255px;height:auto\" srcset=\"https:\/\/goias.gov.br\/ligo\/wp-content\/uploads\/sites\/61\/2025\/12\/adk-1024x452.png 1024w, https:\/\/goias.gov.br\/ligo\/wp-content\/uploads\/sites\/61\/2025\/12\/adk-300x133.png 300w, https:\/\/goias.gov.br\/ligo\/wp-content\/uploads\/sites\/61\/2025\/12\/adk-768x339.png 768w, https:\/\/goias.gov.br\/ligo\/wp-content\/uploads\/sites\/61\/2025\/12\/adk.png 1177w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n<\/div>\n\n\n<h2 class=\"wp-block-heading has-medium-font-size\"><strong>O que \u00e9 o Google ADK (Agent Development Kit)<\/strong><\/h2>\n\n\n\n<p>O <strong>Google ADK (Agent Development Kit)<\/strong> \u00e9 um framework criado para facilitar o desenvolvimento de <strong>agentes inteligentes<\/strong>, ou seja, aplica\u00e7\u00f5es baseadas em modelos de linguagem que n\u00e3o apenas respondem perguntas, mas <strong>tomam decis\u00f5es<\/strong>, <strong>utilizam ferramentas<\/strong>, <strong>executam a\u00e7\u00f5es<\/strong> e <strong>seguem regras de comportamento<\/strong>.<\/p>\n\n\n\n<p>Diferente de uma simples chamada a um modelo de linguagem, o ADK fornece uma estrutura para:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Definir <strong>instru\u00e7\u00f5es e objetivos<\/strong> do agente<\/li>\n\n\n\n<li>Controlar <strong>quando e como ferramentas externas s\u00e3o utilizadas<\/strong><\/li>\n\n\n\n<li>Organizar o fluxo de execu\u00e7\u00e3o do agente<\/li>\n\n\n\n<li>Evitar que toda a l\u00f3gica fique concentrada apenas em prompts<\/li>\n<\/ul>\n\n\n\n<p>Na pr\u00e1tica, o ADK funciona como uma \u201ccamada de orquestra\u00e7\u00e3o\u201d sobre um modelo de linguagem. Ele n\u00e3o substitui o LLM, mas define <strong>como o LLM deve se comportar dentro de um contexto mais amplo<\/strong>, permitindo a cria\u00e7\u00e3o de agentes mais previs\u00edveis, reutiliz\u00e1veis e control\u00e1veis.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"alignright size-full is-resized\"><img decoding=\"async\" width=\"607\" height=\"235\" src=\"https:\/\/goias.gov.br\/ligo\/wp-content\/uploads\/sites\/61\/2025\/12\/wso2.png\" alt=\"\" class=\"wp-image-205382\" style=\"width:265px;height:auto\" srcset=\"https:\/\/goias.gov.br\/ligo\/wp-content\/uploads\/sites\/61\/2025\/12\/wso2.png 607w, https:\/\/goias.gov.br\/ligo\/wp-content\/uploads\/sites\/61\/2025\/12\/wso2-300x116.png 300w\" sizes=\"(max-width: 607px) 100vw, 607px\" \/><\/figure>\n<\/div>\n\n\n<h2 class=\"wp-block-heading has-medium-font-size\"><strong>O que \u00e9 o WSO2<\/strong><\/h2>\n\n\n\n<p>O <strong>WSO2<\/strong> \u00e9 uma plataforma de <strong>gerenciamento de APIs e integra\u00e7\u00e3o<\/strong>, muito utilizada em ambientes corporativos e governamentais por oferecer controle, seguran\u00e7a e governan\u00e7a no consumo de servi\u00e7os.<\/p>\n\n\n\n<p>No contexto de modelos de linguagem, o WSO2 atua como um <strong>gateway<\/strong> entre as aplica\u00e7\u00f5es consumidoras (como agentes criados com o Google ADK) e os modelos LLM propriamente ditos. Isso significa que:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>O acesso aos modelos \u00e9 feito via <strong>APIs padronizadas<\/strong><\/li>\n\n\n\n<li>Existe <strong>controle de autentica\u00e7\u00e3o e autoriza\u00e7\u00e3o<\/strong>, geralmente via OAuth2<\/li>\n\n\n\n<li>\u00c9 poss\u00edvel aplicar <strong>pol\u00edticas de seguran\u00e7a<\/strong>, limites de uso e auditoria<\/li>\n\n\n\n<li>Os modelos n\u00e3o ficam expostos diretamente \u00e0 internet<\/li>\n<\/ul>\n\n\n\n<p>Em ambientes como o do Estado de Goi\u00e1s, essa abordagem \u00e9 fundamental para garantir que o uso de modelos de IA siga requisitos de seguran\u00e7a, conformidade e rastreabilidade.<\/p>\n\n\n\n<h2 class=\"wp-block-heading has-text-align-left has-large-font-size\"><strong>Hora de por a m\u00e3o na massa.<\/strong><\/h2>\n\n\n\n<p class=\"has-medium-font-size\"><strong>Pr\u00e9-requisitos<\/strong><\/p>\n\n\n\n<p>Lista clara para evitar frustra\u00e7\u00e3o:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Python 3.10+<\/li>\n\n\n\n<li>pip<\/li>\n\n\n\n<li>Acesso ao endpoint do modelo no WSO2<\/li>\n\n\n\n<li>Client ID \/ Client Secret (OAuth2)<\/li>\n\n\n\n<li>Ambiente virtual (opcional, mas recomendado)<\/li>\n<\/ul>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#f6f6f4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>python -m venv .venv&lt;br>\nsource .venv\/bin\/activate  # linux\/mac\n.venv\\Scripts\\activate     # windows<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula-soft\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #62E884\">python<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #BF9EEE\">-m<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">venv<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">.venv<\/span><span style=\"color: #F286C4\">&lt;<\/span><span style=\"color: #E7EE98\">b<\/span><span style=\"color: #F6F6F4\">r<\/span><span style=\"color: #F286C4\">&gt;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #97E1F1\">source<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">.venv\/bin\/activate<\/span><span style=\"color: #F6F6F4\">  <\/span><span style=\"color: #7B7F8B\"># linux\/mac<\/span><\/span>\n<span class=\"line\"><span style=\"color: #62E884\">.venv\\Scripts\\activate<\/span><span style=\"color: #F6F6F4\">     <\/span><span style=\"color: #7B7F8B\"># windows<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"has-medium-font-size\"><strong>Instala\u00e7\u00e3o do Google ADK<\/strong><\/p>\n\n\n\n<p>Explicar de forma direta:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#f6f6f4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>pip install google-adk litellm<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula-soft\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #62E884\">pip<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">install<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">google-adk<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">litellm<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Com o ambiente configurado e o Google ADK instalado, \u00e9 importante compreender <strong>como os diferentes componentes dessa solu\u00e7\u00e3o se conectam<\/strong>. Antes de partir para a implementa\u00e7\u00e3o do agente, vale visualizar a arquitetura geral envolvida na comunica\u00e7\u00e3o entre o usu\u00e1rio, o agente, a plataforma de gerenciamento de APIs e o modelo de linguagem.<\/p>\n\n\n\n<p>O diagrama a seguir ilustra, de forma simplificada, o fluxo de intera\u00e7\u00e3o desde a solicita\u00e7\u00e3o do usu\u00e1rio at\u00e9 a chamada ao modelo LLM, evidenciando o papel de cada camada \u2014 do agente criado com o Google ADK at\u00e9 o acesso ao modelo por meio do WSO2.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"683\" src=\"https:\/\/goias.gov.br\/ligo\/wp-content\/uploads\/sites\/61\/2025\/12\/diagrama-1024x683.jpg\" alt=\"\" class=\"wp-image-205384\" srcset=\"https:\/\/goias.gov.br\/ligo\/wp-content\/uploads\/sites\/61\/2025\/12\/diagrama-1024x683.jpg 1024w, https:\/\/goias.gov.br\/ligo\/wp-content\/uploads\/sites\/61\/2025\/12\/diagrama-300x200.jpg 300w, https:\/\/goias.gov.br\/ligo\/wp-content\/uploads\/sites\/61\/2025\/12\/diagrama-768x512.jpg 768w, https:\/\/goias.gov.br\/ligo\/wp-content\/uploads\/sites\/61\/2025\/12\/diagrama.jpg 1536w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Para iniciar, s\u00e3o importadas as bibliotecas necess\u00e1rias para o funcionamento do agente e para a comunica\u00e7\u00e3o com o WSO2, al\u00e9m da defini\u00e7\u00e3o de algumas vari\u00e1veis essenciais para o processo de autentica\u00e7\u00e3o. Esse conjunto inclui tanto componentes do Google ADK quanto bibliotecas auxiliares para requisi\u00e7\u00f5es HTTP e manipula\u00e7\u00e3o de dados.<\/p>\n\n\n\n<p>\u00c9 importante destacar que, neste exemplo, a defini\u00e7\u00e3o das credenciais e vari\u00e1veis de configura\u00e7\u00e3o \u00e9 feita de forma <strong>simplificada<\/strong>, com o objetivo exclusivo de facilitar o entendimento do fluxo apresentado. <strong>Boas pr\u00e1ticas e protocolos de seguran\u00e7a n\u00e3o foram aplicados neste trecho<\/strong>, devendo ser obrigatoriamente adotados em cen\u00e1rios reais, conforme as diretrizes e pol\u00edticas de cada \u00f3rg\u00e3o ou institui\u00e7\u00e3o.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#f6f6f4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>from google.adk.agents import Agent\nfrom google.adk.models.lite_llm import LiteLlm \nfrom google.adk.models.llm_request import LlmRequest\nfrom google.adk.models.llm_response import LlmResponse\nimport requests\nimport base64\nfrom datetime import datetime, timedelta\nfrom typing import AsyncGenerator\nimport httpx\nimport litellm\nfrom typing import AsyncGenerator\n\nconsumer_key=''\nconsumer_secret=''\nurl_token='https:\/\/endere\u00e7o_do_wso2\/token'\nwso2_endpoint = \"https:\/\/endpoint_da_api\/v1\"<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula-soft\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F286C4\">from<\/span><span style=\"color: #F6F6F4\"> google.adk.agents <\/span><span style=\"color: #F286C4\">import<\/span><span style=\"color: #F6F6F4\"> Agent<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F286C4\">from<\/span><span style=\"color: #F6F6F4\"> google.adk.models.lite_llm <\/span><span style=\"color: #F286C4\">import<\/span><span style=\"color: #F6F6F4\"> LiteLlm <\/span><\/span>\n<span class=\"line\"><span style=\"color: #F286C4\">from<\/span><span style=\"color: #F6F6F4\"> google.adk.models.llm_request <\/span><span style=\"color: #F286C4\">import<\/span><span style=\"color: #F6F6F4\"> LlmRequest<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F286C4\">from<\/span><span style=\"color: #F6F6F4\"> google.adk.models.llm_response <\/span><span style=\"color: #F286C4\">import<\/span><span style=\"color: #F6F6F4\"> LlmResponse<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F286C4\">import<\/span><span style=\"color: #F6F6F4\"> requests<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F286C4\">import<\/span><span style=\"color: #F6F6F4\"> base64<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F286C4\">from<\/span><span style=\"color: #F6F6F4\"> datetime <\/span><span style=\"color: #F286C4\">import<\/span><span style=\"color: #F6F6F4\"> datetime, timedelta<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F286C4\">from<\/span><span style=\"color: #F6F6F4\"> typing <\/span><span style=\"color: #F286C4\">import<\/span><span style=\"color: #F6F6F4\"> AsyncGenerator<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F286C4\">import<\/span><span style=\"color: #F6F6F4\"> httpx<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F286C4\">import<\/span><span style=\"color: #F6F6F4\"> litellm<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F286C4\">from<\/span><span style=\"color: #F6F6F4\"> typing <\/span><span style=\"color: #F286C4\">import<\/span><span style=\"color: #F6F6F4\"> AsyncGenerator<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">consumer_key<\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #DEE492\">&#39;&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">consumer_secret<\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #DEE492\">&#39;&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">url_token<\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #DEE492\">&#39;<\/span><span style=\"color: #E7EE98\">https:\/\/endere\u00e7o_do_wso2\/token<\/span><span style=\"color: #DEE492\">&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">wso2_endpoint <\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">https:\/\/endpoint_da_api\/v1<\/span><span style=\"color: #DEE492\">&quot;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading has-large-font-size\">Gera\u00e7\u00e3o de token de acesso (OAuth2)<\/h2>\n\n\n\n<p>No contexto de consumo de modelos de linguagem expostos por meio do WSO2, \u00e9 necess\u00e1rio realizar a <strong>autentica\u00e7\u00e3o via OAuth2<\/strong> para obter um token de acesso v\u00e1lido. Esse token ser\u00e1 utilizado nas requisi\u00e7\u00f5es subsequentes ao endpoint do modelo.<\/p>\n\n\n\n<p>O trecho de c\u00f3digo abaixo apresenta uma <strong>implementa\u00e7\u00e3o b\u00e1sica e simplificada<\/strong> de gera\u00e7\u00e3o de token utilizando o fluxo <em>client credentials<\/em>. O objetivo \u00e9 <strong>apenas exemplificar o processo<\/strong>, facilitando o entendimento do fluxo de autentica\u00e7\u00e3o, e <strong>n\u00e3o deve ser encarado como uma implementa\u00e7\u00e3o definitiva para ambientes produtivos<\/strong>.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#f6f6f4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>def gera_token(Consumer_Key=consumer_key,\n               Consumer_Secret=consumer_secret,\n               url=url_token):\n    basic = f'{Consumer_Key}:{Consumer_Secret}'\n    basic_bytes = basic.encode('ascii')\n    base64_bytes = base64.b64encode(basic_bytes)\n    base64_basic = base64_bytes.decode('ascii')\n    data = {'grant_type':'client_credentials'}\n    headers = {\"Authorization\": \"Basic {}\".format(base64_basic)}\n    token = requests.post(url=url, data=data, headers=headers).json()\n    return token&#91;'access_token'&#93;\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula-soft\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F286C4\">def<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #62E884\">gera_token<\/span><span style=\"color: #F6F6F4\">(<\/span><span style=\"color: #FFB86C; font-style: italic\">Consumer_Key<\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\">consumer_key,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">               <\/span><span style=\"color: #FFB86C; font-style: italic\">Consumer_Secret<\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\">consumer_secret,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">               <\/span><span style=\"color: #FFB86C; font-style: italic\">url<\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\">url_token):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    basic <\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #F286C4\">f<\/span><span style=\"color: #E7EE98\">&#39;<\/span><span style=\"color: #BF9EEE\">{<\/span><span style=\"color: #F6F6F4\">Consumer_Key<\/span><span style=\"color: #BF9EEE\">}<\/span><span style=\"color: #E7EE98\">:<\/span><span style=\"color: #BF9EEE\">{<\/span><span style=\"color: #F6F6F4\">Consumer_Secret<\/span><span style=\"color: #BF9EEE\">}<\/span><span style=\"color: #E7EE98\">&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    basic_bytes <\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\"> basic.encode(<\/span><span style=\"color: #DEE492\">&#39;<\/span><span style=\"color: #E7EE98\">ascii<\/span><span style=\"color: #DEE492\">&#39;<\/span><span style=\"color: #F6F6F4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    base64_bytes <\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\"> base64.b64encode(basic_bytes)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    base64_basic <\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\"> base64_bytes.decode(<\/span><span style=\"color: #DEE492\">&#39;<\/span><span style=\"color: #E7EE98\">ascii<\/span><span style=\"color: #DEE492\">&#39;<\/span><span style=\"color: #F6F6F4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    data <\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\"> {<\/span><span style=\"color: #DEE492\">&#39;<\/span><span style=\"color: #E7EE98\">grant_type<\/span><span style=\"color: #DEE492\">&#39;<\/span><span style=\"color: #F6F6F4\">:<\/span><span style=\"color: #DEE492\">&#39;<\/span><span style=\"color: #E7EE98\">client_credentials<\/span><span style=\"color: #DEE492\">&#39;<\/span><span style=\"color: #F6F6F4\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    headers <\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\"> {<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">Authorization<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">: <\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">Basic <\/span><span style=\"color: #BF9EEE\">{}<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">.format(base64_basic)}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    token <\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\"> requests.post(<\/span><span style=\"color: #FFB86C; font-style: italic\">url<\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\">url, <\/span><span style=\"color: #FFB86C; font-style: italic\">data<\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\">data, <\/span><span style=\"color: #FFB86C; font-style: italic\">headers<\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\">headers).json()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    <\/span><span style=\"color: #F286C4\">return<\/span><span style=\"color: #F6F6F4\"> token&#91;<\/span><span style=\"color: #DEE492\">&#39;<\/span><span style=\"color: #E7EE98\">access_token<\/span><span style=\"color: #DEE492\">&#39;<\/span><span style=\"color: #F6F6F4\">&#93;<\/span><\/span>\n<span class=\"line\"><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Nesta fun\u00e7\u00e3o, as credenciais (<code>consumer_key<\/code> e <code>consumer_secret<\/code>) s\u00e3o combinadas e codificadas em Base64 para compor o header de autentica\u00e7\u00e3o do tipo <em>Basic Authentication<\/em>. Em seguida, \u00e9 realizada uma requisi\u00e7\u00e3o HTTP ao endpoint de token do WSO2, que retorna um <em>access token<\/em> utilizado para autorizar chamadas \u00e0s APIs protegidas.<\/p>\n\n\n\n<p>\u00c9 importante destacar que:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Esta fun\u00e7\u00e3o <strong>n\u00e3o implementa cache de token<\/strong>, renova\u00e7\u00e3o autom\u00e1tica ou tratamento de erros.<\/li>\n\n\n\n<li>As credenciais est\u00e3o representadas de forma direta apenas para fins did\u00e1ticos.<\/li>\n\n\n\n<li>Cada \u00f3rg\u00e3o ou institui\u00e7\u00e3o pode (e normalmente deve) adotar <strong>pol\u00edticas pr\u00f3prias de seguran\u00e7a<\/strong>, como:\n<ul class=\"wp-block-list\">\n<li>Uso de cofres de segredo (Secret Manager, Vault, etc.)<\/li>\n\n\n\n<li>Rota\u00e7\u00e3o de credenciais<\/li>\n\n\n\n<li>Controle de escopo (<em>scopes<\/em>)<\/li>\n\n\n\n<li>Logs e auditoria de acesso<\/li>\n\n\n\n<li>Tratamento adequado de exce\u00e7\u00f5es e falhas de autentica\u00e7\u00e3o<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p>Portanto, antes de utilizar qualquer l\u00f3gica semelhante em produ\u00e7\u00e3o, \u00e9 fundamental alinhar a implementa\u00e7\u00e3o aos <strong>protocolos de seguran\u00e7a, governan\u00e7a e conformidade definidos pela organiza\u00e7\u00e3o<\/strong>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading has-large-font-size\"><strong>Criando as Ferramentas do agente<\/strong><\/h2>\n\n\n\n<p>Para demonstrar o funcionamento de agentes no Google ADK, foram criadas algumas <strong>ferramentas de exemplo<\/strong> que simulam a obten\u00e7\u00e3o de informa\u00e7\u00f5es sobre cidades. Essas ferramentas t\u00eam como objetivo ilustrar <strong>como um agente pode decidir quando utilizar uma fun\u00e7\u00e3o externa<\/strong> para complementar sua resposta, sem a necessidade de integra\u00e7\u00e3o com servi\u00e7os reais neste momento.<\/p>\n\n\n\n<p>As fun\u00e7\u00f5es apresentadas retornam dados <strong>simulados<\/strong>, como hor\u00e1rio local, \u00e1rea territorial e coordenadas geogr\u00e1ficas, permitindo focar no comportamento do agente, na estrutura das ferramentas e na forma como o ADK orquestra as chamadas, sem adicionar complexidade externa ao exemplo.<\/p>\n\n\n\n<p>Cada ferramenta segue um padr\u00e3o simples:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Recebe um par\u00e2metro de entrada (<code>city<\/code>)<\/li>\n\n\n\n<li>Executa uma l\u00f3gica interna simulada<\/li>\n\n\n\n<li>Retorna um dicion\u00e1rio contendo uma resposta textual, que poder\u00e1 ser utilizada diretamente pelo agente<\/li>\n<\/ul>\n\n\n\n<p>Esse tipo de abordagem \u00e9 especialmente \u00fatil em fases iniciais de desenvolvimento, testes ou aprendizado, antes de substituir as fun\u00e7\u00f5es simuladas por integra\u00e7\u00f5es reais com APIs corporativas, bases de dados ou servi\u00e7os internos, respeitando sempre os protocolos e pol\u00edticas de seguran\u00e7a de cada institui\u00e7\u00e3o.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#f6f6f4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>def get_horas(city: str) -> dict:\n    \"\"\"\n    Ferramenta: Obter hor\u00e1rio atual em uma cidade.\n   \n    Descri\u00e7\u00e3o:\n    Retorna o hor\u00e1rio atual aproximado em uma cidade espec\u00edfica, com base em fusos hor\u00e1rios simulados.\n   \n    Par\u00e2metros:\n    - city (str): Nome da cidade desejada.\n   \n    Retorna:\n    - Um dicion\u00e1rio contendo:\n        - o nome da cidade,\n        - o hor\u00e1rio atual no formato HH:MM,\n        - uma descri\u00e7\u00e3o textual.\n    \"\"\"\n    # Simula\u00e7\u00e3o de fusos hor\u00e1rios relativos a UTC\n    fuso_simulado = {\n        \"S\u00e3o Paulo\": -3,\n        \"Rio de Janeiro\": -3,\n        \"Bras\u00edlia\": -3,\n        \"Lisboa\": 0,\n        \"Nova York\": -4,\n        \"T\u00f3quio\": 9,\n        \"Londres\": 1\n    }\n \n    utc_now = datetime.utcnow()\n    offset = fuso_simulado.get(city, 0)\n    local_time = utc_now + timedelta(hours=offset)\n    formatted_time = local_time.strftime(\"%H:%M\")\n    return {\"text\": f\"O hor\u00e1rio atual em {city} \u00e9 aproximadamente {formatted_time}.\"}\n \n \ndef get_tamanho_cidade(city: str) -> dict:\n    \"\"\"\n    Ferramenta: Obter \u00e1rea territorial de uma cidade.\n   \n    Descri\u00e7\u00e3o:\n    Retorna a \u00e1rea aproximada de uma cidade, em quil\u00f4metros quadrados.\n   \n    Par\u00e2metros:\n    - city (str): Nome da cidade desejada.\n   \n    Retorna:\n    - Um dicion\u00e1rio contendo o nome da cidade, sua \u00e1rea em km\u00b2 e uma descri\u00e7\u00e3o textual.\n    \"\"\"\n    # Dados simulados para algumas cidades\n    tamanhos_simulados = {\n        \"S\u00e3o Paulo\": 1521.11,\n        \"Rio de Janeiro\": 1182.3,\n        \"Bras\u00edlia\": 5802.0,\n        \"Salvador\": 693.8,\n    }\n    area = tamanhos_simulados.get(city, 1000.0)\n    return {\"text\": f\"A cidade de {city} possui uma \u00e1rea aproximada de {area:.2f} km\u00b2.\"}\n \n \ndef get_latitude_longitude(city: str) -> dict:\n    \"\"\"\n    Ferramenta: Obter coordenadas geogr\u00e1ficas.\n \n    Descri\u00e7\u00e3o: Retorna a latitude e longitude aproximadas da cidade informada.\n   \n    Par\u00e2metros:\n    - city (str): Nome da cidade desejada.\n   \n    Retorna:\n    - Um dicion\u00e1rio contendo a cidade, latitude e longitude.\n    \"\"\"\n    # Dados simulados para exemplo\n    coordenadas_simuladas = {\n        \"S\u00e3o Paulo\": ( -23.55052, -46.63331),\n        \"Rio de Janeiro\": (-22.90685, -43.1729),\n        \"Bras\u00edlia\": (-15.79389, -47.88278),\n        \"Salvador\": (-12.97139, -38.50139),\n    }\n    coords = coordenadas_simuladas.get(city, (14.123114, 16.12312))\n    return {\"text\": \"As coordenadas da cidade \"+city+\" \u00e9 latitude \"+str(coords&#91;0&#93;)+\" e longitude \"+str(coords&#91;1&#93;)}\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula-soft\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F286C4\">def<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #62E884\">get_horas<\/span><span style=\"color: #F6F6F4\">(<\/span><span style=\"color: #FFB86C; font-style: italic\">city<\/span><span style=\"color: #F286C4\">:<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #97E1F1; font-style: italic\">str<\/span><span style=\"color: #F6F6F4\">) <\/span><span style=\"color: #F286C4\">-&gt;<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #97E1F1; font-style: italic\">dict<\/span><span style=\"color: #F6F6F4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    <\/span><span style=\"color: #7B7F8B\">&quot;&quot;&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">    Ferramenta: Obter hor\u00e1rio atual em uma cidade.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">   <\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">    Descri\u00e7\u00e3o:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">    Retorna o hor\u00e1rio atual aproximado em uma cidade espec\u00edfica, com base em fusos hor\u00e1rios simulados.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">   <\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">    Par\u00e2metros:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">    - city (str): Nome da cidade desejada.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">   <\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">    Retorna:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">    - Um dicion\u00e1rio contendo:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">        - o nome da cidade,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">        - o hor\u00e1rio atual no formato HH:MM,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">        - uma descri\u00e7\u00e3o textual.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">    &quot;&quot;&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    <\/span><span style=\"color: #7B7F8B\"># Simula\u00e7\u00e3o de fusos hor\u00e1rios relativos a UTC<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    fuso_simulado <\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">        <\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">S\u00e3o Paulo<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">: <\/span><span style=\"color: #F286C4\">-<\/span><span style=\"color: #BF9EEE\">3<\/span><span style=\"color: #F6F6F4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">        <\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">Rio de Janeiro<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">: <\/span><span style=\"color: #F286C4\">-<\/span><span style=\"color: #BF9EEE\">3<\/span><span style=\"color: #F6F6F4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">        <\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">Bras\u00edlia<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">: <\/span><span style=\"color: #F286C4\">-<\/span><span style=\"color: #BF9EEE\">3<\/span><span style=\"color: #F6F6F4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">        <\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">Lisboa<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">: <\/span><span style=\"color: #BF9EEE\">0<\/span><span style=\"color: #F6F6F4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">        <\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">Nova York<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">: <\/span><span style=\"color: #F286C4\">-<\/span><span style=\"color: #BF9EEE\">4<\/span><span style=\"color: #F6F6F4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">        <\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">T\u00f3quio<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">: <\/span><span style=\"color: #BF9EEE\">9<\/span><span style=\"color: #F6F6F4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">        <\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">Londres<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">: <\/span><span style=\"color: #BF9EEE\">1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\"> <\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    utc_now <\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\"> datetime.utcnow()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    offset <\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\"> fuso_simulado.get(city, <\/span><span style=\"color: #BF9EEE\">0<\/span><span style=\"color: #F6F6F4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    local_time <\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\"> utc_now <\/span><span style=\"color: #F286C4\">+<\/span><span style=\"color: #F6F6F4\"> timedelta(<\/span><span style=\"color: #FFB86C; font-style: italic\">hours<\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\">offset)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    formatted_time <\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\"> local_time.strftime(<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">%H:%M<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    <\/span><span style=\"color: #F286C4\">return<\/span><span style=\"color: #F6F6F4\"> {<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">text<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">: <\/span><span style=\"color: #F286C4\">f<\/span><span style=\"color: #E7EE98\">&quot;O hor\u00e1rio atual em <\/span><span style=\"color: #BF9EEE\">{<\/span><span style=\"color: #F6F6F4\">city<\/span><span style=\"color: #BF9EEE\">}<\/span><span style=\"color: #E7EE98\"> \u00e9 aproximadamente <\/span><span style=\"color: #BF9EEE\">{<\/span><span style=\"color: #F6F6F4\">formatted_time<\/span><span style=\"color: #BF9EEE\">}<\/span><span style=\"color: #E7EE98\">.&quot;<\/span><span style=\"color: #F6F6F4\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\"> <\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\"> <\/span><\/span>\n<span class=\"line\"><span style=\"color: #F286C4\">def<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #62E884\">get_tamanho_cidade<\/span><span style=\"color: #F6F6F4\">(<\/span><span style=\"color: #FFB86C; font-style: italic\">city<\/span><span style=\"color: #F286C4\">:<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #97E1F1; font-style: italic\">str<\/span><span style=\"color: #F6F6F4\">) <\/span><span style=\"color: #F286C4\">-&gt;<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #97E1F1; font-style: italic\">dict<\/span><span style=\"color: #F6F6F4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    <\/span><span style=\"color: #7B7F8B\">&quot;&quot;&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">    Ferramenta: Obter \u00e1rea territorial de uma cidade.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">   <\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">    Descri\u00e7\u00e3o:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">    Retorna a \u00e1rea aproximada de uma cidade, em quil\u00f4metros quadrados.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">   <\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">    Par\u00e2metros:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">    - city (str): Nome da cidade desejada.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">   <\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">    Retorna:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">    - Um dicion\u00e1rio contendo o nome da cidade, sua \u00e1rea em km\u00b2 e uma descri\u00e7\u00e3o textual.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">    &quot;&quot;&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    <\/span><span style=\"color: #7B7F8B\"># Dados simulados para algumas cidades<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    tamanhos_simulados <\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">        <\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">S\u00e3o Paulo<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">: <\/span><span style=\"color: #BF9EEE\">1521.11<\/span><span style=\"color: #F6F6F4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">        <\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">Rio de Janeiro<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">: <\/span><span style=\"color: #BF9EEE\">1182.3<\/span><span style=\"color: #F6F6F4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">        <\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">Bras\u00edlia<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">: <\/span><span style=\"color: #BF9EEE\">5802.0<\/span><span style=\"color: #F6F6F4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">        <\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">Salvador<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">: <\/span><span style=\"color: #BF9EEE\">693.8<\/span><span style=\"color: #F6F6F4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    area <\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\"> tamanhos_simulados.get(city, <\/span><span style=\"color: #BF9EEE\">1000.0<\/span><span style=\"color: #F6F6F4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    <\/span><span style=\"color: #F286C4\">return<\/span><span style=\"color: #F6F6F4\"> {<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">text<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">: <\/span><span style=\"color: #F286C4\">f<\/span><span style=\"color: #E7EE98\">&quot;A cidade de <\/span><span style=\"color: #BF9EEE\">{<\/span><span style=\"color: #F6F6F4\">city<\/span><span style=\"color: #BF9EEE\">}<\/span><span style=\"color: #E7EE98\"> possui uma \u00e1rea aproximada de <\/span><span style=\"color: #BF9EEE\">{<\/span><span style=\"color: #F6F6F4\">area<\/span><span style=\"color: #F286C4\">:.2f<\/span><span style=\"color: #BF9EEE\">}<\/span><span style=\"color: #E7EE98\"> km\u00b2.&quot;<\/span><span style=\"color: #F6F6F4\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\"> <\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\"> <\/span><\/span>\n<span class=\"line\"><span style=\"color: #F286C4\">def<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #62E884\">get_latitude_longitude<\/span><span style=\"color: #F6F6F4\">(<\/span><span style=\"color: #FFB86C; font-style: italic\">city<\/span><span style=\"color: #F286C4\">:<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #97E1F1; font-style: italic\">str<\/span><span style=\"color: #F6F6F4\">) <\/span><span style=\"color: #F286C4\">-&gt;<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #97E1F1; font-style: italic\">dict<\/span><span style=\"color: #F6F6F4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    <\/span><span style=\"color: #7B7F8B\">&quot;&quot;&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">    Ferramenta: Obter coordenadas geogr\u00e1ficas.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\"> <\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">    Descri\u00e7\u00e3o: Retorna a latitude e longitude aproximadas da cidade informada.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">   <\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">    Par\u00e2metros:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">    - city (str): Nome da cidade desejada.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">   <\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">    Retorna:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">    - Um dicion\u00e1rio contendo a cidade, latitude e longitude.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #7B7F8B\">    &quot;&quot;&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    <\/span><span style=\"color: #7B7F8B\"># Dados simulados para exemplo<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    coordenadas_simuladas <\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">        <\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">S\u00e3o Paulo<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">: ( <\/span><span style=\"color: #F286C4\">-<\/span><span style=\"color: #BF9EEE\">23.55052<\/span><span style=\"color: #F6F6F4\">, <\/span><span style=\"color: #F286C4\">-<\/span><span style=\"color: #BF9EEE\">46.63331<\/span><span style=\"color: #F6F6F4\">),<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">        <\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">Rio de Janeiro<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">: (<\/span><span style=\"color: #F286C4\">-<\/span><span style=\"color: #BF9EEE\">22.90685<\/span><span style=\"color: #F6F6F4\">, <\/span><span style=\"color: #F286C4\">-<\/span><span style=\"color: #BF9EEE\">43.1729<\/span><span style=\"color: #F6F6F4\">),<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">        <\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">Bras\u00edlia<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">: (<\/span><span style=\"color: #F286C4\">-<\/span><span style=\"color: #BF9EEE\">15.79389<\/span><span style=\"color: #F6F6F4\">, <\/span><span style=\"color: #F286C4\">-<\/span><span style=\"color: #BF9EEE\">47.88278<\/span><span style=\"color: #F6F6F4\">),<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">        <\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">Salvador<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">: (<\/span><span style=\"color: #F286C4\">-<\/span><span style=\"color: #BF9EEE\">12.97139<\/span><span style=\"color: #F6F6F4\">, <\/span><span style=\"color: #F286C4\">-<\/span><span style=\"color: #BF9EEE\">38.50139<\/span><span style=\"color: #F6F6F4\">),<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    coords <\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\"> coordenadas_simuladas.get(city, (<\/span><span style=\"color: #BF9EEE\">14.123114<\/span><span style=\"color: #F6F6F4\">, <\/span><span style=\"color: #BF9EEE\">16.12312<\/span><span style=\"color: #F6F6F4\">))<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    <\/span><span style=\"color: #F286C4\">return<\/span><span style=\"color: #F6F6F4\"> {<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">text<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">: <\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">As coordenadas da cidade <\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F286C4\">+<\/span><span style=\"color: #F6F6F4\">city<\/span><span style=\"color: #F286C4\">+<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\"> \u00e9 latitude <\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F286C4\">+<\/span><span style=\"color: #97E1F1; font-style: italic\">str<\/span><span style=\"color: #F6F6F4\">(coords&#91;<\/span><span style=\"color: #BF9EEE\">0<\/span><span style=\"color: #F6F6F4\">&#93;)<\/span><span style=\"color: #F286C4\">+<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\"> e longitude <\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F286C4\">+<\/span><span style=\"color: #97E1F1; font-style: italic\">str<\/span><span style=\"color: #F6F6F4\">(coords&#91;<\/span><span style=\"color: #BF9EEE\">1<\/span><span style=\"color: #F6F6F4\">&#93;)}<\/span><\/span>\n<span class=\"line\"><\/span><\/code><\/pre><\/div>\n\n\n\n<p>No Google ADK, <strong>a forma como as ferramentas s\u00e3o declaradas influencia diretamente o comportamento do agente<\/strong>. Fun\u00e7\u00f5es bem definidas, com par\u00e2metros claros e descri\u00e7\u00f5es objetivas, ajudam o modelo a entender quando uma ferramenta deve ser utilizada e qual resultado esperar de sua execu\u00e7\u00e3o. Uma defini\u00e7\u00e3o inadequada pode levar a usos incorretos, respostas inconsistentes ou execu\u00e7\u00f5es desnecess\u00e1rias. Por isso, declarar corretamente as fun\u00e7\u00f5es que atuar\u00e3o como ferramentas \u00e9 um passo essencial para garantir agentes mais previs\u00edveis e eficientes.<\/p>\n\n\n\n<h2 class=\"wp-block-heading has-large-font-size\">Atualiza\u00e7\u00e3o autom\u00e1tica de token OAuth2 do WSO2<\/h2>\n\n\n\n<p>Durante o uso do Google ADK consumindo modelos LLM por meio do WSO2, um ponto importante \u00e9 o <strong>gerenciamento do token OAuth2<\/strong>. Como esses tokens possuem tempo de expira\u00e7\u00e3o, a aplica\u00e7\u00e3o pode falhar com erros de autentica\u00e7\u00e3o (<code>401<\/code> ou <code>AuthenticationError<\/code>) caso o token expire durante a execu\u00e7\u00e3o do agente.<\/p>\n\n\n\n<p>Para resolver esse problema, foi adicionada uma <strong>camada de refresh autom\u00e1tico do token<\/strong>, estendendo a classe <code>LiteLlm<\/code> utilizada pelo Google ADK.<\/p>\n\n\n\n<p>A ideia \u00e9 simples:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Executar a chamada normalmente para o modelo LLM via LiteLLM.<\/li>\n\n\n\n<li>Caso ocorra um erro de autentica\u00e7\u00e3o (<code>AuthenticationError<\/code>), assumir que o token expirou.<\/li>\n\n\n\n<li>Solicitar um novo token ao WSO2.<\/li>\n\n\n\n<li>Atualizar dinamicamente o header <code>Authorization<\/code>.<\/li>\n\n\n\n<li>Reexecutar a chamada ao modelo <strong>uma \u00fanica vez<\/strong>, agora com o token atualizado.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Implementa\u00e7\u00e3o<\/h3>\n\n\n\n<p>Abaixo est\u00e1 a classe respons\u00e1vel por encapsular esse comportamento:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#f6f6f4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>async def refresh_wso2_token() -> str:\n    async with httpx.AsyncClient() as client:\n        resp = await client.post(\n            url_token,\n            data={\n                \"grant_type\": \"client_credentials\",\n                \"client_id\": consumer_key,\n                \"client_secret\": consumer_secret,\n            },\n            headers={\"Content-Type\": \"application\/x-www-form-urlencoded\"},\n            timeout=10,\n        )\n        resp.raise_for_status()\n        return resp.json()&#91;\"access_token\"&#93;\n\nclass LiteLlmWithWso2Refresh(LiteLlm):\n    async def generate_content_async(\n        self, llm_request: LlmRequest, stream: bool = False\n    ) -> AsyncGenerator&#91;LlmResponse, None&#93;:\n\n        try:\n            async for resp in super().generate_content_async(\n                llm_request, stream=stream\n            ):\n                yield resp\n\n        except litellm.exceptions.AuthenticationError:\n\n            # \ud83d\udd01 Refresh do token OAuth2 no WSO2\n            new_token = await refresh_wso2_token()\n\n            # Atualiza o header Authorization sem efeitos colaterais\n            headers = self._additional_args.get(\"extra_headers\", {})\n            headers = dict(headers)\n            headers&#91;\"Authorization\"&#93; = f\"Bearer {new_token}\"\n\n            self._additional_args&#91;\"extra_headers\"&#93; = headers\n\n            # \ud83d\udd01 Reexecuta a chamada apenas uma vez\n            async for resp in super().generate_content_async(\n                llm_request, stream=stream\n            ):\n                yield resp<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula-soft\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #62E884\">async<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">def<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">refresh_wso2_token<\/span><span style=\"color: #F6F6F4\">() -<\/span><span style=\"color: #F286C4\">&gt;<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">str:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    <\/span><span style=\"color: #62E884\">async<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">with<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">httpx.AsyncClient<\/span><span style=\"color: #F6F6F4\">() <\/span><span style=\"color: #E7EE98\">as<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">client:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">        <\/span><span style=\"color: #62E884\">resp<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">=<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">await<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">client.post<\/span><span style=\"color: #F6F6F4\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">            <\/span><span style=\"color: #62E884\">url_token,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">            <\/span><span style=\"color: #BF9EEE\">data<\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #E7EE98\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">                <\/span><span style=\"color: #62E884\">&quot;grant_type&quot;<\/span><span style=\"color: #97E1F1\">:<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">client_credentials<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">                <\/span><span style=\"color: #62E884\">&quot;client_id&quot;<\/span><span style=\"color: #97E1F1\">:<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">consumer_key,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">                <\/span><span style=\"color: #62E884\">&quot;client_secret&quot;<\/span><span style=\"color: #97E1F1\">:<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">consumer_secret,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">            },<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">            <\/span><span style=\"color: #BF9EEE\">headers<\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #E7EE98\">{<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">Content-Type<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">:<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #62E884\">&quot;application\/x-www-form-urlencoded&quot;<\/span><span style=\"color: #62E884\">},<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">            <\/span><span style=\"color: #BF9EEE\">timeout<\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #BF9EEE\">10<\/span><span style=\"color: #E7EE98\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">        )<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">        <\/span><span style=\"color: #62E884\">resp.raise_for_status<\/span><span style=\"color: #F6F6F4\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">        return resp.json()&#91;<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">access_token<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">&#93;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #62E884\">class<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">LiteLlmWithWso2Refresh<\/span><span style=\"color: #F6F6F4\">(<\/span><span style=\"color: #62E884\">LiteLlm<\/span><span style=\"color: #F6F6F4\">)<\/span><span style=\"color: #E7EE98\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    <\/span><span style=\"color: #62E884\">async<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">def<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">generate_content_async<\/span><span style=\"color: #F6F6F4\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">        <\/span><span style=\"color: #62E884\">self,<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">llm_request:<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">LlmRequest,<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">stream:<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">bool<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">=<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">False<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    ) -<\/span><span style=\"color: #F286C4\">&gt;<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">AsyncGenerator&#91;LlmResponse,<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">None&#93;:<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">        <\/span><span style=\"color: #62E884\">try:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">            <\/span><span style=\"color: #62E884\">async<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">for<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">resp<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">in<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">super<\/span><span style=\"color: #F6F6F4\">()<\/span><span style=\"color: #E7EE98\">.generate_content_async<\/span><span style=\"color: #F6F6F4\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">                <\/span><span style=\"color: #62E884\">llm_request,<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">stream=stream<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">            )<\/span><span style=\"color: #E7EE98\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">                <\/span><span style=\"color: #62E884\">yield<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">resp<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">        <\/span><span style=\"color: #62E884\">except<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">litellm.exceptions.AuthenticationError:<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">            <\/span><span style=\"color: #7B7F8B\"># \ud83d\udd01 Refresh do token OAuth2 no WSO2<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">            <\/span><span style=\"color: #62E884\">new_token<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">=<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">await<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">refresh_wso2_token<\/span><span style=\"color: #F6F6F4\">()<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">            <\/span><span style=\"color: #7B7F8B\"># Atualiza o header Authorization sem efeitos colaterais<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">            <\/span><span style=\"color: #62E884\">headers<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">=<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">self._additional_args.get<\/span><span style=\"color: #F6F6F4\">(<\/span><span style=\"color: #62E884\">&quot;extra_headers&quot;<\/span><span style=\"color: #62E884\">,<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">{}<\/span><span style=\"color: #F6F6F4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">            <\/span><span style=\"color: #62E884\">headers<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">=<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">dict<\/span><span style=\"color: #F6F6F4\">(<\/span><span style=\"color: #62E884\">headers<\/span><span style=\"color: #F6F6F4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">            <\/span><span style=\"color: #62E884\">headers&#91;<\/span><span style=\"color: #62E884\">&quot;Authorization&quot;<\/span><span style=\"color: #62E884\">&#93;<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">=<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">f<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">Bearer {new_token}<\/span><span style=\"color: #DEE492\">&quot;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">            <\/span><span style=\"color: #62E884\">self._additional_args&#91;<\/span><span style=\"color: #62E884\">&quot;extra_headers&quot;<\/span><span style=\"color: #62E884\">&#93;<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">=<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">headers<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">            <\/span><span style=\"color: #7B7F8B\"># \ud83d\udd01 Reexecuta a chamada apenas uma vez<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">            <\/span><span style=\"color: #62E884\">async<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">for<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">resp<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">in<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">super<\/span><span style=\"color: #F6F6F4\">()<\/span><span style=\"color: #E7EE98\">.generate_content_async<\/span><span style=\"color: #F6F6F4\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">                <\/span><span style=\"color: #62E884\">llm_request,<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">stream=stream<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">            )<\/span><span style=\"color: #E7EE98\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">                <\/span><span style=\"color: #62E884\">yield<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">resp<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading has-large-font-size\">Cria\u00e7\u00e3o do modelo customizado (vLLM)<\/h2>\n\n\n\n<p>Nesta etapa \u00e9 realizada a cria\u00e7\u00e3o de um <strong>modelo customizado<\/strong> utilizando o <code>LiteLlm<\/code>, que ser\u00e1 respons\u00e1vel por intermediar a comunica\u00e7\u00e3o entre o agente do Google ADK e um modelo de linguagem servido via <strong>vLLM<\/strong>. Essa configura\u00e7\u00e3o permite que o agente utilize um modelo hospedado externamente, acessado por meio do WSO2, sem a necessidade de conex\u00e3o direta com o servidor do modelo.<\/p>\n\n\n\n<p>O trecho abaixo define o modelo que ser\u00e1 consumido pelo agente, especificando o identificador do modelo no vLLM, o endpoint exposto pelo WSO2 e os headers necess\u00e1rios para autentica\u00e7\u00e3o e comunica\u00e7\u00e3o com a API.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#f6f6f4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>custom_model = LiteLlmWithWso2Refresh(\n    model=\"hosted_vllm\/llama-31-8b-instruct\",\n    api_key=\"qualquer_key\",\n    base_url=wso2_endpoint,\n    extra_headers={\n        \"Authorization\": f\"Bearer {gera_token()}\",\n        \"Content-Type\": \"application\/json\",\n        \"Accept\": \"application\/json\"\n    }\n)<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula-soft\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F6F6F4\">custom_model <\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\"> LiteLlmWithWso2Refresh(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    <\/span><span style=\"color: #FFB86C; font-style: italic\">model<\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">hosted_vllm\/llama-31-8b-instruct<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    <\/span><span style=\"color: #FFB86C; font-style: italic\">api_key<\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">qualquer_key<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    <\/span><span style=\"color: #FFB86C; font-style: italic\">base_url<\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\">wso2_endpoint,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    <\/span><span style=\"color: #FFB86C; font-style: italic\">extra_headers<\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">        <\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">Authorization<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">: <\/span><span style=\"color: #F286C4\">f<\/span><span style=\"color: #E7EE98\">&quot;Bearer <\/span><span style=\"color: #BF9EEE\">{<\/span><span style=\"color: #F6F6F4\">gera_token()<\/span><span style=\"color: #BF9EEE\">}<\/span><span style=\"color: #E7EE98\">&quot;<\/span><span style=\"color: #F6F6F4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">        <\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">Content-Type<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">: <\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">application\/json<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">        <\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">Accept<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">: <\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">application\/json<\/span><span style=\"color: #DEE492\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">)<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Essa abordagem permite que o Google ADK utilize modelos servidos pelo vLLM de forma transparente, mantendo o controle de acesso, seguran\u00e7a e governan\u00e7a providos pelo WSO2.<\/p>\n\n\n\n<h2 class=\"wp-block-heading has-large-font-size\">Cria\u00e7\u00e3o do modelo customizado (Ollama)<\/h2>\n\n\n\n<p>Al\u00e9m do consumo de modelos servidos via vLLM, o Google ADK tamb\u00e9m pode ser configurado para utilizar modelos disponibilizados por meio do <strong>Ollama<\/strong>, desde que estes estejam expostos por um endpoint compat\u00edvel e protegidos pelo WSO2. Nesse cen\u00e1rio, o <code>LiteLlm<\/code> atua novamente como a camada de integra\u00e7\u00e3o entre o agente e o modelo de linguagem.<\/p>\n\n\n\n<p>O trecho a seguir demonstra a cria\u00e7\u00e3o de um modelo customizado apontando para um modelo hospedado no Ollama, especificando o identificador do modelo, o endpoint exposto pelo WSO2 e os headers necess\u00e1rios para autentica\u00e7\u00e3o.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#f6f6f4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>ollama_custom_model = LiteLlmWithWso2Refresh(\n    model=\"ollama\/llama3.1:8b\", \n    api_key=\"qualquer_key\",\n    api_base=wso2_endpoint, # Endpoint do OLLAMA\n    extra_headers={\n        \"Authorization\": f\"Bearer {gera_token()}\",\n        \"Content-Type\": \"application\/json\",\n        \"Accept\": \"application\/json\"\n    }\n)<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula-soft\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F6F6F4\">ollama_custom_model <\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\"> LiteLlmWithWso2Refresh(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    <\/span><span style=\"color: #FFB86C; font-style: italic\">model<\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">ollama\/llama3.1:8b<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">, <\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    <\/span><span style=\"color: #FFB86C; font-style: italic\">api_key<\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">qualquer_key<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    <\/span><span style=\"color: #FFB86C; font-style: italic\">api_base<\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\">wso2_endpoint, <\/span><span style=\"color: #7B7F8B\"># Endpoint do OLLAMA<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    <\/span><span style=\"color: #FFB86C; font-style: italic\">extra_headers<\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">        <\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">Authorization<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">: <\/span><span style=\"color: #F286C4\">f<\/span><span style=\"color: #E7EE98\">&quot;Bearer <\/span><span style=\"color: #BF9EEE\">{<\/span><span style=\"color: #F6F6F4\">gera_token()<\/span><span style=\"color: #BF9EEE\">}<\/span><span style=\"color: #E7EE98\">&quot;<\/span><span style=\"color: #F6F6F4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">        <\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">Content-Type<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">: <\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">application\/json<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">        <\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">Accept<\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #F6F6F4\">: <\/span><span style=\"color: #DEE492\">&quot;<\/span><span style=\"color: #E7EE98\">application\/json<\/span><span style=\"color: #DEE492\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">)<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Nesse caso, o valor informado em <code>api_key<\/code> \u00e9 apenas um placeholder, j\u00e1 que a autentica\u00e7\u00e3o efetiva ocorre por meio do token OAuth2 enviado no header <code>Authorization<\/code>. Essa configura\u00e7\u00e3o permite que o agente do Google ADK utilize modelos servidos pelo Ollama de forma segura e padronizada, mantendo a governan\u00e7a e o controle de acesso providos pelo WSO2.<\/p>\n\n\n\n<p>Apesar de ambos os modelos customizados utilizarem o <code>LiteLlm<\/code>, existem pequenas diferen\u00e7as na forma como o c\u00f3digo \u00e9 configurado para o <strong>vLLM<\/strong> e para o <strong>Ollama<\/strong>. No caso do vLLM, o modelo \u00e9 identificado pelo prefixo <code>hosted_vllm<\/code>, indicando que a infer\u00eancia ocorre em um servidor vLLM externo. J\u00e1 no Ollama, o prefixo <code>ollama<\/code> \u00e9 utilizado para sinalizar que o modelo segue o padr\u00e3o de consumo do Ollama.<\/p>\n\n\n\n<p>Al\u00e9m disso, h\u00e1 varia\u00e7\u00f5es nos par\u00e2metros de configura\u00e7\u00e3o: no vLLM \u00e9 utilizado o atributo <code>base_url<\/code>, enquanto no Ollama \u00e9 empregado <code>api_base<\/code>, refletindo a forma como cada backend exp\u00f5e seu endpoint.<\/p>\n\n\n\n<p>Essas diferen\u00e7as s\u00e3o sutis, mas importantes para que o <code>LiteLlm<\/code> identifique corretamente o backend utilizado e direcione as requisi\u00e7\u00f5es de forma adequada.<\/p>\n\n\n\n<p>Existem diferen\u00e7as importantes no papel de cada um dentro da arquitetura. No caso do vLLM, o foco est\u00e1 em <strong>alta performance e escalabilidade<\/strong>, sendo mais indicado para ambientes que exigem maior throughput e controle fino sobre recursos de infer\u00eancia. J\u00e1 o Ollama \u00e9 geralmente utilizado em cen\u00e1rios mais simples ou locais, facilitando a execu\u00e7\u00e3o e o gerenciamento de modelos com menor complexidade operacional.<\/p>\n\n\n\n<h2 class=\"wp-block-heading has-large-font-size\">Cria\u00e7\u00e3o do agente<\/h2>\n\n\n\n<p>Com o modelo customizado configurado e as ferramentas definidas, o pr\u00f3ximo passo \u00e9 a <strong>cria\u00e7\u00e3o do agente propriamente dito<\/strong> utilizando o Google ADK. \u00c9 nesse momento que s\u00e3o estabelecidos o comportamento, as regras de uso de ferramentas e a forma como o agente deve interagir com o usu\u00e1rio.<\/p>\n\n\n\n<p>No trecho abaixo, o agente \u00e9 criado a partir do <code>custom_model<\/code>, recebe um nome e uma descri\u00e7\u00e3o, e \u00e9 configurado com um conjunto de instru\u00e7\u00f5es detalhadas. Essas instru\u00e7\u00f5es funcionam como regras de opera\u00e7\u00e3o, orientando o agente sobre <strong>quando utilizar ferramentas<\/strong>, <strong>como responder ao usu\u00e1rio<\/strong> e <strong>quais comportamentos devem ser evitados<\/strong>. <\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#f6f6f4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>root_agent = Agent(\n    model=custom_model,\n    name='agente_ferramentas',\n    description='Agente com ferramentas',\n    instruction=\"\"\"Voc\u00ea \u00e9 um agente inteligente que pode usar ferramentas quando necess\u00e1rio.\n\nREGRAS ABSOLUTAS:\n\n1. Use UMA ferramenta por vez, somente se for estritamente necess\u00e1rio.\n2. Se a informa\u00e7\u00e3o j\u00e1 for suficiente para responder, N\u00c3O use ferramentas.\n3. Ap\u00f3s receber o resultado de uma ferramenta, voc\u00ea DEVE responder ao usu\u00e1rio.\n4. Nunca chame ferramentas novamente depois de j\u00e1 ter recebido os dados necess\u00e1rios.\n5. A resposta final ao usu\u00e1rio NUNCA deve conter chamadas de ferramentas.\n6. Nunca explique seu racioc\u00ednio interno, nem diga se usou ou n\u00e3o ferramentas, a menos que o usu\u00e1rio pergunte.\n\nFERRAMENTAS DISPON\u00cdVEIS:\n\nget_latitude_longitude(city)\nRetorna a latitude e longitude de uma cidade.\n\nget_tamanho_cidade(city)\nRetorna a \u00e1rea aproximada (em km\u00b2) de uma cidade.\n\nget_horas(city)\nRetorna o hor\u00e1rio atual aproximado em uma cidade.\n\nCOMPORTAMENTO:\n\n- Se a pergunta puder ser respondida com conhecimento geral \u2192 responda naturalmente.\n- Se exigir um dado espec\u00edfico ou atual \u2192 use a ferramenta correta.\n- Quando responder ao usu\u00e1rio, seja direto, claro e natural.\n\nAgora aguarde a pergunta do usu\u00e1rio.\n\"\"\",\n    tools=&#91;\n        get_horas,\n        get_tamanho_cidade,\n        get_latitude_longitude\n    &#93;\n)<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula-soft\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F6F6F4\">root_agent <\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\"> Agent(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    <\/span><span style=\"color: #FFB86C; font-style: italic\">model<\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\">custom_model,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    <\/span><span style=\"color: #FFB86C; font-style: italic\">name<\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #DEE492\">&#39;<\/span><span style=\"color: #E7EE98\">agente_ferramentas<\/span><span style=\"color: #DEE492\">&#39;<\/span><span style=\"color: #F6F6F4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    <\/span><span style=\"color: #FFB86C; font-style: italic\">description<\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #DEE492\">&#39;<\/span><span style=\"color: #E7EE98\">Agente com ferramentas<\/span><span style=\"color: #DEE492\">&#39;<\/span><span style=\"color: #F6F6F4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    <\/span><span style=\"color: #FFB86C; font-style: italic\">instruction<\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #DEE492\">&quot;&quot;&quot;<\/span><span style=\"color: #E7EE98\">Voc\u00ea \u00e9 um agente inteligente que pode usar ferramentas quando necess\u00e1rio.<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #E7EE98\">REGRAS ABSOLUTAS:<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #E7EE98\">1. Use UMA ferramenta por vez, somente se for estritamente necess\u00e1rio.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #E7EE98\">2. Se a informa\u00e7\u00e3o j\u00e1 for suficiente para responder, N\u00c3O use ferramentas.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #E7EE98\">3. Ap\u00f3s receber o resultado de uma ferramenta, voc\u00ea DEVE responder ao usu\u00e1rio.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #E7EE98\">4. Nunca chame ferramentas novamente depois de j\u00e1 ter recebido os dados necess\u00e1rios.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #E7EE98\">5. A resposta final ao usu\u00e1rio NUNCA deve conter chamadas de ferramentas.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #E7EE98\">6. Nunca explique seu racioc\u00ednio interno, nem diga se usou ou n\u00e3o ferramentas, a menos que o usu\u00e1rio pergunte.<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #E7EE98\">FERRAMENTAS DISPON\u00cdVEIS:<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #E7EE98\">get_latitude_longitude(city)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #E7EE98\">Retorna a latitude e longitude de uma cidade.<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #E7EE98\">get_tamanho_cidade(city)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #E7EE98\">Retorna a \u00e1rea aproximada (em km\u00b2) de uma cidade.<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #E7EE98\">get_horas(city)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #E7EE98\">Retorna o hor\u00e1rio atual aproximado em uma cidade.<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #E7EE98\">COMPORTAMENTO:<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #E7EE98\">- Se a pergunta puder ser respondida com conhecimento geral \u2192 responda naturalmente.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #E7EE98\">- Se exigir um dado espec\u00edfico ou atual \u2192 use a ferramenta correta.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #E7EE98\">- Quando responder ao usu\u00e1rio, seja direto, claro e natural.<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #E7EE98\">Agora aguarde a pergunta do usu\u00e1rio.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #DEE492\">&quot;&quot;&quot;<\/span><span style=\"color: #F6F6F4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    <\/span><span style=\"color: #FFB86C; font-style: italic\">tools<\/span><span style=\"color: #F286C4\">=<\/span><span style=\"color: #F6F6F4\">&#91;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">        get_horas,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">        get_tamanho_cidade,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">        get_latitude_longitude<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">    &#93;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F6F6F4\">)<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>A defini\u00e7\u00e3o expl\u00edcita das regras dentro do campo <code>instruction<\/code> \u00e9 fundamental para garantir um comportamento previs\u00edvel do agente, evitando usos desnecess\u00e1rios de ferramentas ou ciclos de execu\u00e7\u00e3o incorretos. J\u00e1 o par\u00e2metro <code>tools<\/code> informa ao Google ADK quais fun\u00e7\u00f5es est\u00e3o dispon\u00edveis para o agente, permitindo que ele escolha a ferramenta adequada apenas quando a informa\u00e7\u00e3o n\u00e3o puder ser obtida diretamente pelo modelo.<\/p>\n\n\n\n<p>Essa separa\u00e7\u00e3o entre <strong>modelo<\/strong>, <strong>ferramentas<\/strong> e <strong>instru\u00e7\u00f5es<\/strong> \u00e9 um dos principais diferenciais do Google ADK, pois torna o agente mais control\u00e1vel, reutiliz\u00e1vel e alinhado a cen\u00e1rios corporativos.<\/p>\n\n\n\n<h2 class=\"wp-block-heading has-medium-font-size\">Estrutura final do projeto<\/h2>\n\n\n\n<p>Ao final da implementa\u00e7\u00e3o, o projeto fica organizado de forma simples e modular, separando os agentes de acordo com o modelo utilizado. Essa organiza\u00e7\u00e3o facilita a manuten\u00e7\u00e3o, os testes e a evolu\u00e7\u00e3o do c\u00f3digo, al\u00e9m de permitir reutilizar a mesma base para diferentes backends de infer\u00eancia.<\/p>\n\n\n\n<p>A estrutura final dos arquivos \u00e9 apresentada a seguir:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.\n\u251c\u2500\u2500 README.md\n\u251c\u2500\u2500 requirements.txt\n\u251c\u2500\u2500 hello\n\u2502   \u251c\u2500\u2500 __init__.py\n\u2502   \u251c\u2500\u2500 .env\n\u2502   \u2514\u2500\u2500 agent.py\n\u2514\u2500\u2500 helloollama\n    \u251c\u2500\u2500 __init__.py\n    \u251c\u2500\u2500 .env\n    \u2514\u2500\u2500 agent.py\n<\/code><\/pre>\n\n\n\n<p>O arquivo <code>README.md<\/code> concentra as instru\u00e7\u00f5es gerais do projeto, enquanto o <code>requirements.txt<\/code> define as depend\u00eancias necess\u00e1rias para execu\u00e7\u00e3o. Cada diret\u00f3rio (<code>hello<\/code> e <code>helloollama<\/code>) representa um agente independente, com sua pr\u00f3pria configura\u00e7\u00e3o de ambiente (<code>.env<\/code>) e arquivo principal (<code>agent.py<\/code>), permitindo apontar para modelos distintos, como vLLM ou Ollama, sem interfer\u00eancia entre eles.<\/p>\n\n\n\n<p>Em todos os arquivos <code>__init__.py<\/code>, foi inclu\u00edda apenas a linha:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#f6f6f4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>from . import agent<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula-soft\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F286C4\">from<\/span><span style=\"color: #F6F6F4\"> . <\/span><span style=\"color: #F286C4\">import<\/span><span style=\"color: #F6F6F4\"> agent<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Essa abordagem garante que o m\u00f3dulo do agente seja carregado automaticamente ao importar o pacote, mantendo a estrutura simples e consistente, sem adicionar l\u00f3gica desnecess\u00e1ria nesses arquivos.<\/p>\n\n\n\n<p>Essa separa\u00e7\u00e3o torna o projeto mais organizado e facilita a adapta\u00e7\u00e3o do c\u00f3digo para novos agentes, modelos ou ambientes, mantendo uma estrutura clara e escal\u00e1vel.<\/p>\n\n\n\n<h2 class=\"wp-block-heading has-large-font-size\">Execu\u00e7\u00e3o dos agentes com o Google ADK<\/h2>\n\n\n\n<p>Ap\u00f3s a defini\u00e7\u00e3o do agente e da estrutura do projeto, o Google ADK oferece diferentes formas de executar e testar os agentes criados. As duas mais comuns s\u00e3o por meio da interface web (<code>adk web<\/code>) e pela linha de comando (<code>adk run<\/code>), ambas utilizando a mesma base de c\u00f3digo.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Execu\u00e7\u00e3o via <code>adk run<\/code><\/h4>\n\n\n\n<p>A forma mais simples de executar um agente \u00e9 utilizando o comando <code>adk run<\/code>, apontando para o m\u00f3dulo que cont\u00e9m a defini\u00e7\u00e3o do agente. Por exemplo, para executar o agente configurado com o modelo vLLM:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#f6f6f4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>adk run hello<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula-soft\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #62E884\">adk<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">run<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">hello<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Ou, no caso do agente que utiliza o modelo via Ollama:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#f6f6f4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>adk run helloollama<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula-soft\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #62E884\">adk<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">run<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">helloollama<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Nesse modo, o agente \u00e9 iniciado em um ambiente interativo no terminal, permitindo enviar perguntas diretamente e observar o comportamento do agente, incluindo o uso (ou n\u00e3o) das ferramentas definidas.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Execu\u00e7\u00e3o via <code>adk web<\/code><\/h4>\n\n\n\n<p>Outra op\u00e7\u00e3o \u00e9 executar o agente utilizando a interface web fornecida pelo ADK, o que pode ser \u00fatil para testes manuais e demonstra\u00e7\u00f5es. Para isso, basta executar:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#f6f6f4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>adk web<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula-soft\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #62E884\">adk<\/span><span style=\"color: #F6F6F4\"> <\/span><span style=\"color: #E7EE98\">web<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Ao iniciar esse comando, o ADK sobe uma interface web local onde os agentes dispon\u00edveis no projeto podem ser selecionados e testados por meio de um chat. Essa abordagem facilita a valida\u00e7\u00e3o do comportamento do agente sem a necessidade de intera\u00e7\u00f5es via terminal.<\/p>\n\n\n\n<p>Ambos os modos utilizam as mesmas configura\u00e7\u00f5es, modelos e ferramentas definidos no c\u00f3digo, tornando o processo de execu\u00e7\u00e3o flex\u00edvel e adequado tanto para desenvolvimento quanto para testes iniciais.<\/p>\n\n\n\n<h2 class=\"wp-block-heading has-large-font-size\">Conclus\u00e3o<\/h2>\n\n\n\n<p>Ao longo deste material, foi apresentado um passo a passo para a cria\u00e7\u00e3o de agentes inteligentes utilizando o Google ADK, consumindo modelos de linguagem protegidos e expostos por meio do WSO2. A abordagem demonstrou como evoluir de um uso simples de LLMs para a constru\u00e7\u00e3o de agentes com comportamento controlado, uso consciente de ferramentas e integra\u00e7\u00e3o com diferentes backends de infer\u00eancia, como vLLM e Ollama. Esse modelo de desenvolvimento permite maior governan\u00e7a, seguran\u00e7a e previsibilidade, atendendo \u00e0s necessidades de ambientes corporativos e governamentais, al\u00e9m de servir como base para a expans\u00e3o futura com novos agentes, ferramentas e integra\u00e7\u00f5es.<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Neste artigo vamos mostrar um passo a passo de um agente usando o Google ADK que consome modelos de linguagem publicados no WSO2 do Estado de Goi\u00e1s, permitindo a cria\u00e7\u00e3o de agentes com ferramentas, mem\u00f3ria e controle de execu\u00e7\u00e3o.<\/p>\n","protected":false},"author":712,"featured_media":205379,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_links_to":"","_links_to_target":""},"categories":[55,26],"tags":[61],"class_list":["post-205378","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-inteligencia_artificial","category-publicacoes-ligo","tag-inteligencia-artificial"],"rttpg_featured_image_url":{"full":["https:\/\/goias.gov.br\/ligo\/wp-content\/uploads\/sites\/61\/2025\/12\/capaoutra.jpg",1024,1331,false],"landscape":["https:\/\/goias.gov.br\/ligo\/wp-content\/uploads\/sites\/61\/2025\/12\/capaoutra.jpg",1024,1331,false],"portraits":["https:\/\/goias.gov.br\/ligo\/wp-content\/uploads\/sites\/61\/2025\/12\/capaoutra.jpg",1024,1331,false],"thumbnail":["https:\/\/goias.gov.br\/ligo\/wp-content\/uploads\/sites\/61\/2025\/12\/capaoutra-150x150.jpg",150,150,true],"medium":["https:\/\/goias.gov.br\/ligo\/wp-content\/uploads\/sites\/61\/2025\/12\/capaoutra-231x300.jpg",231,300,true],"large":["https:\/\/goias.gov.br\/ligo\/wp-content\/uploads\/sites\/61\/2025\/12\/capaoutra-788x1024.jpg",788,1024,true],"1536x1536":["https:\/\/goias.gov.br\/ligo\/wp-content\/uploads\/sites\/61\/2025\/12\/capaoutra.jpg",1024,1331,false],"2048x2048":["https:\/\/goias.gov.br\/ligo\/wp-content\/uploads\/sites\/61\/2025\/12\/capaoutra.jpg",1024,1331,false]},"rttpg_author":{"display_name":"Adriano Pericles","author_link":"https:\/\/goias.gov.br\/ligo\/author\/adrianorodrigues\/"},"rttpg_comment":1,"rttpg_category":"<a href=\"https:\/\/goias.gov.br\/ligo\/categoria\/publicacoes-ligo\/inteligencia_artificial\/\" rel=\"category tag\">Intelig\u00eancia Artificial<\/a> <a href=\"https:\/\/goias.gov.br\/ligo\/categoria\/publicacoes-ligo\/\" rel=\"category tag\">Publica\u00e7\u00f5es Ligo<\/a>","rttpg_excerpt":"Neste artigo vamos mostrar um passo a passo de um agente usando o Google ADK que consome modelos de linguagem publicados no WSO2 do Estado de Goi\u00e1s, permitindo a cria\u00e7\u00e3o de agentes com ferramentas, mem\u00f3ria e controle de execu\u00e7\u00e3o.","_links":{"self":[{"href":"https:\/\/goias.gov.br\/ligo\/wp-json\/wp\/v2\/posts\/205378","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/goias.gov.br\/ligo\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/goias.gov.br\/ligo\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/goias.gov.br\/ligo\/wp-json\/wp\/v2\/users\/712"}],"replies":[{"embeddable":true,"href":"https:\/\/goias.gov.br\/ligo\/wp-json\/wp\/v2\/comments?post=205378"}],"version-history":[{"count":2,"href":"https:\/\/goias.gov.br\/ligo\/wp-json\/wp\/v2\/posts\/205378\/revisions"}],"predecessor-version":[{"id":205401,"href":"https:\/\/goias.gov.br\/ligo\/wp-json\/wp\/v2\/posts\/205378\/revisions\/205401"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/goias.gov.br\/ligo\/wp-json\/wp\/v2\/media\/205379"}],"wp:attachment":[{"href":"https:\/\/goias.gov.br\/ligo\/wp-json\/wp\/v2\/media?parent=205378"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/goias.gov.br\/ligo\/wp-json\/wp\/v2\/categories?post=205378"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/goias.gov.br\/ligo\/wp-json\/wp\/v2\/tags?post=205378"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}