1. Visão geral
O cenário da tecnologia e da IA muda mais rápido do que qualquer pessoa consegue acompanhar. Novos modelos, artigos e produtos são lançados todos os dias. Um agente de resumo que busca as manchetes de hoje, escreve resumos objetivos e gera um PDF todas as manhãs resolveria isso. No entanto, criar um significava escolher um framework, definir ferramentas em Python, escrever um loop de orquestração, empacotar um contêiner e implantar no Cloud Run. Tudo isso antes de o agente fazer uma única solicitação da Web.
Os agentes gerenciados na API Gemini mudam essa equação. Você escreve dois arquivos de configuração do Markdown e um script renderizador pré-criado, faz uma chamada de API e uma sandbox do Ubuntu real é inicializada, navega na Web, escreve seus resumos e gera um PDF. Nenhum contêiner. Nenhuma implantação. Nenhum código de orquestração.
Neste codelab, você vai criar exatamente esse agente: de uma função vazia a um resumo diário funcional, um conceito por vez.
O que você criará
- Criar e executar seu primeiro agente gerenciado em uma sandbox real do Linux
- Personalizar o agente com instruções detalhadas
- Baixar a saída em PDF do agente
- Continue a conversa para refinar o resumo sem buscar novamente na Web
- Salve a configuração do agente e invoque-a por ID em execuções futuras
O que é necessário
- Python 3.10 ou mais recente
- Uma chave da API Gemini com o faturamento ativado: aistudio.google.com/api-keys
- ~US$1 de crédito de API (cada execução completa custa de US $0,30 a US$ 1,30)
2. O que são agentes gerenciados na API Gemini?
Três níveis de sistemas de IA
Antes de começar a programar, confira onde os agentes gerenciados se encaixam em relação às duas alternativas:
Nível | O que é | Quem gerencia a infraestrutura? |
LLM padrão | Você faz um comando, e ele responde com texto. Sem as mãos, sem memória, sem Internet. | N/A: não pode fazer nada sozinho |
Agente auto-hospedado | Você conecta ADK/LangChain/AutoGen + Docker + ferramentas + memória. | Você: tudo (ou uma plataforma gerenciada como o Agent Engine) |
Agente gerenciado | Você dá um objetivo a ele. O Google provisiona um sandbox seguro. O agente escreve e executa código, lê erros, pesquisa na Web e corrige bugs de forma autônoma. | Google: tudo isso |
Este codelab é sobre a terceira linha. Você fornece uma tarefa e arquivos de configuração. O Google cuida de todo o resto.
O que você pode criar com o ADK e o Cloud Run
Para criar um agente de resumo de notícias que navega na Web, executa Python e gera um PDF, você precisa de tudo isso com o ADK + Cloud Run:
# agent.py: define tools and wire up the agent
from google.adk.agents import LlmAgent
from google.adk.tools import google_search, built_in_code_execution
agent = LlmAgent(
name="digest-agent",
model=MODEL,
instruction=AGENTS_MD, # your editorial voice and rules
tools=[google_search, built_in_code_execution],
)
# app.py: serve the agent over HTTP
from google.adk.runners import FastApiRunner
runner = FastApiRunner(agent=agent)
app = runner.app
# pdf_tool.py: custom tool, install reportlab, render PDF
# scraper.py: custom tool, fetch each news source
# streaming.py: wire agent events to your SSE endpoint
# Dockerfile: package everything
FROM python:3.12
COPY . /app
RUN pip install google-adk reportlab requests
CMD ["uvicorn", "app:app", "--host", "0.0.0.0"]
# Deploy to Cloud Run
gcloud run deploy digest-agent \
--image gcr.io/your-project/digest-agent \
--set-secrets GEMINI_API_KEY=gemini-key:latest \
--memory 2Gi
Isso é antes de o agente ser executado pela primeira vez. Você ainda tem isolamento de sandbox (para que o agente não danifique seu servidor), instalação de pacotes, gerenciamento de estado entre chamadas de ferramentas e a infraestrutura de streaming para enviar eventos a um cliente.
O que os agentes gerenciados substituem
from google import genai
client = genai.Client()
stream = client.interactions.create(
agent="antigravity-preview-05-2026",
input="",
stream=True,
environment={
"type": "remote",
"sources": [ # your config files, mounted at startup
{
"type": "inline",
"target": ".agents/AGENTS.md",
"content": AGENTS_MD,
},
{
"type": "inline",
"target": ".agents/skills/digest-pdf/SKILL.md",
"content": SKILL_MD,
},
{
"type": "inline",
"target": ".agents/skills/digest-pdf/scripts/generate_pdf.py",
"content": GENERATE_PDF_PY,
},
],
},
)
O que o ADK + Cloud Run exige | O que os agentes gerenciados fazem por você |
Imagem do contêiner + Dockerfile + CI/CD | Sandbox do Ubuntu totalmente gerenciado (Python 3.12, Node 22, 4 CPUs / 16 GB de RAM) |
Implantação e escalonamento do Cloud Run | Provisionado por interação, expira automaticamente após 7 dias de inatividade |
Isolamento do sandbox | Isolado por interação |
Ferramenta de PDF personalizada + | O agente instala pacotes no sandbox |
Infraestrutura de streaming SSE |
|
Definições de ferramentas em Python | Ferramentas integradas: navegação na Web, execução de código, sistema de arquivos |
Gerenciamento de estado entre chamadas de ferramentas | Integrado ao ciclo de raciocínio do agente |
Você escreve arquivos de configuração (AGENTS.md, SKILL.md, um script pré-criado) e faz uma chamada de API. O Google cuida de todo o resto.
Como o sandbox funciona
interactions.create() call
│
▼
Google provisions Ubuntu sandbox (Python 3.12, Node 22, 4 CPU / 16 GB RAM)
│
▼
Agent reasoning loop:
plan → fetch URLs → run Python → write files → reason → repeat
│
▼
Events stream back in real time: tool calls, text chunks, completion
│
▼
interaction.completed → environment_id + interaction_id
O sandbox persiste por 7 dias de inatividade. Você pode retomar com environment_id para refinar a saída, executar tarefas de acompanhamento ou bifurcar em um agente salvo e nomeado.
3. Configurar
Opção A: Cloud Shell (recomendado)
Clique no botão abaixo para abrir este codelab no Google Cloud Shell. Todas as dependências são pré-instaladas.
Opção B: configuração local
git clone https://github.com/Saoussen-CH/tech-digest-managed-agent.git
cd tech-digest-managed-agent
Instale o uv, se necessário:
curl -LsSf https://astral.sh/uv/install.sh | sh
configurar sua chave de API
cp .env.example .env
cloudshell edit .env
Defina sua chave:
GEMINI_API_KEY=your-key-here
Instalar dependências
uv sync
4. Fazer sua primeira chamada de agente
Abra o arquivo inicial
cloudshell edit run_digest.py
O run_digest() tem uma tarefa TODO para preencher agora e mais três para a próxima etapa. Dois assistentes já estão pré-preenchidos acima dele:
load_source(path): lê um arquivo de.agents/relativo ao script. Você vai usá-lo no próximo exercício para montar o estilo editorial, o manual em PDF e o renderizador na sandbox.run_stream(stream): processa o fluxo de eventos e retorna(environment_id, interaction_id). Você não precisa escrever o loop de eventos.
O que adicionar
TODO 1:substitua pass por (ignore os TODOs 3 e 4 por enquanto, eles são para a próxima etapa):
from google import genai
client = genai.Client()
stream = client.interactions.create(
agent=BASE_AGENT,
input="Fetch the Hacker News front page and list the top 5 stories.",
stream=True,
environment="remote",
)
environment_id, interaction_id = run_stream(stream)
print(f"\nDone. environment_id={environment_id}")
O que cada parte faz
genai.Client() lê GEMINI_API_KEY do ambiente. Todo o resto passa por esse cliente.
interactions.create() é a chamada principal. Quatro parâmetros fazem isso funcionar:
agent=BASE_AGENT: seleciona o agente do Antigravity (antigravity-preview-05-2026), um agente gerenciado de uso geral com tecnologia do Gemini 3.5 Flash. Ele vem com três ferramentas integradas ativadas por padrão:code_execution(executar Bash, Python, Node.js),google_searcheurl_context(buscar e ler páginas da Web). As ferramentas do sistema de arquivos (read_file,write_file,list_files) são ativadas automaticamente quando você transmite o parâmetroenvironment. Uma chamada provisiona um ambiente Ubuntu totalmente gerenciado com Python 3.12, Node.js 22, git, pip e curl pré-instalados. Não há contêiner para criar nem implantação para executar.input: a tarefa desta execução. O agente navega pelo Hacker News e analisa os resultados.environment="remote": provisiona um novo sandbox da nuvem para essa interação.stream=True: retorna um iterável de eventos em vez de bloquear. Sem ele, a chamada aguarda de 30 a 90 segundos e retorna toda a saída de uma vez comointeraction.output_text. Com o streaming, você vê o motivo e a ação do agente conforme eles acontecem. O streaming não é um recurso avançado aqui: é o padrão certo, porque uma caixa preta de 90 segundos não dá nenhum sinal sobre se o agente está funcionando ou travado.
O que você acabou de provisionar:cada chamada interactions.create() inicializa um sandbox dedicado:
Componente | Especificação |
Sistema operacional | Ambiente isolado do Ubuntu Linux |
Ambientes de execução pré-instalados | Python 3.12, Node.js 22, Bash |
Computação | 4 núcleos de CPU, 16 GB de RAM |
Gerenciamento de contexto | A compactação automática é acionada com cerca de 135 mil tokens. |
Rede | Acesso à Web de saída via proxy de saída |
O agente pode instalar qualquer pacote com pip ou npm, ler e gravar arquivos e fazer solicitações da Web de saída. Sua máquina e suas credenciais nunca são tocadas.
environment_id é um handle do sandbox que acabou de ser executado. Após interaction.completed, o sandbox não é desligado: ele fica ativo por até 7 dias. O environment_id é como você volta a ele. Transmita para uma segunda chamada interactions.create(), e o agente será retomado no mesmo sistema de arquivos, com os mesmos arquivos e pacotes instalados, como se nunca tivesse saído. A próxima etapa usa esse valor para baixar o PDF sem executar o agente novamente, e a etapa seguinte o usa para continuar a conversa.
interaction_id é um identificador da conversa que acabou de ser concluída. Transmita como previous_interaction_id na próxima chamada, e o agente terá memória completa do que disse e fez nesta vez.
Verificar
uv run python run_digest.py
Você vai ver a saída ao vivo enquanto o agente trabalha:
[agent started]
[tool] run_code
Here are the top 5 stories currently on the Hacker News front page, retrieved via the official Hacker News API:
1. **Qwen 3.6 27B is the sweet spot for local development** — 471 points
2. **.self: A new top-level domain designed to support self-hosting** — 116 points
...
Done. environment_id=e3de58774073f75a6ef42924c6ce2e88
A API retorna um environment_id real mesmo com environment="remote". O sandbox foi executado. O que está faltando é a configuração: sem voz, sem skill, sem gerador de PDF. O agente apenas imprimiu histórias como texto e parou. A próxima etapa adiciona esses dados.
Cada linha de saída é mapeada para um evento de run_stream():
| O que é | O que |
| agente buscando um URL |
|
| agente executando código no sandbox |
|
| agente pesquisando na Web |
|
| ferramentas de arquivos e outros |
|
| texto escrito pelo agente | transmitido diretamente para stdout |
5. Personalizar o agente
O agente não tinha instruções: sem voz, sem habilidade, sem gerador de PDF. Nesta etapa, você carrega os arquivos de configuração de .agents/ e os monta no sandbox.
O que mudar
Faça quatro mudanças em run_digest.py:
TODO 2:abaixo de load_source(), adicione as três constantes no nível do módulo (elas ficam fora de run_digest(), na parte de cima do arquivo):
AGENTS_MD = load_source(".agents/AGENTS.md")
SKILL_MD = load_source(".agents/skills/digest-pdf/SKILL.md")
GENERATE_PDF_PY = load_source(".agents/skills/digest-pdf/scripts/generate_pdf.py")
Abra cada arquivo para ver o que você está carregando: AGENTS.md define o estilo editorial e as regras de fluxo de trabalho; SKILL.md é o manual em PDF com instruções detalhadas; generate_pdf.py é o renderizador pré-criado que o agente vai executar.
Agora faça mais duas mudanças em run_digest():
TODO 3:mude environment de "remote" para o dicionário de fontes e defina input como "":
environment={
"type": "remote",
"sources": [
{
"type": "inline",
"target": ".agents/AGENTS.md",
"content": AGENTS_MD,
},
{
"type": "inline",
"target": ".agents/skills/digest-pdf/SKILL.md",
"content": SKILL_MD,
},
{
"type": "inline",
"target": ".agents/skills/digest-pdf/scripts/generate_pdf.py",
"content": GENERATE_PDF_PY,
},
],
},
TODO 4:adicione estas linhas logo após print(f"\nDone. environment_id={environment_id}"):
set_key(".env", "ENVIRONMENT_ID", environment_id)
set_key(".env", "INTERACTION_ID", interaction_id)
(set_key já está importado na parte de cima de run_digest.py.)
Isso grava os dois IDs em .env durante essa execução. Assim, a próxima etapa pode baixar o PDF sem executar o agente novamente.
O que cada fonte faz
Cada origem é um arquivo montado no sistema de arquivos do sandbox na inicialização, antes da execução do agente. Os caminhos target correspondem ao local em que o arnês Antigravity espera encontrá-los:
.agents/
├── AGENTS.md ← auto-loaded as global instructions
└── skills/
└── digest-pdf/
├── SKILL.md ← auto-discovered and registered as a skill
└── scripts/
└── generate_pdf.py ← pre-built renderer the agent can run
caminho | Variável | O que o arnês faz com ele |
|
| Carregadas automaticamente como instruções persistentes: estilo editorial, fluxo de trabalho, regras de execução |
|
| Descoberta e registrada automaticamente como uma habilidade nomeada. O agente a invoca por nome. |
|
| Renderizador de PDF pré-criado. O agente escreve |
Verificar
uv run python run_digest.py
A execução leva de 1 a 3 minutos. Você vai ver o agente lendo arquivos de configuração, gravando resumos e salvando o PDF:
[agent started]
[tool] read_file (/.agents/skills/digest-pdf/SKILL.md)
[tool] list_files (/.agents/skills/digest-pdf/scripts)
[tool] read_file (/.agents/skills/digest-pdf/scripts/generate_pdf.py)
[tool] run_code
[tool] write_file (/workspace/summaries.json)
[tool] run_code
[tool] delete_file (/tmp/test_scrape.py)
I have successfully generated today's tech news digest and saved the formatted document to /workspace/digest.pdf.
Done. environment_id=4129ffd75574e308748e9425d7ec828f
environment_id agora é um valor real: o sandbox foi executado com seus arquivos de configuração, e o agente criou digest.pdf. A próxima etapa faz o download.
6. Faça download do PDF
O agente escreveu digest.pdf em /workspace/digest.pdf na sandbox. O snapshot do ambiente está disponível como um arquivo tar pela API Gemini Files.
Instale o requests, se necessário:
uv pip install requests
O que preencher
Abra download_pdf.py. Ele tem duas tarefas TODO.
TODO 1:preencha a chamada requests.get():
r = requests.get(
f"https://generativelanguage.googleapis.com/v1beta/files/environment-{environment_id}:download",
params={"alt": "media"},
headers={"x-goog-api-key": api_key},
allow_redirects=True,
)
r.raise_for_status()
O URL aborda o snapshot do sandbox. params={"alt": "media"} retorna bytes brutos em vez de metadados. Seu GEMINI_API_KEY atual também autentica a API Files.
TODO 2:encontre e extraia o PDF do arquivo tar:
member = next(m for m in tar.getmembers() if m.name.endswith("workspace/digest.pdf"))
tar.extract(member, path=tmp, filter="data")
O prefixo do caminho tar varia entre as execuções. Portanto, pesquise por sufixo em vez de codificar o caminho exato. filter="data" suprime o aviso de descontinuação do Python 3.13 sobre extração de tar não segura.
Verificar
uv run python download_pdf.py
Saved digest.pdf (48,231 bytes)
Abra digest.pdf no mesmo diretório. Ele contém o resumo formatado que o agente gerou de páginas da Web ativas.
7. Continuar a conversa
Você já tem o digest.pdf. Se você só queria o arquivo, está tudo pronto. Esta etapa é sobre algo diferente: pedir ao agente para mudar o resumo sem buscar novamente na Web.
O sandbox ainda está ativo. O agente ainda tem /workspace/digest.pdf e lembra de todas as matérias que resumiu. Uma segunda chamada interactions.create() envia uma mensagem de acompanhamento para essa mesma sandbox. Aqui, você pede para adicionar uma observação "Por que isso é importante" em cada matéria, e o PDF é atualizado no lugar, sem nova busca ou resumo.
O que preencher
Abra refine_digest.py. Ele tem três TODOs.
TODOs 1 e 2:preencha os dois parâmetros multiturno em interactions.create():
environment=environment_id,
previous_interaction_id=interaction_id,
O environment=environment_id retoma o mesmo sandbox com os arquivos e pacotes dele. previous_interaction_id=interaction_id dá ao agente o histórico de conversas. Nada mais muda em relação à primeira chamada.
TODO 3:persista o novo interaction_id de volta para .env após o loop de eventos:
set_key(".env", "INTERACTION_ID", interaction_id)
Cada chamada interactions.create() produz um novo interaction_id. Ao reescrever, a próxima execução passa esse refinamento como previous_interaction_id, encadeando as ações corretamente. O ID da sandbox nunca muda, então não é necessário atualizar o ENVIRONMENT_ID.
Os dois parâmetros que fazem o multiturno funcionar
ID | O que ele preserva | Analogia |
| Arquivos, pacotes instalados, estado do sistema: tudo no sistema de arquivos do Linux | Manter a mesma mesa de escritório entre as reuniões |
| Histórico da conversa: o que o agente disse e fez em interações anteriores | Lembrar o que foi discutido na última reunião |
Você pode transmitir qualquer um dos IDs de forma independente:
environment_idapenas: reutilize arquivos e pacotes, mas inicie uma nova conversa. Útil para uma nova tarefa no mesmo espaço de trabalho.previous_interaction_idapenas: continue o contexto da conversa, mas em uma nova sandbox (os arquivos sumiram).- Ambos: continuidade total, que é o que esta etapa usa.
Sem environment_id: sandbox em branco, sem PDF. Sem previous_interaction_id: sem contexto, o agente não pode refinar uma seção específica.
Verificar
uv run python refine_digest.py
O stream precisa ser rápido, já que o agente não está buscando nada de novo. Depois que ele terminar:
Refinement done.
Saved digest_v2.pdf (52,418 bytes)
Abra digest_v2.pdf e compare com digest.pdf. Cada matéria agora tem uma linha "Por que isso é importante".
8. Persistir uma configuração de agente gerenciado
Até agora, todas as chamadas transmitiram AGENTS.md, SKILL.md e generate_pdf.py inline. Isso funciona, mas o código de chamada carrega todo o conteúdo do arquivo em cada execução. O agents.create() incorpora a configuração a um agente salvo e nomeado no lado do Google. A próxima invocação apenas transmite o ID do agente:
Inline calls: send sources on every call
Named agent: bake once → invoke by ID, no sources
O que preencher
Abra save_agent.py. Ele tem uma tarefa (TODO 1).
Observe que as constantes são importadas diretamente de run_digest.py (sem duplicação):
from run_digest import BASE_AGENT, AGENTS_MD, SKILL_MD, GENERATE_PDF_PY
TODO 1:preencha a chamada agents.create():
agent = client.agents.create(
id="my-digest",
base_agent=BASE_AGENT,
description="Daily tech digest with editorial voice and PDF generation.",
base_environment={
"type": "remote",
"sources": [
{
"type": "inline",
"target": ".agents/AGENTS.md",
"content": AGENTS_MD,
},
{
"type": "inline",
"target": ".agents/skills/digest-pdf/SKILL.md",
"content": SKILL_MD,
},
{
"type": "inline",
"target": ".agents/skills/digest-pdf/scripts/generate_pdf.py",
"content": GENERATE_PDF_PY,
},
],
},
)
base_environment (não environment) é a principal diferença da chamada inline na etapa anterior: as fontes são armazenadas no lado do Google e montadas automaticamente em todas as invocações futuras. Execute uma vez, não em todas as execuções de resumo.
Verificar: salvar o agente
uv run python save_agent.py
Saved: my-digest
my-digest: Daily tech digest with editorial voice and PDF generation.
Invocar o agente salvo
Abra invoke_agent.py. Ele chama o agente salvo por ID sem fontes:
stream = client.interactions.create(
agent="my-digest",
input="",
stream=True,
environment="remote",
)
Compare isso com a chamada inline: agent=BASE_AGENT é substituído por "my-digest", e o bloco environment completo com três fontes inline é substituído por environment="remote". A configuração já está integrada ao lado do Google.
Verificar: invocar o agente salvo
uv run python invoke_agent.py
Você vai ver a mesma transmissão ao vivo da execução inline, mas a chamada não terá arquivos de origem. Após a execução, ENVIRONMENT_ID e INTERACTION_ID em .env são atualizados para que você possa continuar com refine_digest.py como antes.
[agent started]
[tool] read_file
[tool] write_file
[tool] run_code
I have successfully created today's tech news digest.
Done. environment_id=9a1c3e02-...
9. Limpeza
O sandbox expira automaticamente após 7 dias de inatividade. Não há servidores para parar. Nenhum contêiner para excluir.
Se você salvou uma configuração de agente, exclua-a:
uv run python delete_agent.py
10. Resumo
Você criou um agente gerenciado do zero, um conceito por vez. Confira o que cada exercício ensinou:
Exercício | Conceito | API Key |
Faça sua primeira chamada | Provisionar um sandbox real do Linux e transmitir os eventos ao vivo |
|
Personalizar o agente | Montar arquivos de configuração; manter IDs em |
|
Faça download do PDF | Baixar o PDF sem executar o agente novamente | API Gemini Files |
Continuar a conversa | Continuar a conversa sem buscar novamente na Web |
|
Persistir configuração do agente | Persistir a configuração do agente; invocar por ID, sem necessidade de fontes |
|
Padrões principais
- Uma chamada, um sandbox: o
interactions.create()processa toda a infraestrutura (sem contêineres para implantação, sem pacotes para instalação local). - Streaming progressivo: o
stream=Truetransforma uma caixa preta de 90 segundos em um feed publicado de chamadas de ferramentas e partes de texto. - Fontes in-line: monte
AGENTS.md,SKILL.mde scripts pré-criados no sandbox sem etapas de upload ou implantação. - Descoberta automática de arneses: os arquivos colocados em
.agents/são coletados automaticamente (não é necessário configurar o SDK). - Estado bidimensional:
environment_idrastreia arquivos e pacotes;previous_interaction_idrastreia o contexto da conversa; qualquer um pode ser transmitido de forma independente - Download de snapshot: o ambiente é um tar de sistema de arquivos completo, acessível pela API Gemini Files.
- Agentes nomeados: o
agents.create()incorpora a configuração de forma permanente. As chamadas futuras transmitem apenas o ID do agente eenvironment="remote", sem fontes.
ADK + Cloud Run x agentes gerenciados: a diferença em resumo
Capacidade | ADK + Cloud Run | Agentes gerenciados na API Gemini |
Provisionar um sandbox |
|
|
Definir ferramentas | Funções Python registradas no agente | Integrados: navegação na Web, execução de código, sistema de arquivos |
Instalar pacotes |
| O agente executa |
Transmitir eventos | Infraestrutura de SSE personalizada |
|
Continuar uma sessão | Banco de dados de sessão + injeção de contexto |
|
Arquivos de configuração | Codificado no agente ou injetado na inicialização | Montado via |
Infraestrutura para gerenciar | Contêiner, Cloud Run, IAM, secrets | Nenhum |