TL;DR: Este artigo mostra como construir agentes de IA que lembram de tudo por semanas ou meses, utilizando microVMs do Foundry como workspace persistente por projeto — sem precisar de banco de dados externo. A Microsoft resolve o problema do loop stateless armazenando o estado no servidor e reconstruindo o contexto a cada ativação. Ideal para workflows longos como resposta a RFP, onde o agente precisa coordenar tarefas que se estendem por dias e envolver pessoas em diferentes momentos. A escolha entre hosted e local depende de governança de dados, escala e simplicidade.
Por que isso importa?
Seu agente de IA simplesmente esqueceu tudo. De novo.
Se você já construiu agentes que precisam acompanhar trabalho ao longo de dias ou semanas — e não apenas conversas únicas — já esbarrou nessa parede: o loop do agente é stateless. Cada turno raciocina sobre o que recebe e depois esquece. Mas workflows reais de negócio não cabem em uma única conversa.
Este post mostra como construir agentes que lembram, usando as sandbox VMs por projeto do Foundry para manter estado por semanas de trabalho descontínuo. Sem necessidade de banco de dados externo.
O que você vai aprender: - Como persistir estado do agente em microVMs do Foundry - Padrões de session handling para workflows longos - Quando escolher arquitetura hosted vs. local
Glossário rápido:
- MAF (Microsoft Agent Framework): O framework para construir agentes de IA que podem usar ferramentas e orquestrar sub-agentes
- Foundry: A plataforma da Microsoft para hospedar e executar agentes de IA em produção
- MicroVM: Uma máquina virtual leve e isolada que o Foundry provisiona por projeto — pense nela como o workspace persistente do seu agente
- MCP (Model Context Protocol): Um padrão para conectar modelos de IA a ferramentas e fontes de dados externas
- WorkIQ: Componente customizado que expõe capacidades do M365 como endpoints MCP
Qual é o workflow de negócio e o desafio central?
O workflow de referência aqui é a orquestração de resposta a SOW (Statement of Work). Um Owner de SOW inicia uma resposta a RFP e o agente executa todo o engajamento através do Microsoft 365: ele encontra a RFP, redige um project charter, extrai owners e tarefas da reunião de kickoff, aloca o trabalho, distribui os kickoff briefs (após aprovação do owner) e então monitora e-mail e chat para rastrear cada tarefa até a conclusão, redigindo lembretes para os atrasados.
O problema é que isso não é uma conversa única — acontece ao longo de dias ou semanas, com pessoas contribuindo em seu próprio ritmo e o agente acordando intermitentemente para avançar o trabalho. Esse é o desafio central: um loop de agente é stateless — cada turno raciocina sobre o que recebe e esquece — mas o processo exige continuidade através de longos intervalos descontínuos. Algo precisa lembrar de cada tarefa pendente, cada submissão e cada próximo passo, e reconstruir esse quadro perfeitamente a cada vez que o loop acorda.
Como a solução aborda o problema?
Em vez de empurrar esse fardo para o cliente, deixamos que o agente hosted do Foundry carregue seu próprio estado em uma sandbox VM por projeto (microVM). A ideia em alto nível:
- Estado vive na sandbox, não no cliente. Cada projeto ganha sua própria microVM do Foundry com um $HOME durável. O agente escreve tudo que precisa lá — o charter, um log de projeto estruturado com tarefas e status, cursores de canal, um rastro de atividade.
- Cada ativação reconstrói o mundo. O loop não depende de um ponteiro in-memory solto. Em cada turno ele lê seus próprios arquivos de estado de volta para o contexto, reconstrói o status completo do engajamento, avança exatamente a fase que deve e escreve o estado atualizado de volta. Quer o humano retorne em cinco minutos ou cinco dias, o agente recria uma imagem autoritativa a partir do disco.
- O cliente permanece enxuto. Como a substância fica no servidor, o desktop app só precisa lembrar qual sandbox pertence a qual projeto — um session id — e nada sensível jamais chega ao endpoint.
Isso transforma um loop stateless em um workflow stateful de longa duração, sem banco de dados externo e sem estacionar dados de negócio na máquina local.
Qual é a arquitetura e design?
O sistema tem dois componentes:
- O Foundry Hosted Agent é o cérebro: construído usando o Microsoft Agent Framework (MAF), raciocina com modelos OpenAI no Foundry, acessa o Microsoft 365 através de um único Foundry Toolbox que expõe os endpoints MCP do WorkIQ, e é dono do loop do agente, skills, memória, sessão, estado e orquestração — chamando o M365 como o usuário logado via Foundry OAuth Identity Passthrough, para nunca segurar um token de usuário.
O workflow é construído como uma orchestrator skill (sow-response) com sub-skills especialistas (RFP search, charter draft, kickoff extract, task allocate, reply poll); o orchestrator inspeciona o estado, decide a fase atual e delega para o sub-agente certo.
Cada skill é um MAF Agent aquecido construído uma vez na inicialização, todos compartilhando um único FoundryChatClient — então as invocações de sub-agente raciocinam através do mesmo model client. O design baseado em skills é o que o torna extensível: uma skill é apenas uma pasta com um SKILL.md; adicione uma nova e o loader constrói um agente para ela e começa a rotear para ela por sua descrição — um processo de negócio completamente novo, sem mudanças no framework.
O agente roda localmente durante o desenvolvimento e é deployado como um Foundry hosted agent em produção, código idêntico de qualquer forma.
- O segundo componente, o Desktop App, é uma camada deliberadamente enxuta: ele autentica o usuário, anexa o bearer à chamada, lembra um session id por projeto, faz polling em background para que o workflow avance sem supervisão e renderiza o resultado — mantendo apenas session pointers e um cache não sensível de UI. Os dois conversam através da OpenAI Responses API. O MAF fornece o loop em si — o raciocínio por turno, o dispatch de tools via MCP e a orquestração de sub-agentes que leva cada fase à conclusão.
Como funciona o gerenciamento de sessão e estado no código?
Na primeira interação de um projeto, o Desktop client pede ao Foundry para criar uma sessão. O agent session id retornado é o handle para a microVM distinta provisionada para aquele projeto, e o cliente persiste imediatamente:
def _ensure_session_sdk(self, project_dict, isolation_key) -> str:
# project_dict: registro persistido deste projeto (label, ids, etc.).
# isolation_key: uma chave ESTÁVEL de propriedade do cliente — passamos o project_id — que
# diz ao Foundry "todos os turnos com esta chave pertencem à mesma sessão/microVM".
# Se já criamos uma sessão para este projeto em execução anterior, reutilizamos.
# session_id é o handle para a sandbox VM durável do projeto.
sid = project_dict.get("session_id")
if sid:
return sid # sandbox já existe — reatachar depois
# Primeira interação para este projeto: pedir Foundry para provisionar nova sessão.
# create_session cria uma microVM dedicada cujo $HOME conterá TODO
# o estado deste projeto. A plataforma GERA o id; nós não escolhemos.
session = self._get_project_client().beta.agents.create_session(
agent_name=agent_name, # qual agente deployado vincular
isolation_key=isolation_key, # = project_id, fixa uma sessão por projeto
)
sid = session.agent_session_id # o handle da sandbox gerado pelo servidor
# Persistir o id ANTES da primeira requisição sair, para que uma falha no meio do turno
# nunca deixe o projeto sem ponteiro para sua sandbox.
project_dict["session_id"] = sid
_save_projects(self._projects_data) # escreve o arquivo local de ponteiros
return sid
A partir daí, toda requisição incorpora esse session id (reatachando a sandbox) através da superfície Responses API — responses.create(stream=True, ...) — mais um previous_response_id para encadear o transcript:
# oc: o Responses client compatível com OpenAI para o agente hosted. É obtido
# do Foundry project client (AIProjectClient.get_openai_client(...)) e
# é o que efetivamente coloca a requisição no fio para o endpoint /responses do agente.
oc = self._get_openai_client()
# Monta o payload para um turno contra a superfície OpenAI Responses API.
create_kwargs = {
"input": prompt, # a mensagem do usuário/automática para este turno
"stream": True, # stream de eventos SSE conforme acontecem
# agent_session_id é o campo crítico: diz ao Foundry para REATACHAR
# a microVM existente deste projeto (e seu estado $HOME) para este turno,
# em vez de começar do zero. É isso que torna o loop stateful.
"extra_body": {"agent_session_id": _session_id},
}
# previous_response_id encadeia o transcript in-memory do turno anterior para que o
# modelo tenha contexto conversacional recente. É best-effort (o transcript pode
# expirar); o estado durável sempre vem do $HOME, não deste id.
if previous_response_id:
create_kwargs["previous_response_id"] = previous_response_id
# Dispara o turno. O agente hosted monta a sandbox correta, executa o loop do agente,
# e faz stream de eventos (deltas de texto, tool calls, completion) de volta ao cliente.
stream = oc.responses.create(**create_kwargs)
O agent_session_id fixa a sandbox durável (sobrevive a restarts e idle); o previous_response_id encadeia o transcript in-memory (best-effort). Dentro da sandbox, o agente reidrata e atualiza seu próprio estado através de system state tools expostas junto com o Toolbox — principalmente uma operação JSON-patch para que cada skill atualize apenas as chaves que possui:
@tool # exposto ao agente como tool chamável, junto com as ferramentas MCP do WorkIQ
def state_patch_json(path: str, patch: dict[str, Any]) -> str:
"""Faz merge de chaves top-level em um arquivo JSON sem sobrescrever campos
não relacionados. Usado para toda atualização do project_log.
path: um caminho RELATIVO ao $HOME da sandbox (ex.: "project_log.json").
state.patch_json valida que fica dentro de $HOME — sem escape.
patch: as chaves para fazer merge. Apenas essas chaves são tocadas; todo o resto
no arquivo é preservado. Isso permite que uma skill atualize, por exemplo,
o status de uma tarefa sem sobrescrever campos de outra skill.
"""
return state.patch_json(path, patch) # read-modify-write, atômico
A garantia de "reconstruir o mundo a cada ativação" repousa nessas leituras e patches contra o $HOME.
Como obter telemetria de forma simples?
Como o agente roda no Foundry com MAF, conectar o projeto Foundry ao Application Insights te dá todo o loop do agente como traces OpenTelemetry, turnkey — chamadas de modelo, cada tools/call MCP, cada invocação de sub-agente, cada patch de estado. A única customização é um span processor que carimba o project.id em cada span na inicialização; a plataforma é dona do exporter. Você vê o loop completo de várias semanas de ponta a ponta sem construir pipeline de logging sob medida.
E a alternativa: rodar o loop no cliente?
A outra opção é rodar o loop do agente e seu estado na máquina local. Os trade-offs:
- Residência de dados. Hosted: substância sensível fica em sandbox governado pelo Azure; o endpoint mantém apenas session ids — ideal onde compliance limita dados de negócio em dispositivos locais. Local: charter, artefatos e log de tarefas vivem no laptop, expandindo a superfície de DLP e vulnerabilidade.
- Escala e compartilhamento. Hosted: sandboxes por projeto provisionadas pela plataforma e qualquer colega logado pode se conectar. Local: limitado à máquina de um usuário; colaboração multi-usuário é complicada.
- Simplicidade para um único usuário. Local: sem plumber de sessão, sem latência de cold-start, totalmente offline — genuinamente mais simples para um power-user em um ambiente permissivo. Hosted: um pouco mais de configuração (session minting, resume handling) em troca de governança e escala.
Quando escolher cada um: opte por hosted para times, portfolios multi-projeto ou ambientes regulados; mantenha local para um power-user em uma máquina permissiva que valoriza zero roundtrips.
Veja em ação

Como começar?
Pronto para construir seu próprio agente stateful? Aqui estão três caminhos:
🚀 Explore o código: O código-fonte completo do Charter Agent está no GitHub: Charter-Agent-Repo — clone, rode localmente e adapte os padrões para seu workflow.
📚 Aprenda os fundamentos:
- Microsoft Agent Framework — entenda o loop do agente e a arquitetura de skills
- Foundry hosted agents quickstart — faça deploy do seu primeiro agente em minutos
- Working with Sessions in Foundry Hosted Agents
- Foundry Toolbox overview — conecte seu agente ao M365 e outros serviços
Perguntas Frequentes
-
Qual é o principal problema que este artigo resolve?
O loop tradicional de agentes de IA é stateless: a cada interação o modelo raciocina sobre o que recebe e depois esquece. Isso inviabiliza workflows que se estendem por dias ou semanas, como resposta a RFP, onde o agente precisa coordenar tarefas ao longo do tempo com múltiplas interrupções. -
Como a solução com microVM evita a necessidade de um banco de dados externo?
Cada projeto ganha sua própria microVM no Foundry com um diretório $HOME durável. O agente escreve todo o estado (charter, log de tarefas, cursores de canal) diretamente em arquivos no sandbox. A cada ativação, ele lê esses arquivos de volta para o contexto, avança a fase devida e atualiza o estado — sem depender de um banco relacional ou NoSQL externo. -
Quais são os trade-offs entre rodar o agente no servidor (hosted) vs. localmente?
Hosted: dados sensíveis ficam em sandbox Azure-governado, suporte a múltiplos usuários e escalabilidade, mas exige mais configuração (session minting, resume handling). Local: simplicidade para um power-user, sem latência de rede e funcionamento offline, mas os dados residem no laptop, ampliando a superfície de DLP e dificultando colaboração. -
Como a telemetria é tratada nessa arquitetura?
Conectando o projeto Foundry ao Application Insights, todo o loop do agente é exposto como traces OpenTelemetry de forma turnkey — incluindo chamadas de modelo, invocações de ferramentas MCP, execuções de sub-agentes e patches de estado. A única configuração customizada é um span processor que adiciona o project.id a cada span.
Artigo originalmente publicado por srikantan em Azure Updates - Latest from Azure Charts.