1. Introdução

Na primeira semana, perguntamos quem diz o que funciona. Na segunda semana, a pergunta foi quem decide o que vai ser executado em seguida. A terceira semana perguntou o que uma corrida deixa para trás. Esta semana, a conversa termina, e a questão é o que sobrevive a ela. Acontece que o tipo de coisa decide para onde ela vai.
O arquivo é onde o vale aparece quando algo deu errado. Uma torre que anota tudo e Vesper, o arquivista, na mesa do térreo. Sua lanterna se apaga à noite. Vá e pergunte.
Ela é uma boa companhia. Um mês depois, ela também fica feliz em conhecer você.
Um registro não é uma memória.
Essa frase é o laboratório inteiro. Você vai subir em quatro degraus, e cada degrau é um andar da torre:
degrau | o chão | o que ele lembra | o que o mantém |
1 | a mesa e o chão | esta visita |
|
2 | segundo andar, sua gaveta | este visitante | o prefixo |
3 | terceiro andar, a torre | o que foi dito | Memory Bank da Vertex AI |
4 | andar quatro, a temporada | todo o vale | BigQuery |
Cada degrau acima é porque algo caiu do degrau abaixo.

Você já conhece as cinco maneiras de esquecer do arquivista, porque todas elas já aconteceram com você em uma ligação de suporte:
o que ela diz | o que deu errado | |
~~1~~ | ~~Pode me dar essa referência de novo?~~ | ~~esqueci em uma conversa~~ — a terceira semana corrigiu isso |
~~2~~ | ~~Transferi a ligação. Comece do início.~~ | ~~o histórico morreu com o processo~~ — a terceira semana também corrigiu isso |
3 | Olá! Como posso ajudar? | para alguém com um caso em aberto do mês passado |
4 | Você pode descrever os danos? | ela olhou para a lanterna da última vez |
5 | Nunca vimos isso antes. | 31 pessoas perguntaram nesta temporada |
A linha três é desta semana. Ele falha de três maneiras diferentes: uma nova visita (capítulo 2), uma frase sem linha no papel (capítulo 3) e um arquivo que existe apenas dentro do processo (capítulo 4). Cada uma dessas maneiras é um capítulo. A quarta linha é com você: look() em archive/agent.py é onde ela lê uma marca em uma foto. A linha cinco é o capítulo 5 e é opcional.
Você não precisa das semanas de um a três. Um agente é um modelo com uma instrução e algumas ferramentas. Todo o resto se explica por si só.
Você vai escrever três linhas, e cada uma delas é um conceito de memória:
a linha | o que é |
| O estado é escrito por código, nunca pela conversa |
| um prefixo é uma vida útil |
| a política de recall — o arquivo não é lembrado |
Mais uma linha já está lá para você ler: a política de gravação, await ctx.add_events_to_memory(...). No capítulo 3, você lê o que ela faz antes de escrever a linha que a usa.
Os outros dois níveis não são edições: você constrói uma torre (um mecanismo de agente que hospeda o banco de memória) e o mesmo código se conecta a ela por conta própria, e você carrega um data warehouse (BigQuery), coloca um gráfico sobre ele e entrega ao mesmo agente duas consultas controladas: uma por significado e outra por conexão.
Todos os capítulos executam o mesmo loop, que é o que você vai usar nos seus próprios agentes: ler o código → escrever a linha → assistir na torre. Nada é executado primeiro, nada é reiniciado e nada é Ctrl+C: cada edição é capturada na próxima mensagem, e conectar a torre é uma linha em um arquivo que o Archive relê a cada solicitação. A torre é um desenho que se redesenha: ela lê os mesmos arquivos que você edita e tem três botões: 🌙 termina o dia, 🗓 inicia a próxima visita e 🔥 esquece você. Todo o resto é feito no código e no terminal.
Dois lugares, e eles nunca mudam de função: a guia 1 é o terminal, e a guia 2 é o arquivo. O ambiente de trabalho (adk web) aparece exatamente uma vez, no capítulo 1, para uma análise do estado bruto da sessão. Depois disso, você não precisa mais dele. Cada 👉 abaixo indica qual é. 👉💻 é a guia 1, 👉🖥 é a guia 2 e 👉🔬 é a bancada. 👉📖 é abrir um arquivo e ler, sem necessidade de mudanças, e 👉✏️ é o tipo de etapa que edita. Sempre que uma etapa pedir para você dizer algo à Vesper, a mensagem exata estará no bloco logo abaixo. Copie como está. Uma seção cujo cabeçalho termina em — somente leitura não tem nada para digitar, colar ou clicar: o código já está no repositório e em execução, impresso para você ler.
A frase na porta de Vesper é a que está na parte de cima. A frase desta semana é a linha de encerramento da quarta semana da temporada:
Fatos e preferências pertencem a lojas diferentes.
2. 🧰 Configuração
- O quê: aponte para um projeto ou cole uma chave, instale e prove que o conjunto de ferramentas está verde.
- Por quê? Nada é inicializado aqui. Cada servidor é iniciado logo antes da etapa que precisa dele. Assim, quando uma tela é aberta, você sabe qual comando é o proprietário dela.
- Como: um script que cria o projeto, um que instala e direciona você para a Vertex AI e um pré-lançamento que lê seu código e informa onde você está.
Tudo neste laboratório é executado no Cloud Shell. O Python, o uv e o gcloud já estão instalados lá, e o Gemini é acessado pela Vertex AI usando suas próprias credenciais. Não há chave de API em nenhum lugar deste laboratório, e não é necessário instalar nada no seu notebook.
Há uma coisa que este laboratório não pode oferecer: um projeto na nuvem do Google Cloud com faturamento ativado. A etapa 1 cria uma conta que pode pagar por isso. A etapa 4 transforma essa conta em um projeto ou retoma o projeto Agent Valley que você já criou na primeira, segunda ou terceira semana. Faça isso nessa ordem. Cada etapa depois da 4 lê o projeto que a etapa 4 define.
1 · Receba uma conta com faturamento (~1 min)
🌐 Faça isso antes de qualquer outra coisa. Faça login com uma Conta do Google que tenha o faturamento ativado. Qualquer uma dessas contas funciona. Se não tiver, inicie um teste sem custo financeiro. Ele oferece uma conta de faturamento, que é tudo o que a etapa 4 precisa.
2 · Abrir o Cloud Shell (~1 minuto)
🌐 Clique em Ativar o Cloud Shell na parte de cima do console do Google Cloud. É o ícone em forma de terminal no cabeçalho.

🌐 Clique em Abrir editor (o ícone de pasta aberta com um lápis). Isso abre o editor do Cloud Shell com um explorador de arquivos à esquerda. É ali que você trabalha sempre que uma etapa é marcada com 👉✏️.

🌐 Se for preciso autorizar em algum momento hoje, clique em Autorizar para continuar.
🌐 Abra um terminal no editor, que é a guia 1. Todas as etapas 👉💻 serão executadas lá, a menos que seja indicado o contrário. A guia 2 é o arquivo, e você a abre no capítulo 1, logo antes da etapa que precisa dela. Se o terminal ainda não estiver na parte de baixo da tela, abra-o com Visualizar → Terminal:

🌐 Verifique em qual conta você fez login. Ela precisa ser a mesma da etapa 1:
gcloud auth list
3 · Faça o laboratório (~1 min)
💻 Clone o repositório. Este é o repositório de arquivos, não o da semana 1, 2 ou 3:
cd ~
git clone https://github.com/cuppibla/agent-valley-archive
cd agent-valley-archive
4 · Crie seu projeto ou reutilize o de uma semana anterior (~2 min)
💻 Um script encontra sua conta de faturamento, cria um projeto nela e aponta o Cloud Shell para esse projeto. Se você fez a primeira, a segunda ou a terceira semana, o projeto Agent Valley será encontrado primeiro e vai ser oferecida a opção de reutilizá-lo. Diga sim, e não haverá um segundo projeto faturável para pensar:
cd ~/agent-valley-archive
./setup_project.sh
👀 Espere um ✓ para a conta de faturamento escolhida, um ✓ para o projeto criado ou reutilizado e um final como:
cd ~/agent-valley-archive
Project ready: agent-valley-4271
Next: ./setup_codelab.sh
agent-valley-4271 é o ID do projeto, que terá dígitos diferentes. Quatro coisas acontecem:
billing | usa a conta | |
project | procura um projeto do Agent Valley que você já tem (da semana 1, 2 ou 3) e oferece a opção de reutilizá-lo. Caso contrário, cria | |
seleciona | grava o ID em | |
waits | faz pesquisas até que o projeto possa veicular, por até dois minutos | |
🌐 O mesmo projeto agora está no console. O ID dele fica no card Informações do projeto no painel:

5 · Instalar e apontar para a Vertex AI (~3 min)
💻 Instale uv, exporte as três variáveis que enviam o ADK para a Vertex AI e execute a configuração:
cd ~/agent-valley-archive
curl -LsSf https://astral.sh/uv/install.sh | sh
source ~/.local/bin/env
export GOOGLE_GENAI_USE_VERTEXAI=TRUE
export GOOGLE_CLOUD_PROJECT=$(gcloud config get project)
export GOOGLE_CLOUD_LOCATION=global
./setup_codelab.sh
$(gcloud config get project) tem algo a ser retornado porque a etapa 4 o definiu. É por isso que a etapa 4 vem primeiro.
setup_codelab.sh é idempotente e pode ser executado novamente quantas vezes for necessário. Ele faz cinco coisas, em ordem:
api | lê a etapa 4 do projeto selecionado e ativa | |
uv env | O | |
site | executa | |
.env | grava as variáveis que o laboratório lê: | |
Verificação de modelo | faz uma chamada real para o Gemini, então um projeto ruim falha aqui no momento da configuração, não depois dentro de um capítulo | |
6 · Prove que é verde (~1 min)
💻 Execute a simulação. Cada marcação é uma sondagem real, não uma estimativa:
cd ~/agent-valley-archive
uv run python scripts/preflight.py
👀 A pré-verificação faz uma pergunta ao modelo para provar que suas credenciais funcionam, verifica se os pacotes do arquivo estão no lugar e lê seu código e imprime a barra de progresso desta semana:
cd ~/agent-valley-archive
desk ▢ the slip · write_down writes nothing chapter 1 · EDIT ONE
floor 1 ✓ the file · SqliteSessionService chapter 1, read only
floor 2 ▢ the drawer · CASE = "case" chapter 2 · EDIT TWO
floor 3 ✓ what was said · closing time files the day chapter 3, read only
floor 3 ▢ the asking · recall never looks chapter 3 · EDIT THREE
floor 3 ▢ the tower · InMemoryMemoryService chapter 4 · built, not edited
floor 3 ✓ the rules · USER_PREFERENCES, LANTERN_CONTEXT chapter 4, read only
Três já estão marcadas. São aqueles que você apenas lê. Três são linhas que você escreve, e uma é uma torre que você constrói. Execute a verificação prévia novamente a qualquer momento no laboratório para saber onde você está. Ela lê seus arquivos, não uma lista de verificação.
3. Session, State, SqliteSessionService
- O quê: escreva uma linha, inicie a bancada uma vez e veja o preenchimento do escorregador. Depois, faça o mesmo na torre. Em seguida, leia por que ela sobrevive à noite.
- Por quê? A primeira coisa a saber sobre a memória é que nada é lembrado por si só. Alguém escreve.
- Como: uma linha em
agent.py, sem mais mudanças.
EDITAR UM
👉📖 Abra archive/agent.py e encontre write_down. Leia até o 👉:
case = dict(tool_context.state.get(CASE, {}))
if case.get(field):
return {"already_written": {field: case[field]}}
case[field] = value
# 👉 EDIT ONE — chapter 1. She heard you. Nothing was written. Delete the
# "# " in front of the next line, then save — the slip is session state,
# and state is written by code, never by the conversation:
# tool_context.state[CASE] = case
return {"written": {field: value}}
A função cria o comprovante em um dicionário local e o retorna. Um dicionário local morre com a chamada. Execute o código como está, e o Vesper vai ouvir você perfeitamente: quatro chamadas write_down são disparadas, cada uma responde "written", e o estado da sessão permanece vazio, porque nada chegou a ele. Ela ouviu você. Nada foi escrito.
👉✏️ Ainda em archive/agent.py, dentro de write_down: exclua o # na frente de uma linha, o # e o espaço depois dele. Antes:
case[field] = value
# 👉 EDIT ONE — chapter 1. She heard you. Nothing was written. Delete the
# "# " in front of the next line, then save — the slip is session state,
# and state is written by code, never by the conversation:
# tool_context.state[CASE] = case
return {"written": {field: value}}
Depois:
case[field] = value
# 👉 EDIT ONE — chapter 1. She heard you. Nothing was written. Delete the
# "# " in front of the next line, then save — the slip is session state,
# and state is written by code, never by the conversation:
tool_context.state[CASE] = case
return {"written": {field: value}}
Salvar.
O comprovante é preenchido
👉💻 Inicie o ambiente de trabalho. Esta é a única vez que você vai abrir o laboratório. É a única janela que mostra o estado da sessão como o JSON bruto:
cd ~/agent-valley-archive
uv run adk web . --allow_origins="*"
👉🔬 Abra o ambiente de trabalho com Visualização da Web → Visualizar na porta 8000. O botão "Visualização da Web" é o ícone de um olho sobre uma janela no canto superior direito do Cloud Shell. Escolha arquivar e, antes de digitar qualquer coisa, clique em Estado no painel à esquerda.
👀 Vazio. Ninguém disse nada ainda.
👉🔬 Agora diga tudo isso em uma só mensagem:
Hi! My lantern keeps going out at night. My case number is k7f2, and there's a little q7 stamped on the base.
👀 Quatro chips write_down são disparados. Clique em um e leia o JSON: "written": {"no": "k7f2"}. Agora clique em Estado novamente.

case {"no": "k7f2", "item": "lantern", "mark": "q7",
"symptom": "keeps going out at night"}
👀 Vazio e depois cheio, dentro de uma mensagem. É com isso que ela se lembra, e isso não apareceu sozinho. Você escreveu a linha que a escreve. Esse é todo o mecanismo: uma função simples que grava em tool_context.state e uma instrução que diz para ela usar sempre que o visitante disser algo que se encaixe em uma linha do papel.
👉🔬 Pergunte a ela:
What's my case number?
👀 k7f2. Ela lê o que está escrito no papel. Sem o comando EDIT ONE, ela teria pedido isso a você: a primeira linha da lista de suporte, em uma conversa.
Os dois guardas são o comprovante sendo um formulário em papel: quatro linhas curtas, cada uma escrita uma vez. Elas são mais importantes do que parecem. Sem elas, o modelo descobre que pode despejar toda a conversa em symptom, e o capítulo 3, cujo objetivo é o slip não tem uma linha para isso, deixa de ser verdadeiro. O formato de uma loja é aplicado ou não pelo código que a grava.
Agora vá até a torre
👉💻 Você concluiu o laboratório. Deixe a bancada em execução ou feche a guia. O restante do laboratório está no arquivo. Abra uma segunda guia do terminal (guia 2: o arquivo):
cd ~/agent-valley-archive
bash valley.sh
👉🖥 Abra o arquivo com Visualização na Web → Alterar porta, digite 3440 e clique em Alterar e visualizar. 3440 não está na lista rápida da prévia da Web. O padrão é 8080. Portanto, você precisa definir manualmente uma vez. Pressione ▶ Iniciar e depois O arquivo. Você está na porta. Escolha quem veio perguntar (um nome e uma espécie) e entre.

👀 Um prédio. Vesper está na mesa do térreo, e é lá que você vai conversar. Acima dela: primeiro, segundo e terceiro andares, além de um sótão escuro. Os quatro degraus são os quatro andares. Seu familiar está no térreo, porque é até onde você subiu. A coluna ao lado do desenho mostra o que cada andar tem agora: as mesmas quatro lojas da tabela na introdução, na mesma ordem. Nada à direita é um botão.
👉🖥 Cole as mesmas quatro coisas na caixa abaixo da conversa (esta mensagem exata) e pressione "Enter":
Hi! My lantern keeps going out at night. My case number is k7f2, and there's a little q7 stamped on the base.

👀 Observe o espaço de trabalho. O papel se escreve, uma linha de cada vez, no desenho e por completo em o papel ao lado. Mesma ferramenta, mesmo estado: a torre está apenas desenhando o que write_down escreveu, e vai continuar fazendo isso pelo resto do laboratório.
Ela se lembra durante a noite — somente leitura
O que você escreveu e o que é
a linha | o que é | onde ele está |
| estado da sessão: escrito pelo código, lido pela instrução | a mesa · |
| o armazenamento de sessão: uma visita em um arquivo, não em um processo | primeiro andar · |
Esta barra alcança uma visita e sobrevive ao horário de fechamento. Ele não sobrevive à próxima visita.
4. Estado do usuário
- O quê: volte um mês depois, e o escorregão terá desaparecido. Cinco personagens que seguem você.
- Por quê: uma sessão é uma visita. A próxima visita é uma nova sessão e nunca viu a última.
- Como: cinco caracteres em
state.py.


👉🖥 Pressione 🗓 um mês depois. Essa é uma nova sessão para o mesmo visitante, assim como iniciar uma nova conversa na terceira semana.
Este é o arquivo. Como posso ajudar?
👉🖥 Olhe para a torre. O primeiro andar tem outro livro — esta visita. A gaveta do segundo andar está vazia. O papel no espaço de trabalho está em branco.

👀 Por quê: o encarte é gravado no estado da sessão, e uma sessão é esta visita. Mudar visitas, mudar sessões. Nada foi transferido porque nada foi informado. A última visita ainda está no arquivo (o primeiro livro do primeiro andar), mas o recibo foi escrito com uma chave que dura uma visita.
EDITAR DOIS
👉✏️ Abra archive/state.py. Encontre o 👉. Antes:
# 👉 EDIT TWO — chapter 2. Five characters. A key with no prefix lives for one
# visit; `user:` follows the visitor into every visit after this.
CASE = "case"
Depois:
CASE = "user:case"
Salvar. Sem reinicialização: o Archive reimporta seu código em todas as mensagens.
👉🖥 Cole as mesmas quatro coisas novamente: esta mensagem exata:
Hi! My lantern keeps going out at night. My case number is k7f2, and there's a little q7 stamped on the base.
👉🖥 Em seguida, pressione 🗓 um mês depois de novo, o mesmo botão de antes.

👀 A gaveta do segundo andar tem seu nome e os quatro campos dentro. O papel na mesa tem as mesmas quatro linhas, tirado da gaveta quando você entrou. Seu familiar subiu um andar. Mesma chave, todas as visitas, um valor: esse é o prefixo fazendo o trabalho dele.
O prefixo é um tempo de vida.
prefixo | quanto tempo ele dura | qual andar |
(nenhum) | esta visita | a mesa |
| cada visita feita por esse visitante | segundo andar, sua gaveta |
| para todos, para sempre | parte do quarto andar |
| esta curva apenas, nunca sobe as escadas | — |
Uma mesa, quatro gavetas. Este capítulo aborda um deles.
Ela conhece você agora
👉🖥 Esta visita é nova e você ainda não disse nada nela. Pergunte a ela:
What did I bring in last time?
👀 Tenho anotado que você trouxe uma lanterna, estojo k7f2. Ele está marcado com q7 e você mencionou que ele continua saindo à noite. Cada palavra que saiu da gaveta, não da conversa. Esta visita tem uma mensagem, e a mensagem não nomeou nada. Esse é o estado no nível do usuário fazendo o trabalho dele: uma chave user: está lá antes que o visitante diga uma palavra, em todas as visitas que ele faz.
A gaveta contém as quatro linhas do comprovante e nada mais. O que você diz que não tem uma linha no papel — o que você tentou, por que se importa, se quer um novo — não tem para onde ir e, um mês depois, desaparece. O gaveteiro cruza o mês. Uma frase não. O capítulo 3 é sobre isso.
O que você escreveu e o que é
a linha | o que é | onde ele está |
| um prefixo é um tempo de vida: a mesma chave, com escopo para o visitante em vez da visita | segundo andar · estado |
Esta barra alcança um visitante. A gaveta segue você, mas a conversa ainda não.
5. InMemoryMemoryService
- O quê: leia a linha que arquiva o dia, escreva a linha que pergunta e depois um horário de encerramento e uma pergunta.
- Por quê: o comprovante é um formulário. Um formulário tem as linhas que você deu a ele. As pessoas não falam em linhas, e arquivar o que elas disseram é apenas metade da lembrança.
- Como: leia
file, uma linha emrecalle depois uma 🌙, um 🗓 e uma pergunta.

O que ela faz a caminho de casa — somente leitura
O campo não é lembrado
Essa linha coloca o dia na prateleira. Ele não tira nada. Uma prateleira cheia de cards ajuda tanto quanto uma vazia se ninguém olhar. E, como o código é enviado, ninguém olha: recall, o nó que é executado antes do Vesper em todas as perguntas, não pergunta nada à torre. O armazenamento que você não consegue lembrar no momento certo não é memória, é um registro. A outra metade é o olhar, e você pode escrever sobre isso.
EDIÇÃO 3: a pergunta
👉📖 Em archive/agent.py, encontre recall, a função logo acima de file. É um nó de função simples que é executado antes do Vesper em todas as perguntas, não o modelo decidindo quando procurar. Isso significa que os momentos em que ele não encontra nada também são visíveis. Leia até o 👉:
if query.strip():
try:
# 👉 EDIT THREE — chapter 3. Filed is not remembered: the cards are on
# the shelf and nobody is looking at them. Delete the "# " in front
# of the next line, then save:
# found = await ctx.search_memory(query)
pass
except ValueError:
# no memory service wired on this runner — degrade, do not crash
pass
👉✏️ Ainda em archive/agent.py, dentro de recall: exclua o # na frente de uma linha, o # e o espaço depois dele. Antes:
try:
# 👉 EDIT THREE — chapter 3. Filed is not remembered: the cards are on
# the shelf and nobody is looking at them. Delete the "# " in front
# of the next line, then save:
# found = await ctx.search_memory(query)
pass
except ValueError:
Depois:
try:
# 👉 EDIT THREE — chapter 3. Filed is not remembered: the cards are on
# the shelf and nobody is looking at them. Delete the "# " in front
# of the next line, then save:
found = await ctx.search_memory(query)
pass
except ValueError:
Deixe o pass onde está. Ele não faz nada agora porque found já é None acima.
Salvar. Sem reinicialização.
Duas linhas, duas políticas, e você escreveu uma delas. A política de gravação decide o que é mantido e quando (horário de fechamento, o dia todo). A política de recall decide quando procurar e com o quê (todas as perguntas, a pergunta em si). O ADK oferece os verbos — add_events_to_memory, search_memory — e não entra na política. Essa é a divisão correta, e é por isso que a pergunta foi escrita por você.
Fecha às
👉🖥 Diga três coisas que não têm uma linha no comprovante. Uma mensagem ou três:
I read by it at night, so night is exactly when I need it.
I've tried hanging it higher. No change.
I don't want a new one — it was a gift.

👉🖥 Depois, pressione 🌙 Por hoje é só.

👀 Observe o espaço de trabalho. As três coisas que você disse saem do escorregador e flutuam para cima, pousando no terceiro andar. Em os cards ao lado da torre, eles são listados: um card para cada mensagem enviada, marcada como quote, suas frases palavra por palavra e neste processo acima delas. A luminária de mesa fica acesa até que eles aterrissem.
Um mês depois, ela sabe
👉🖥 Pressione 🗓 um mês depois e pergunte:
What have I already tried?
👀 Você tentou pendurar mais alto, mas não ajudou. Ela sabe. O comprovante não tem uma linha para isso e nunca teve, então a gaveta não poderia ter respondido. recall encontrou o cartão, escreveu em ctx.state["recalled"] e a instrução dela diz isso. Uma linha é a diferença.
E tudo isso está na cabeça dela
Confira os cards ao lado da torre: neste processo. No momento, a memória é InMemoryMemoryService, um dicionário dentro de bash valley.sh, e dura exatamente o mesmo tempo que esse processo. Feche a torre hoje à noite e abra amanhã: os livros estão no primeiro andar, a gaveta está no segundo andar e o terceiro andar está escuro. O caso foi mantido no arquivo. O que você disse estava no processo, e o processo acabou.
Persistência não é memória.
Há duas coisas erradas com o terceiro andar: ele está em processo e é uma citação, não um fato. O próximo capítulo corrige os dois problemas sem código algum.
O que você lê, o que você escreve e o que é
a linha | o que é | onde ele está |
| a política de gravação: um dia inteiro, no horário de fechamento | terceiro andar · o serviço de memória |
| a política de recall — todas as perguntas, antes de responder |
|
Essa etapa alcança o que foi dito e o mantém em um dicionário dentro de um processo, com suas próprias palavras. As duas partes estão erradas, e o próximo capítulo corrige ambas sem código algum.
6. MemoryBank
- O que: um script cria um Memory Bank. As duas linhas que você já tem começam a escrever fatos nele e a lê-los de volta.
- Por quê: um serviço de memória é um serviço. O local em que o arquivo fica é uma decisão de implantação, não do agente. Você pode mudar isso sem afetar o agente.
- Como: execute
make_tower.py, diga três frases, pressione 🌙, pressione 🗓 e faça uma pergunta. Depois, uma análise somente leitura da gravação e da leitura.
Construa a torre
O terceiro andar do capítulo 3 era um dicionário Python dentro de bash valley.sh. O Memory Bank é a versão gerenciada desse recurso: ele fica em uma instância do Agent Engine no seu projeto, mantém fatos destilados do dia em vez das suas frases e os encontra por significado em vez de palavras compartilhadas. Não é necessário implantar o Vesper em um Agent Engine para usá-lo. Uma instância sem nada implantado ainda hospeda um Memory Bank, e é isso que o script cria: uma torre sem ninguém morando nela, cuja única função é guardar os cards.
👉💻 Na guia 1 (cerca de um minuto):
cd ~/agent-valley-archive
uv run python scripts/make_tower.py
👀 O que esperar:
building the tower in YOUR_PROJECT / us-central1 — about a minute...
built, with the two topics in archive/topics.py configured on it.
resource: projects/.../locations/us-central1/reasoningEngines/6792...
AGENT_ENGINE written to .env
Next — nothing to restart. The Archive reads .env on every message:
look at floor three — under the cards it now says Memory Bank.
(adk web, if you use it: --memory_service_uri "agentengine://projects/.../reasoningEngines/6792...")
Uma chamada de SDK, agent_engines.create(), e uma linha gravada em .env. O arquivo é lido novamente pelo arquivo em cada solicitação, então não é necessário reiniciar nada.
Veja como o vídeo funciona
👉🖥 Observe o terceiro andar: a torre se redesenha sozinha em alguns segundos. Em os cards, agora aparece Memory Bank, e a prateleira está vazia: as três citações do capítulo 3 estavam no processo, e este não é o processo. Diga as três frases de novo, uma mensagem ou três:
I read by it at night, so night is exactly when I need it.
I've tried hanging it higher. No change.
I don't want a new one — it was a gift.
👉🖥 Pressione 🌙 por hoje é só. O tempo de fechamento agora é de cerca de oito segundos. A torre está extraindo. Depois, olhe para o terceiro andar.

👀 Os cards não são suas frases. Elas dizem coisas como Uso minha lanterna para ler à noite, que é quando ela fica apagando e Já tentei pendurar a lanterna mais alto, cada uma marcada fact com uma data. Destilação. O que foi inserido foi uma conversa. O que saiu são fatos.
👉🖥 Pressione 🗓 um mês depois (uma nova visita, então nada do que você acabou de dizer está mais na conversa) e faça esta pergunta, que não compartilha uma palavra com os cards:
Should I just get a different lamp?
👀 Como foi um presente, você mencionou que não quer substituir a lanterna e já tentou pendurá-la mais alto. Cada palavra veio do cartão, e só ele poderia ter dito a ela: esta visita tem uma mensagem. Pesquisa por similaridade. A torre corresponde ao significado, não às palavras. A pergunta diz lâmpada e diferente, e o card diz lanterna e substituir. E ele está fora do processo agora: desligue a torre hoje à noite e os cards estarão lá amanhã, porque eles ficam no Agent Engine, não em bash valley.sh.
Gravação e leitura (somente leitura)
O direito de ser esquecido

👉🖥 Clique em 🔥 esqueça-me, abaixo da caixa de mensagem.
👀 Três andares ficam escuros e um não:
o que ele contém | depois de 🔥 | |
terceiro andar, os cards | o que ela lembrou: os fatos que o Memory Bank extraiu das suas visitas | desapareceu — |
segundo andar, a gaveta |
| apagados |
o espaço de trabalho, o escorregão | a cópia do caso desta visita | apagados |
primeiro andar, os livros | as visitas em si: uma sessão no | inalterado: a contagem não muda |
Os livros são o registro: que uma visita aconteceu, em qual dia e o que foi dito nela. Os cards e a gaveta são a memória: o que ela fez dessas visitas e leva para a próxima. Um pedido para ser esquecido se refere à memória: os fatos derivados de uma pessoa e o estado que a acompanha. A decisão de manter ou não o registro de uma visita é separada, tomada por motivos diferentes (uma trilha de auditoria, um histórico de suporte). Este laboratório mantém o registro de propósito para que você possa ver os dois se separarem: o registro e a memória não são a mesma coisa, e esquecer um não afeta o outro. Essa é a frase na porta de Vesper, vista do outro lado.
A abstração de memória do ADK tem add_events_to_memory e search_memory. Não há exclusão. O esquecimento é uma ação de governança, não do agente. Portanto, ele fica no aplicativo — archive/tower.py, memories.delete no cliente bruto — onde o modelo não pode alcançar por acidente. Se um agente pode esquecer é algo que você projeta, assim como se ele pode lembrar.
O que você criou e leu, e o que é
a coisa | o que é | onde ele está |
| o serviço de memória, como um serviço: uma decisão de implantação, fora do agente | Memory Bank da Vertex AI em um Agent Engine |
| o mesmo período |
|
| o que pode ser mantido, decidido no momento da gravação, não no comando |
|
🔥 → | O esquecimento é uma ação do aplicativo. A API Memory do ADK não tem exclusão. |
|
Esta etapa alcança o que foi dito. Um dia se passa, um fato é revelado, destilado ao que os tópicos permitem, e o livro no primeiro andar nunca se moveu.
7. GraphRAG
Opcional.
- O quê: um script carrega o passado do vale no BigQuery, gera embeddings dentro do data warehouse e cria um gráfico sobre as tabelas sem mover uma linha. Em seguida, duas perguntas para o Vesper, que tem duas consultas controladas: uma para o que soa parecido e outra para o que está conectado.
- Por quê: "parece igual" não é o mesmo que "está conectado". Um vetor encontra onde procurar, um gráfico encontra o que está anexado, e a resposta precisa carregar o caminho percorrido.
- Como —
bash scripts/season.sh, uma vez. Todo o resto neste capítulo é somente leitura.
A torre de Vesper é limitada a você — (app_name, user_id) — por construção. As visitas de outras pessoas não são a memória dela, e pesquisar mais não mudaria isso. Eles pertencem ao vale, que os guarda em um armazém. Nesta temporada, 31 visitantes vieram por causa de uma lanterna q7 que apagou à noite, e um deles encontrou a causa. Este capítulo carrega esse data warehouse e entrega duas consultas fixas a ele.
Graph RAG
A RAG é recuperar e gerar: encontre os registros certos, entregue-os ao modelo e deixe que ele responda com base neles. A RAG simples faz a recuperação por semelhança: incorpora a pergunta e extrai os registros mais próximos. Isso encontra coisas que parecem a pergunta, e é onde a torre do capítulo 4 parou. A RAG de grafo adiciona uma segunda etapa de recuperação que segue arestas (chaves que um data warehouse já tem) de qualquer semelhança encontrada para o que estiver anexado a ela. As duas etapas respondem a perguntas diferentes, e este capítulo faz você perguntar as duas:
etapa | a pergunta que ele responde | como | neste capítulo |
similaridade | Onde devo procurar? | incorporar a pergunta, |
|
travessia | o que está conectado a isso? |
|
|
geração | O que devo dizer ao visitante? | o modelo, com o caminho como citação | a resposta dela |
Executar
A temporada é enviada como CSVs simples em season/ (visitantes, itens, perguntas, correções, temporadas), da mesma forma que um sistema de suporte os exportaria. Um script leva todos eles até o armazém, e é a única coisa que você executa neste capítulo.
👉💻 Na guia 1 (cerca de três minutos; ela imprime cada etapa à medida que avança e para na primeira que falha):
cd ~/agent-valley-archive
bash scripts/season.sh
👀 Quando ele termina, o quarto andar da torre acende, e a legenda ao lado diz aberto.
O que ele criou: somente leitura
Como ela lê — somente leitura
Pergunte a ela
👉🖥 O quarto andar está aberto na torre. Pergunte a ela da mesma forma que um visitante faria:
Has anyone else had a q7 lantern go out at night?

👀 Ela responde: outras 31 pessoas... a maioria disse que a chama ficou baixa e se apagou depois de uma hora... A lontra Marlow descobriu que os pavios estavam muito rasos, e a última linha da resposta dela é o caminho. Esta é a resposta dela. Leia, não envie de volta:
mark q7 → 31 visits this season → 10 different things said → the wicks in the q7 batch were dipped too shallow — they drown in the oil and starve in an hour
O caminho é a citação. Cada salto é uma aresta no gráfico, e uma aresta é uma chave. Assim, qualquer pessoa pode percorrer o caminho novamente e chegar ao mesmo número. Uma pontuação de similaridade não pode ser percorrida novamente por ninguém. Se ela disser, logo antes do caminho, que as linhas voltaram por três junções porque o projeto não tem uma reserva de gráfico, essa é a edição do seu projeto recusando GRAPH_TABLE. As linhas e o caminho são os mesmos.
👉🖥 Agora deixe a marca de fora — envie isto:
Has anyone else had a lantern that keeps dying once the sun is down?
👀 Ela chega ao mesmo 31 e ao mesmo caminho. O que mudou foi o caminho: season_search correu primeiro, encontrou cinco visitantes que soam de forma semelhante (cada um carregando q7), pegou essa marca e só então caminhou. Semelhante não é conectado, mas sim onde procurar.
O que foi carregado e o que é
a coisa | o que é | onde ele está |
| um depósito: colunas com nomes e tipos |
|
| a etapa de similaridade: onde procurar |
|
| a etapa de travessia: o que está conectado; as tabelas se tornam nós e setas |
|
| o único passeio que ela pode fazer; o caminho é a citação |
|
Algumas dezenas de visitantes não são motivo para comprar um armazém. O que este capítulo ensina é o formato da consulta, não a escala. Aumente esse gráfico mil vezes e o MATCH não vai mudar em um caractere.
8. Fechar
Três linhas, uma torre, um armazém: quatro andares. Nada foi reiniciado.
o degrau | o que você fez | o que foi comprado |
UM |
| um deslize que existe: o estado é escrito por código |
DOIS |
| uma gaveta que segue o visitante |
o envio |
| o que foi dito, mantido |
TRÊS |
| o que foi mantido, pedido — o arquivo não é lembrado |
a torre |
| uma torre que destila e sobrevive à noite |
as regras |
| apenas o que deve ser mantido |
a temporada |
| as visitas de todos os outros, por significado e por conexão |
O que cada peça substituiu
ADK 2 | o que você escreveria em vez disso | o que isso custa para você |
| um dict ao lado do loop de chat, gravado em disco por você | o modelo não consegue ler, e você escreve o currículo e o bloqueio |
o prefixo | uma tabela de usuários e uma junção em cada turno | decidir onde uma chave pertence, sempre |
| um cron que despeja transcrições e o modelo decidindo quando procurar | ele despeja, nada destila, e você nunca vê as vezes em que não parecia |
| um repositório de vetores, um comando de extração, um job de consolidação e "não se lembre de curiosidades" no comando | três serviços, e a regra é válida até que o modelo entenda o contrário. |
| exportar, incorporar em outro lugar, um banco de dados de grafo, um job de sincronização e o modelo gravando SQL | os dados saem do data warehouse para serem compreendidos, e você descobre quais junções foram estimadas quando um cliente faz |
Três perguntas, pare no primeiro "sim"
- Isso vai importar amanhã? Não → não manter nada. Ela vive e morre na conversa.
- Uma função pode verificar isso? Sim → a gaveta. O código escreve, cada turno lê e nenhuma frase pode mudar.
- Caso contrário → a torre. Destilado do que foi dito, pesquisado quando solicitado, revisado pelo que é dito em seguida.
A frase
Um registro não é uma memória. Uma memória é um registro mais duas decisões: o que manter e quando procurar. O tipo de coisa que ela é decide em qual andar ela fica.
Fatos e preferências pertencem a lojas diferentes.
👀 Todos os andares estão iluminados. Seu familiar fica na parte de cima. O carimbo do Arquivo está no passaporte, e a quinta semana abre o Mercado Noturno, onde Nix comanda o palco em tempo real, e tudo o que a torre sabe acompanha você.