Como Construir Agentes de IA com Strands SDK, SageMaker AI e MLflow

Por que usar modelos no SageMaker AI em vez de serviços gerenciados?

Empresas que constroem agentes de IA frequentemente precisam de mais do que os serviços gerenciados de modelos de fundação (FM — Foundation Model) conseguem oferecer. Requisitos como controle preciso de desempenho, otimização de custos em escala, conformidade regulatória, residência de dados e configurações de rede que se integrem às arquiteturas de segurança existentes são comuns em ambientes corporativos.

O Amazon SageMaker AI atende a esses requisitos ao dar às organizações controle sobre recursos de computação, comportamento de escalabilidade e posicionamento de infraestrutura — tudo isso aproveitando a camada operacional gerenciada da AWS. Os modelos implantados via SageMaker AI podem alimentar agentes de IA, lidar com cargas de trabalho conversacionais e se integrar com frameworks de orquestração, assim como os FMs disponíveis no Amazon Bedrock. A diferença fundamental é que a organização mantém o controle arquitetural sobre como e onde a inferência acontece.

Neste artigo, a AWS demonstra como construir agentes de IA usando o Strands Agents SDK com modelos implantados em endpoints do SageMaker AI. O tutorial cobre o deploy de modelos de fundação via SageMaker JumpStart, a integração com o Strands Agents, a configuração de observabilidade com MLflow e a implementação de testes A/B entre variantes de modelos.

Visão geral das ferramentas envolvidas

O Strands Agents SDK é um SDK de código aberto que adota uma abordagem orientada a modelos para construir e executar agentes de IA com poucas linhas de código. Ele escala desde casos de uso simples até os mais complexos, e do desenvolvimento local até o deploy em produção.

O Amazon SageMaker JumpStart é um hub de aprendizado de máquina (ML — Machine Learning) que acelera a jornada de ML das equipes. Com ele, é possível avaliar, comparar e selecionar FMs rapidamente com base em métricas de qualidade e responsabilidade predefinidas.

O SageMaker AI MLflow é uma funcionalidade gerenciada que simplifica o ciclo de vida de ML por meio de rastreamento de experimentos, versionamento de modelos e gerenciamento de deploy.

Um Jupyter Notebook com o código completo está disponível no repositório no GitHub.

Construindo o primeiro agente com Strands

Um agente Strands combina um modelo, um prompt de sistema e um conjunto de ferramentas. O SDK oferece suporte a diversos provedores de modelos, incluindo o Amazon SageMaker AI, e disponibiliza ferramentas comuns por meio do pacote strands-agent-tools. O trecho de código abaixo mostra como criar um primeiro agente usando o Strands Agents SDK com o modelo Claude 4.5 Sonnet via Amazon Bedrock:

model = BedrockModel(
    model_id="us.anthropic.claude-sonnet-4-5-20250929-v1:0"
)

agent = Agent(model=model, tools=[http_request])
agent("Where is the international space station now?")

Uma lista de perfis de inferência disponíveis pode ser consultada no Guia do Usuário do Amazon Bedrock. Exemplos detalhados de agentes construídos com o Strands Agents SDK estão disponíveis no repositório de exemplos no GitHub.

Passo a passo: construindo um agente Strands com SageMaker AI

O Strands Agents SDK implementa um provedor nativo para o SageMaker AI, permitindo executar agentes contra modelos implantados em endpoints de inferência do SageMaker. Isso inclui tanto modelos pré-treinados do SageMaker JumpStart quanto modelos customizados com fine-tuning. O modelo utilizado deve suportar APIs de completions de chat compatíveis com OpenAI. O tutorial usa os modelos Qwen3 4B e Qwen3 8B disponíveis no SageMaker JumpStart.

Pré-requisitos

  • Uma conta AWS com acesso ao Amazon Bedrock e ao Amazon SageMaker AI
  • Uma role com permissões para SageMaker AI, Amazon Bedrock, SageMaker AI Serverless MLflow, Amazon S3 e SageMaker JumpStart
  • Um Jupyter Notebook rodando localmente ou no SageMaker AI Studio

Passo 1: Instalar os pacotes necessários

%%writefile requirements.txt
strands-agents>=1.9.1
strands-agents-tools>=0.2.8
mlflow>=3.4.0
strands-agents[sagemaker]
mlflow-sagemaker>=1.5.11

pip install -r requirements.txt

Passo 2: Fazer o deploy do modelo como endpoint no SageMaker AI

# Deploy initial endpoint with Qwen-4B
import sagemaker
import boto3
from boto3.session import Session
from sagemaker.jumpstart.model import JumpStartModel

boto_session = Session()
sts = boto3.client('sts')
account_id = sts.get_caller_identity().get("Account")
region = boto_session.region_name

ENDPOINT_NAME = INITIAL_CONFIG_NAME = "llm-qwen-endpoint-sagemaker"

model_a = JumpStartModel(
    model_id="huggingface-reasoning-qwen3-4b",
    model_version="1.0.0",
    name="qwen3-4b-model"
)

predictor_a = model_a.deploy(
    initial_instance_count=1,
    instance_type="ml.g5.2xlarge",
    endpoint_name=ENDPOINT_NAME
)

Passo 3: Usar o modelo implantado com o agente Strands

from strands.models.sagemaker import SageMakerAIModel
from strands import Agent, tool
from strands_tools import http_request, calculator

model_sagemaker = SageMakerAIModel(
    endpoint_config={
        "endpoint_name": ENDPOINT_NAME,
        "region_name": region
    },
    payload_config={
        "max_tokens": 2048,
        "temperature": 0.2,
        "stream": True,
    }
)

agent = Agent(model=model_sagemaker, tools=[http_request])
agent("Where is the international space station now? (Use: http://api.open-notify.org/iss-now.json)")

Para mais informações sobre o SageMaker AI como provedor de modelos para o Strands Agents, consulte a documentação do Amazon SageMaker no site do Strands Agents.

Observabilidade com SageMaker AI Serverless MLflow

O SageMaker AI Serverless MLflow oferece observabilidade abrangente para agentes de IA, capturando automaticamente traces de execução, padrões de uso de ferramentas e fluxos de tomada de decisão — sem necessidade de instrumentação manual. O serviço gerenciado reduz a sobrecarga operacional e se integra nativamente ao Strands Agents SDK, permitindo monitorar o comportamento dos agentes em múltiplos deploys, identificar gargalos de desempenho e manter trilhas de auditoria para requisitos de conformidade.

Passo 1: Configurar o MLflow App

É possível configurar um MLflow App via interface do SageMaker AI Studio ou programaticamente com o SDK Boto3. O exemplo abaixo usa o Boto3:

s3_client = boto3.client('s3', region_name=region)
bucket_name = f'{account_id}-mlflow-bucket'

if region == 'us-east-1':
    s3_client.create_bucket(Bucket=bucket_name)
else:
    s3_client.create_bucket(
        Bucket=bucket_name,
        CreateBucketConfiguration={'LocationConstraint': region}
    )

sagemaker_client = boto3.client('sagemaker')

mlflow_app_details = sagemaker_client.create_mlflow_app(
    Name='strands-mlflow-app',
    ArtifactStoreUri=f's3://{account_id}-mlflow-bucket/artifacts',
    RoleArn=role,
)
print(f"MLflow app creation initiated: {mlflow_app_details['Arn']}")

Passo 2: Habilitar o logging automático para o agente

import os
import mlflow

tracking_uri = mlflow_app_details['Arn']
os.environ["MLFLOW_TRACKING_URI"] = tracking_uri

mlflow.set_experiment("Strands-MLflow")
mlflow.strands.autolog()

Passo 3: Executar o agente com rastreamento ativo

def capitalize(response):
    return response.upper()

agent = Agent(model=model_sagemaker, tools=[http_request])
response = agent("Where is the international space station now?")
capitalize(response.message['content'][0]['text'])

Os traces e métricas ficam disponíveis na interface do MLflow App por meio de uma URL pré-assinada:

presigned_response = sagemaker_client.create_presigned_mlflow_app_url(
    Arn=mlflow_app_details['Arn']
)
mlflow_ui_url = presigned_response['AuthorizedUrl']
print(f"MLflow UI URL: {mlflow_ui_url}")

Rastreamento manual de funções personalizadas

O logging automático do MLflow captura a invocação do agente e suas chamadas de ferramentas e FMs. Funções externas ao agente, como a capitalize do exemplo, não são registradas automaticamente. Para rastrear um bloco completo de código, o MLflow oferece a capacidade de rastreamento manual via decoradores:

@mlflow.trace(span_type="func", attributes={"operation": "capitalize"})
def capitalize(response):
    return response.upper()

@mlflow.trace
def run_agent():
    agent = Agent(tools=[http_request])
    mlflow.update_current_trace(request_preview="Run Strands Agent")
    response = agent("Where is the international space station now? (Use: http://api.open-notify.org/iss-now.json) ")
    capitalized_response = capitalize(response.message['content'][0]['text'])
    return capitalized_response

capitalized_response = run_agent()
print(capitalized_response)

Testes A/B com múltiplas variantes de modelos

Com o SageMaker AI, é possível otimizar os modelos de linguagem de grande porte (LLM — Large Language Model) para aplicações de agentes. Por exemplo, ao considerar uma migração do Qwen3-4B para o Qwen3-8B, não é necessário fazer a troca completa imediatamente. É possível implantar o novo modelo lado a lado com o atual e distribuir o tráfego entre os dois endpoints de LLM para conduzir testes A/B antes de confirmar a atualização.

Configurando as variantes de produção

# Step1: Create a model from JumpStart
model_b_name ="sagemaker-strands-demo-qwen3-8b"
model_b_id, model_b_version = "huggingface-reasoning-qwen3-8b", "1.0.0"

model_8b = JumpStartModel(
    model_id="huggingface-reasoning-qwen3-8b",
    model_version="1.0.0",
    name=model_b_name
)
model_b.create(instance_type="ml.g5.2xlarge")

# Step2: Create production variants for A/B testing
production_variants = [
    {
        "VariantName": "qwen-4b-variant",
        "ModelName": "qwen3-4b-model",
        "InitialInstanceCount": 1,
        "InstanceType": "ml.g5.2xlarge",
        "InitialVariantWeight": 0.5
    },
    {
        "VariantName": "qwen3-8b-variant",
        "ModelName": model_b_name,
        "InitialInstanceCount": 1,
        "InstanceType": "ml.g5.2xlarge",
        "InitialVariantWeight": 0.5
    }
]

# Step3: Create new endpoint configuration
ENDPOINT_CONFIG_AB_TESTING = "llm-endpoint-config-ab"
sagemaker_client.create_endpoint_config(
    EndpointConfigName=ENDPOINT_CONFIG_AB_TESTING,
    ProductionVariants=production_variants
)

# Step4: Update the endpoint with new A/B testing configuration
sagemaker_client.update_endpoint(
    EndpointName=ENDPOINT_NAME,
    EndpointConfigName=ENDPOINT_CONFIG_AB_TESTING
)

waiter = boto3.client('sagemaker').get_waiter('endpoint_in_service')
waiter.wait(EndpointName=ENDPOINT_NAME)

Para um experimento controlado, é possível criar dois agentes apontando para variantes específicas:

model_sagemaker_a = SageMakerAIModel(
    endpoint_config={
        "endpoint_name": ENDPOINT_NAME,
        "region_name": region,
        "target_variant":"qwen-4b-variant"
    },
    payload_config={
        "max_tokens": 2048,
        "temperature": 0.2,
        "stream": True,
    }
)

model_sagemaker_b = SageMakerAIModel(
    endpoint_config={
        "endpoint_name": ENDPOINT_NAME,
        "region_name": region,
        "target_variant":"qwen-8b-variant"
    },
    payload_config={
        "max_tokens": 2048,
        "temperature": 0.2,
        "stream": True,
    }
)

Avaliando os agentes com MLflow GenAI

Com ambas as variantes implantadas, o próximo passo é avaliá-las sistematicamente usando o framework de avaliação de IA generativa (GenAI — Generative Artificial Intelligence) do MLflow, que combina métricas customizadas e juízes baseados em LLM.

Criando o dataset de avaliação

eval_dataset = [
    {
        "inputs": {"query": "Calculate 15% tip on a $85.50 bill. Use calculator tool"},
        "expectations": {
            "expected_tool": "calculator",
            "expected_facts": ["The tip amount is approximately $12.83"]
        }
    },
    {
        "inputs": {"query": "What is 2048 divided by 64? Use calculator tool"},
        "expectations": {
            "expected_tool": "calculator",
            "expected_facts": ["The answer is 32"]
        }
    }
]

Definindo os scorers de avaliação

from mlflow.genai.scorers import scorer, Correctness, RelevanceToQuery
from mlflow.entities import Feedback

@scorer
def tool_selection_scorer(inputs, outputs, expectations):
    expected_tool = expectations.get("expected_tool", "")
    tool_used = expected_tool in outputs.get("tools", [])
    return Feedback(name="tool_selection", value=1.0 if tool_used else 0.0)

Executando a avaliação comparativa

import mlflow
from strands import Agent
from strands_tools import calculator

mlflow.set_experiment("Strands_Agents_AB_Evaluation")

def predict_4b(query):
    agent = Agent(model=model_sagemaker_a, tools=[calculator])
    response = agent(query)
    return {"outputs": str(response), "tools": list(response.metrics.tool_metrics.keys())}

def predict_8b(query):
    agent = Agent(model=model_sagemaker_b, tools=[calculator])
    response = agent(query)
    return {"outputs": str(response), "tools": list(response.metrics.tool_metrics.keys())}

scorers = [
    tool_selection_scorer,
    Correctness(model="bedrock:/us.amazon.nova-pro-v1:0"),
    RelevanceToQuery(model="bedrock:/us.amazon.nova-pro-v1:0")
]

eval_results_4b = mlflow.genai.evaluate(data=eval_dataset, predict_fn=predict_4b, scorers=scorers)
eval_results_8b = mlflow.genai.evaluate(data=eval_dataset, predict_fn=predict_8b, scorers=scorers)

Comparando os resultados

metrics_4b = eval_results_4b.metrics
metrics_8b = eval_results_8b.metrics

for metric in metrics_4b:
    print(f"{metric}: 4B={metrics_4b[metric]:.3f}, 8B={metrics_8b[metric]:.3f}")

Caso o novo modelo se mostre superior, basta ajustar os pesos das variantes para direcionar 100% do tráfego para ele:

production_variants = [
    {
        "VariantName": "qwen-8b-variant",
        "ModelName": model_b_name,
        "InitialInstanceCount": 1,
        "InstanceType": "ml.g5.2xlarge",
        "InitialVariantWeight": 1
    }
]

Solução de problemas e limpeza de recursos

Caso ocorra o erro ImportError: cannot import name 'TokenUsageKey' from 'mlflow.tracing.constant' ou outros problemas com o rastreamento do Strands no MLflow, verifique se a versão do MLflow instalada é 3.4.0 ou superior, e se a role utilizada possui permissões de leitura, escrita e listagem no bucket S3 configurado como artifact store do MLflow.

Para remover os recursos criados ao longo do tutorial:

sagemaker_client.delete_endpoint(EndpointName=ENDPOINT_NAME)
sagemaker_client.delete_endpoint_config(EndpointConfigName=INITIAL_CONFIG_NAME)
sagemaker_client.delete_endpoint_config(EndpointConfigName=ENDPOINT_CONFIG_AB_TESTING)

sagemaker_client.delete_mlflow_app(
    Arn=server_info["Arn"]
)

Conclusão

A combinação do Strands Agents SDK com o Amazon SageMaker AI e o SageMaker Serverless MLflow cria um framework robusto para construir, implantar e monitorar agentes de IA com controle total sobre a infraestrutura. O deploy de modelos no SageMaker AI garante controle preciso sobre recursos de computação, configurações de rede e políticas de escalabilidade — especialmente valioso para organizações com requisitos específicos de desempenho, custo ou conformidade. A integração com o MLflow oferece observabilidade sólida, rastreamento de comportamento dos agentes e trilhas de auditoria.

Para quem quiser se aprofundar, a AWS recomenda explorar o Strands Agents SDK e consultar o guia de decisão entre Amazon Bedrock e Amazon SageMaker AI para entender qual serviço é mais adequado para cada caso de uso.

Fonte

Build Strands Agents with SageMaker AI models and MLflow (https://aws.amazon.com/blogs/machine-learning/build-strands-agents-with-sagemaker-ai-models-and-mlflow/)

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *