<?xml version="1.0" encoding="UTF-8" standalone="no"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:series="https://publishpress.com/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" version="2.0">

<channel>
	<title>Asllan Maciel</title>
	<atom:link href="https://asllanmaciel.com.br/feed/" rel="self" type="application/rss+xml"/>
	<link/>
	<description>Minha missão é ajudar você a viver mais e melhor</description>
	<lastBuildDate>Wed, 12 Aug 2026 12:04:55 +0000</lastBuildDate>
	<language>pt-BR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0.4</generator>

<image>
	<url>https://asllanmaciel.com.br/wp-content/uploads/2026/08/Ativo-1.svg</url>
	<title>Asllan Maciel | Tecnologia, IA e Produtos Digitais</title>
	<link/>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Docker Healthcheck: containers confiáveis com Compose</title>
		<link>https://asllanmaciel.com.br/docker-healthcheck-compose-dependencias-confiaveis/</link>
					<comments>https://asllanmaciel.com.br/docker-healthcheck-compose-dependencias-confiaveis/#respond</comments>
		
		<dc:creator><![CDATA[Asllan Maciel]]></dc:creator>
		<pubDate>Wed, 12 Aug 2026 12:04:55 +0000</pubDate>
				<category><![CDATA[Programação]]></category>
		<category><![CDATA[Observabilidade]]></category>
		<category><![CDATA[Healthcheck]]></category>
		<category><![CDATA[docker compose]]></category>
		<category><![CDATA[containers]]></category>
		<category><![CDATA[devops]]></category>
		<category><![CDATA[docker]]></category>
		<guid isPermaLink="false">https://asllanmaciel.com.br/docker-healthcheck-compose-dependencias-confiaveis/</guid>

					<description><![CDATA[<p>Aprenda a detectar containers indisponíveis, coordenar dependências no Docker Compose e validar a saúde da aplicação antes de liberar o ambiente.</p>
<p>O post <a href="https://asllanmaciel.com.br/docker-healthcheck-compose-dependencias-confiaveis/">Docker Healthcheck: containers confiáveis com Compose</a> apareceu primeiro em <a href="https://asllanmaciel.com.br">Asllan Maciel | Tecnologia, IA e Produtos Digitais</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Um container em execução não é necessariamente um serviço disponível. O processo pode continuar ativo enquanto a aplicação trava, perde acesso ao banco ou deixa de responder às requisições. Se o ambiente verifica apenas se o container está “de pé”, essa falha permanece invisível até um usuário reclamar.</p>
<p>O <code>HEALTHCHECK</code> acrescenta um sinal objetivo: o Docker executa um teste dentro do container e registra os estados <code>starting</code>, <code>healthy</code> ou <code>unhealthy</code>. Com o Docker Compose, esse sinal também pode coordenar a inicialização de serviços dependentes e permitir que um deploy espere o ambiente ficar realmente pronto.</p>
<p>Nesta aula 8 da série <a href="https://asllanmaciel.com.br/series/docker-do-zero-ao-profissional/">Docker do Zero ao Profissional</a>, vamos evoluir o projeto apresentado em <a href="https://asllanmaciel.com.br/docker-compose-organizando-multiplos-servicos-facilmente/">Docker Compose: organizando múltiplos serviços</a>. O exemplo usa uma API Python e PostgreSQL, mas o raciocínio vale para qualquer aplicação composta por vários containers.</p>
<h2>Processo ativo não significa aplicação saudável</h2>
<p>O Docker já sabe se o processo principal terminou. O healthcheck responde a outra pergunta: <strong>o serviço ainda consegue cumprir sua função mínima?</strong> Para uma API, isso costuma significar aceitar uma conexão HTTP e responder rapidamente. Para um banco, pode significar aceitar conexões. Para um worker, pode ser confirmar acesso à fila e a recursos essenciais.</p>
<p>Uma verificação útil deve ser:</p>
<ul>
<li>rápida, para não consumir recursos nem acumular processos;</li>
<li>determinística, retornando sucesso ou falha sem ambiguidade;</li>
<li>local, testando o serviço pelo ponto de vista do próprio container;</li>
<li>representativa, sem executar uma operação pesada ou destrutiva;</li>
<li>segura, sem expor dados sensíveis na resposta.</li>
</ul>
<p>Evite usar apenas a existência do processo, porque isso repete o que o runtime já observa. Também evite chamar serviços externos desnecessários: se a API de um terceiro ficar fora do ar, todos os seus containers podem parecer doentes ao mesmo tempo.</p>
<p>A documentação do Docker informa que o comando do healthcheck sinaliza o resultado pelo código de saída. Na prática, <code>0</code> representa sucesso e <code>1</code> indica falha. Após o número configurado de falhas consecutivas, o status passa a <code>unhealthy</code>.</p>
<h2>Crie endpoints de vida e prontidão</h2>
<p>Em aplicações profissionais, é útil separar dois conceitos. <strong>Liveness</strong> confirma que o processo responde. <strong>Readiness</strong> confirma que ele está pronto para receber tráfego e acessar dependências indispensáveis.</p>
<p>Em uma API Flask, a estrutura pode começar assim:</p>
<pre><code class="language-python">from flask import Flask, jsonify
from sqlalchemy import text
from database import engine

app = Flask(__name__)

@app.get(&quot;/health/live&quot;)
def live():
    return jsonify(status=&quot;ok&quot;), 200

@app.get(&quot;/health/ready&quot;)
def ready():
    try:
        with engine.connect() as connection:
            connection.execute(text(&quot;SELECT 1&quot;))
        return jsonify(status=&quot;ready&quot;), 200
    except Exception:
        return jsonify(status=&quot;not_ready&quot;), 503
</code></pre>
<p>O endpoint de vida não consulta o banco; ele apenas prova que a aplicação responde. O de prontidão executa uma consulta mínima e devolve <code>503</code> quando a dependência essencial não está disponível. Não retorne stack traces, credenciais ou detalhes internos da infraestrutura.</p>
<p>Para um projeto pequeno, o healthcheck do container pode chamar <code>/health/ready</code>. Em ambientes maiores, a separação permite que a plataforma reinicie um processo que deixou de responder sem tratar uma indisponibilidade temporária do banco como falha fatal da aplicação.</p>
<h2>Configure o HEALTHCHECK no Dockerfile</h2>
<p>O teste pode fazer parte da imagem, seguindo a mesma evolução iniciada na aula <a href="https://asllanmaciel.com.br/como-criar-imagem-dockerfile/">Criando sua primeira imagem com Dockerfile</a>. Como a imagem do exemplo já possui Python, podemos usar a biblioteca padrão e evitar instalar <code>curl</code> apenas para a verificação:</p>
<pre><code class="language-dockerfile">FROM python:3.13-slim

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .

HEALTHCHECK --interval=30s --timeout=5s \
  --start-period=20s --retries=3 \
  CMD [&quot;python&quot;, &quot;-c&quot;, &quot;import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health/ready', timeout=3)&quot;]

CMD [&quot;gunicorn&quot;, &quot;--bind&quot;, &quot;0.0.0.0:8000&quot;, &quot;app:app&quot;]
</code></pre>
<p>Cada parâmetro controla uma parte do comportamento:</p>
<ul>
<li><code>interval</code>: intervalo entre verificações;</li>
<li><code>timeout</code>: tempo máximo permitido para cada tentativa;</li>
<li><code>start-period</code>: período de tolerância para a aplicação inicializar;</li>
<li><code>retries</code>: quantidade de falhas consecutivas antes de marcar como não saudável.</li>
</ul>
<p>Os valores precisam refletir o comportamento real do serviço. Um <code>start-period</code> curto demais gera falsos negativos durante migrações ou aquecimento. Um intervalo muito longo demora a revelar falhas. Um timeout exagerado mantém verificações presas e reduz a utilidade do sinal.</p>
<p>Há apenas um <code>HEALTHCHECK</code> efetivo por Dockerfile; se a instrução aparecer mais de uma vez, somente a última vale. Você também pode usar <code>HEALTHCHECK NONE</code> para desativar uma verificação herdada da imagem base.</p>
<h2>Coordene banco e API no Docker Compose</h2>
<p>O Compose permite definir ou sobrescrever o healthcheck de cada serviço. A forma longa de <code>depends_on</code> adiciona a condição <code>service_healthy</code>, fazendo a API esperar o banco ficar saudável antes de ser criada:</p>
<pre><code class="language-yaml">services:
  db:
    image: postgres:18
    environment:
      POSTGRES_DB: app
      POSTGRES_USER: app
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: [&quot;CMD-SHELL&quot;, &quot;pg_isready -U app -d app&quot;]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 20s
    restart: unless-stopped

  api:
    build: .
    ports:
      - &quot;8000:8000&quot;
    environment:
      DATABASE_URL: postgresql://app:${POSTGRES_PASSWORD}@db:5432/app
    depends_on:
      db:
        condition: service_healthy
    restart: unless-stopped

volumes:
  postgres_data:
</code></pre>
<p>A sintaxe curta <code>depends_on: [db]</code> garante a ordem de criação, mas não espera o banco aceitar conexões. <code>service_healthy</code> usa o resultado do healthcheck para fechar essa lacuna. Isso reduz erros de inicialização, mas a aplicação ainda deve implementar tentativas com espera progressiva: dependências podem cair depois que o ambiente já iniciou.</p>
<p>Mantenha a senha em um arquivo <code>.env</code> fora do Git ou, em produção, em um gerenciador de segredos. O healthcheck do PostgreSQL não precisa repetir a senha porque <code>pg_isready</code> apenas verifica o estado de aceitação de conexões.</p>
<h2>Entenda o limite das políticas de reinício</h2>
<p><code>restart: unless-stopped</code> e <code>HEALTHCHECK</code> resolvem problemas diferentes. A política de reinício atua quando o processo do container termina; o healthcheck registra se um processo ainda ativo consegue atender ao teste. Um container marcado como <code>unhealthy</code> <strong>não é reiniciado automaticamente pelo Docker Engine apenas por causa desse estado</strong>.</p>
<p>As políticas mais comuns são:</p>
<ul>
<li><code>no</code>: não reinicia automaticamente;</li>
<li><code>on-failure</code>: reinicia quando o processo termina com código diferente de zero;</li>
<li><code>always</code>: reinicia sempre, respeitando as regras de parada manual do Docker;</li>
<li><code>unless-stopped</code>: reinicia, exceto quando o container foi interrompido explicitamente.</li>
</ul>
<p>Se a aplicação detectar uma condição irrecuperável, encerrar o processo com erro permite que <code>on-failure</code> ou <code>unless-stopped</code> atue. Para decisões mais sofisticadas — substituir instâncias doentes, limitar tentativas e distribuir tráfego — use um orquestrador compatível com essas necessidades. Não instale um supervisor dentro do container apenas para mascarar falhas; a documentação do Docker recomenda usar as políticas do runtime.</p>
<h2>Valide o ambiente e provoque uma falha controlada</h2>
<p>Antes de considerar o trabalho concluído, valide a configuração e espere os serviços ficarem saudáveis:</p>
<pre><code class="language-bash">docker compose config
docker compose up --build --wait --wait-timeout 90
docker compose ps
</code></pre>
<p>A opção <code>--wait</code> aguarda os serviços atingirem o estado <code>running</code> ou <code>healthy</code> e implica modo destacado. Isso é especialmente útil em scripts de deploy e integração contínua, pois o comando falha em vez de seguir adiante com um ambiente incompleto.</p>
<p>Para inspecionar o histórico de uma verificação:</p>
<pre><code class="language-bash">docker inspect --format '{{json .State.Health}}' projeto-api-1
docker compose logs --tail=100 api db
</code></pre>
<p>Em um ambiente local, pare o banco por alguns segundos e observe a API mudar de estado. Depois, inicie o banco novamente e confirme a recuperação. Esse teste revela se timeouts, tentativas e endpoints representam o comportamento real, sem esperar a primeira falha em produção.</p>
<p>Use este checklist antes do deploy:</p>
<ul>
<li>[ ] O teste verifica uma capacidade real do serviço, não apenas o processo?</li>
<li>[ ] O endpoint responde rápido e não revela informações sensíveis?</li>
<li>[ ] <code>interval</code>, <code>timeout</code>, <code>start_period</code> e <code>retries</code> foram ajustados ao tempo real de inicialização?</li>
<li>[ ] Dependências críticas usam <code>condition: service_healthy</code>?</li>
<li>[ ] A aplicação tolera a queda de uma dependência depois da inicialização?</li>
<li>[ ] A política de reinício escolhida corresponde ao comportamento esperado?</li>
<li>[ ] <code>docker compose up --wait</code> termina com sucesso no pipeline?</li>
<li>[ ] Uma falha controlada foi observada nos estados e nos logs?</li>
</ul>
<p>Com healthchecks bem definidos, o Docker deixa de informar apenas que processos existem e passa a mostrar se os serviços entregam a capacidade esperada. O próximo passo é levar essa confiabilidade ao processo de entrega: automatizar build, testes e publicação da imagem sem perder rastreabilidade. Enquanto isso, revise também as <a href="https://asllanmaciel.com.br/boas-praticas-docker-performance-e-seguranca/">boas práticas de performance, segurança e organização no Docker</a> para consolidar a base da aplicação.</p>
<p>O post <a href="https://asllanmaciel.com.br/docker-healthcheck-compose-dependencias-confiaveis/">Docker Healthcheck: containers confiáveis com Compose</a> apareceu primeiro em <a href="https://asllanmaciel.com.br">Asllan Maciel | Tecnologia, IA e Produtos Digitais</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://asllanmaciel.com.br/docker-healthcheck-compose-dependencias-confiaveis/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		
		<series:name><![CDATA[Docker do Zero ao Profissional]]></series:name>
	</item>
		<item>
		<title>Oferta piloto: defina escopo, preço e critérios de sucesso</title>
		<link>https://asllanmaciel.com.br/oferta-piloto-escopo-preco-criterios-sucesso/</link>
					<comments>https://asllanmaciel.com.br/oferta-piloto-escopo-preco-criterios-sucesso/#respond</comments>
		
		<dc:creator><![CDATA[Asllan Maciel]]></dc:creator>
		<pubDate>Wed, 12 Aug 2026 06:37:13 +0000</pubDate>
				<category><![CDATA[Marketing Digital]]></category>
		<category><![CDATA[Empreendedorismo]]></category>
		<category><![CDATA[Produto Digital]]></category>
		<category><![CDATA[MVP]]></category>
		<category><![CDATA[Precificação]]></category>
		<category><![CDATA[Validação de Negócios]]></category>
		<category><![CDATA[Oferta Piloto]]></category>
		<category><![CDATA[vendas]]></category>
		<guid isPermaLink="false">https://asllanmaciel.com.br/oferta-piloto-escopo-preco-criterios-sucesso/</guid>

					<description><![CDATA[<p>Transforme uma proposta de valor em oferta piloto: escolha o cliente, limite o escopo, defina preço, evidências e critérios claros para continuar.</p>
<p>O post <a href="https://asllanmaciel.com.br/oferta-piloto-escopo-preco-criterios-sucesso/">Oferta piloto: defina escopo, preço e critérios de sucesso</a> apareceu primeiro em <a href="https://asllanmaciel.com.br">Asllan Maciel | Tecnologia, IA e Produtos Digitais</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Uma proposta de valor clara ainda não é uma oferta. Ela explica para quem você trabalha, qual problema resolve e por que a solução importa. A oferta acrescenta compromissos concretos: o que será entregue, em quanto tempo, por qual preço, com quais limites e como as duas partes saberão se o trabalho funcionou.</p>
<p>Esse é o ponto em que muitos negócios digitais travam. O empreendedor sai das entrevistas cheio de boas ideias, mas tenta transformar tudo em produto completo. Acrescenta funcionalidades, integrações, automações e promessas antes de descobrir se alguém aceita pagar por uma primeira versão do resultado.</p>
<p>Na aula 5 da série <a href="https://asllanmaciel.com.br/series/negocios-digitais-na-pratica/">Negócios Digitais na Prática</a>, vamos seguir o passo iniciado em <a href="https://asllanmaciel.com.br/proposta-valor-entrevistas-oferta-clara/">Proposta de valor: transforme entrevistas em uma oferta clara</a>. O objetivo agora é criar uma <strong>oferta piloto paga</strong>: pequena o bastante para ser entregue com controle e valiosa o bastante para produzir evidência real de compra e resultado.</p>
<h2>O piloto não é desconto nem produto incompleto</h2>
<p>Um piloto é um acordo limitado de aprendizado. Você atende um perfil específico, resolve uma parte bem definida do problema e acompanha o resultado de perto. O cliente sabe que está entrando em uma etapa inicial; você sabe exatamente quais hipóteses quer testar.</p>
<p>Isso é diferente de vender barato tudo o que imagina construir. Quando o escopo continua aberto, o preço reduzido apenas piora a operação: você recebe menos, assume mais risco e ainda termina sem saber qual parte gerou valor.</p>
<p>A Strategyzer recomenda que experimentos iniciais sejam baratos e rápidos, adiando construções caras quando existe uma forma mais simples de aprender. Também diferencia descoberta de validação: conversar ajuda a entender o problema; uma troca real de valor produz evidência mais forte. A oferta piloto cria essa passagem.</p>
<p>Ela deve responder a cinco perguntas:</p>
<ol>
<li>Para quem é esta primeira versão?</li>
<li>Qual resultado específico será perseguido?</li>
<li>O que está incluído e o que está fora?</li>
<li>Quanto custa e quando será pago?</li>
<li>Qual evidência permitirá continuar, ajustar ou encerrar?</li>
</ol>
<p>Se uma dessas respostas estiver vaga, a venda pode até acontecer, mas o aprendizado ficará confuso.</p>
<h2>Escolha um cliente e um resultado estreitos</h2>
<p>Comece pelas evidências reunidas na <a href="https://asllanmaciel.com.br/entrevista-problema-descobrir-dores-reais/">entrevista de problema</a>. Não escolha “pequenas empresas” ou “criadores de conteúdo”. Escolha um grupo que compartilhe contexto, dor e urgência.</p>
<p>Compare:</p>
<blockquote>
<p>Ajudo empresas a automatizar atendimento.</p>
</blockquote>
<p>com:</p>
<blockquote>
<p>Em 14 dias, organizo o atendimento inicial de clínicas pequenas que perdem contatos vindos do WhatsApp, implantando triagem, registro e acompanhamento dos novos pedidos.</p>
</blockquote>
<p>A segunda formulação não promete transformar toda a operação. Ela define público, situação, prazo e resultado observável. Isso facilita a conversa comercial e reduz a quantidade de variáveis no piloto.</p>
<p>Use este modelo:</p>
<pre><code class="language-text">Para [perfil específico]
que hoje enfrenta [situação observável],
o piloto entrega [resultado limitado]
em [prazo],
sem exigir [barreira relevante].
</code></pre>
<p>O resultado deve ser importante para o cliente e possível de verificar. “Melhorar a presença digital” é abstrato. “Publicar uma página de oferta e captar dez conversas qualificadas” é mensurável. “Aumentar vendas” pode depender de fatores demais; “reduzir o tempo de resposta aos contatos” pode ser acompanhado diretamente.</p>
<h2>Converta o resultado em um escopo protegido</h2>
<p>O escopo existe para impedir que o piloto vire um projeto infinito. Organize-o em quatro blocos: entradas, atividades, entregáveis e limites.</p>
<table>
<thead>
<tr>
<th>Bloco</th>
<th>Pergunta prática</th>
<th>Exemplo</th>
</tr>
</thead>
<tbody>
<tr>
<td>Entradas</td>
<td>O que o cliente precisa fornecer?</td>
<td>Acesso, dados e responsável interno</td>
</tr>
<tr>
<td>Atividades</td>
<td>O que será realizado?</td>
<td>Diagnóstico, configuração e teste</td>
</tr>
<tr>
<td>Entregáveis</td>
<td>O que ficará pronto?</td>
<td>Fluxo ativo, painel e documentação</td>
</tr>
<tr>
<td>Limites</td>
<td>O que não faz parte?</td>
<td>Integrações extras e suporte permanente</td>
</tr>
</tbody>
</table>
<p>Evite apresentar uma lista enorme de funcionalidades. O cliente compra progresso, não volume de tarefas. Três entregáveis ligados ao resultado costumam comunicar melhor que vinte itens técnicos.</p>
<p>Inclua também uma regra de mudança. Se surgir uma necessidade fora do combinado, registre-a como hipótese para uma próxima fase, em vez de absorvê-la silenciosamente. Essa disciplina protege margem, prazo e qualidade da evidência.</p>
<p>O <a href="https://asllanmaciel.com.br/mvp-concierge-vender-aprender-antes-automatizar/">MVP concierge</a> é especialmente útil aqui. Você pode executar manualmente etapas que mais tarde serão automatizadas, desde que a experiência e os limites estejam claros. O piloto deve testar o valor do resultado antes de financiar uma infraestrutura complexa.</p>
<h2>Defina um preço que teste compromisso e sustentabilidade</h2>
<p>Preço zero mede interesse, disponibilidade e talvez uso. Não mede disposição de pagar. Se a hipótese central envolve um negócio sustentável, algum compromisso financeiro precisa entrar no teste.</p>
<p>O preço inicial não precisa ser perfeito, mas precisa ser explicável. Considere três referências:</p>
<ul>
<li><strong>custo de entrega:</strong> horas, ferramentas, suporte e risco assumido;</li>
<li><strong>valor percebido:</strong> economia, receita, velocidade ou risco evitado pelo cliente;</li>
<li><strong>alternativas:</strong> quanto custa continuar como está ou contratar outra solução.</li>
</ul>
<p>Para um piloto de serviço ou implantação, um valor fechado simplifica a decisão. Para software, o modelo deve acompanhar como o cliente recebe valor. A orientação atual da Stripe sobre precificação e empacotamento destaca que cobrança por usuário, faixa, consumo ou formato híbrido funciona melhor quando a métrica escolhida acompanha o benefício entregue.</p>
<p>Não use desconto sem contrapartida. Se o primeiro cliente receber uma condição especial, peça algo concreto: participação nas reuniões de revisão, dados de uso, autorização para um caso anonimizado ou depoimento condicionado a resultado. O desconto deixa de ser concessão aleatória e vira parte explícita do experimento.</p>
<p>Uma estrutura simples pode ser:</p>
<pre><code class="language-text">Investimento: R$ X
Pagamento: 50% no início e 50% na entrega
Prazo: 14 dias
Vagas do piloto: 3
Inclui: entregáveis A, B e C
Não inclui: itens D e E
</code></pre>
<p>O meio de pagamento não precisa atrasar a validação. A documentação da Stripe mostra que Payment Links permite criar uma página hospedada e compartilhável para produto ou assinatura sem desenvolver um checkout próprio. Use a solução compatível com seu negócio e sua região, mas mantenha a experiência profissional: descrição clara, recibo, confirmação e próximos passos.</p>
<h2>Escreva critérios de sucesso antes de começar</h2>
<p>Sem critérios definidos antecipadamente, qualquer resultado pode ser reinterpretado como vitória. Um experimento forte começa com uma hipótese precisa, participantes relevantes e evidências que realmente respondam à pergunta, como orienta a Strategyzer ao tratar do desenho de experimentos.</p>
<p>Defina critérios em três níveis:</p>
<h3>Evidência comercial</h3>
<ul>
<li>quantas pessoas do perfil receberam a oferta;</li>
<li>quantas avançaram para conversa;</li>
<li>quantas aceitaram o preço e pagaram;</li>
<li>quais objeções apareceram repetidamente.</li>
</ul>
<h3>Evidência de entrega</h3>
<ul>
<li>o piloto foi concluído dentro do prazo e do escopo;</li>
<li>quantas horas e custos foram consumidos;</li>
<li>onde houve dependência excessiva do fundador;</li>
<li>quais etapas poderiam ser padronizadas.</li>
</ul>
<h3>Evidência de resultado</h3>
<ul>
<li>qual indicador mudou para o cliente;</li>
<li>em quanto tempo o primeiro valor apareceu;</li>
<li>o cliente continuaria, renovaria ou indicaria;</li>
<li>qual parte da solução ele considerou indispensável.</li>
</ul>
<p>Estabeleça uma regra de decisão. Exemplo: “Se dois de cinco clientes qualificados comprarem, os três pilotos forem entregues em até 16 horas cada e pelo menos dois clientes atingirem o indicador combinado, criaremos a segunda versão.” Os números devem refletir sua realidade; o valor está em defini-los antes de conhecer o resultado.</p>
<h2>Conduza o piloto como ciclo de aprendizado</h2>
<p>Uma venda não encerra a validação. Ela inicia um ciclo curto de observação. Faça uma reunião de entrada, registre o estado inicial, entregue em marcos e marque uma revisão final.</p>
<p>Durante a execução, mantenha um diário simples:</p>
<pre><code class="language-text">Hipótese testada:
O que aconteceu:
Evidência observada:
Surpresa ou objeção:
Mudança proposta:
Decisão:
</code></pre>
<p>Evite mudar a oferta para cada cliente no meio do teste. Pequenas adaptações são naturais, mas alterações profundas impedem a comparação. Se três pessoas pedem a mesma mudança, isso é um sinal. Se apenas uma pede algo muito específico, pode ser exceção.</p>
<p>Ao final, separe satisfação de resultado. O cliente pode gostar do atendimento e ainda não obter valor econômico. Também pode atingir o objetivo com uma experiência operacional ruim. As duas dimensões importam para decidir o que padronizar.</p>
<h2>Checklist para colocar a oferta na rua</h2>
<p>Antes de convidar o primeiro cliente, confirme:</p>
<ul>
<li>[ ] o perfil do piloto está descrito de forma específica;</li>
<li>[ ] o problema foi observado em entrevistas reais;</li>
<li>[ ] existe um resultado limitado e mensurável;</li>
<li>[ ] prazo, entradas e entregáveis estão claros;</li>
<li>[ ] o documento informa explicitamente o que não está incluído;</li>
<li>[ ] o preço cobre o aprendizado sem tornar a entrega inviável;</li>
<li>[ ] a condição especial exige uma contrapartida definida;</li>
<li>[ ] o pagamento e a confirmação estão preparados;</li>
<li>[ ] os critérios de sucesso foram escritos antes da venda;</li>
<li>[ ] existe uma reunião final para medir resultado e decidir o próximo passo.</li>
</ul>
<p>A oferta piloto é a ponte entre “as pessoas disseram que gostaram” e “alguém assumiu um compromisso para obter o resultado”. Ela não precisa parecer uma empresa pronta. Precisa ser clara, honesta, entregável e capaz de gerar evidência.</p>
<p>Escolha hoje um único perfil, transforme sua proposta de valor em um resultado de curto prazo e escreva uma página com escopo, preço, limites e critérios de sucesso. Depois apresente-a a cinco pessoas qualificadas. A próxima versão do negócio deve nascer das respostas, das compras e da experiência de entrega — não de mais semanas planejando funcionalidades em isolamento.</p>
<p>O post <a href="https://asllanmaciel.com.br/oferta-piloto-escopo-preco-criterios-sucesso/">Oferta piloto: defina escopo, preço e critérios de sucesso</a> apareceu primeiro em <a href="https://asllanmaciel.com.br">Asllan Maciel | Tecnologia, IA e Produtos Digitais</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://asllanmaciel.com.br/oferta-piloto-escopo-preco-criterios-sucesso/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		
		<series:name><![CDATA[Negócios Digitais na Prática: da Ideia às Primeiras Vendas]]></series:name>
	</item>
		<item>
		<title>Streaming com IA em Python: respostas em tempo real na prática</title>
		<link>https://asllanmaciel.com.br/streaming-responses-api-python-tempo-real/</link>
					<comments>https://asllanmaciel.com.br/streaming-responses-api-python-tempo-real/#respond</comments>
		
		<dc:creator><![CDATA[Asllan Maciel]]></dc:creator>
		<pubDate>Wed, 12 Aug 2026 04:43:18 +0000</pubDate>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Inteligência Artificial]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[Responses API]]></category>
		<category><![CDATA[OpenAI API]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[Streaming]]></category>
		<category><![CDATA[FastAPI]]></category>
		<category><![CDATA[Server-Sent Events]]></category>
		<guid isPermaLink="false">https://asllanmaciel.com.br/?p=5086</guid>

					<description><![CDATA[<p>Aprenda a transmitir respostas de IA em tempo real com Python, Responses API e SSE, tratando eventos, falhas e desconexões sem travar a interface.</p>
<p>O post <a href="https://asllanmaciel.com.br/streaming-responses-api-python-tempo-real/">Streaming com IA em Python: respostas em tempo real na prática</a> apareceu primeiro em <a href="https://asllanmaciel.com.br">Asllan Maciel | Tecnologia, IA e Produtos Digitais</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Quando uma aplicação espera a resposta inteira da inteligência artificial antes de mostrar qualquer coisa, o usuário enxerga apenas uma tela parada. A mesma geração pode parecer muito mais rápida quando o texto começa a chegar em poucos instantes. Essa é a função do <em>streaming</em>: entregar a resposta em eventos menores, conforme o modelo produz o conteúdo.</p>
<p>Nesta continuação da série <a href="https://asllanmaciel.com.br/series/python-ia/">Python + IA</a>, vamos implementar esse fluxo com a Responses API, o SDK oficial para Python e Server-Sent Events (SSE). O objetivo não é somente imprimir fragmentos no terminal. Vamos organizar os eventos, preservar a resposta final e criar um endpoint que uma interface web possa consumir.</p>
<p>O streaming complementa recursos vistos nas aulas sobre <a href="https://asllanmaciel.com.br/saidas-estruturadas-ia-json-automacoes-python/">saídas estruturadas</a>, <a href="https://asllanmaciel.com.br/function-calling-python-ia-ferramentas-seguranca/">function calling</a> e <a href="https://asllanmaciel.com.br/web-search-ia-python-fontes-citacoes/">Web Search</a>. Ele não muda o que o modelo é capaz de fazer; muda como a aplicação apresenta e controla a execução.</p>
<h2>Por que streaming muda a experiência, mas não reduz o trabalho do modelo</h2>
<p>Sem streaming, o fluxo é simples: seu código envia uma requisição, aguarda a conclusão e recebe um objeto pronto. Com streaming, a conexão permanece aberta e o servidor envia uma sequência de eventos. O SDK oficial implementa esse transporte sobre SSE quando <code>stream=True</code> é usado na criação da resposta.</p>
<p>Na prática, isso reduz a latência percebida. Uma geração que leva oito segundos pode começar a exibir conteúdo no primeiro ou segundo segundo. O tempo total e a quantidade de tokens, porém, podem continuar praticamente iguais. Portanto, streaming é uma melhoria de experiência e de arquitetura de entrega, não um desconto automático de custo.</p>
<p>Ele faz sentido em:</p>
<ul>
<li>chats e copilotos;</li>
<li>geração de textos mais longos;</li>
<li>explicações de código;</li>
<li>pesquisas com várias etapas;</li>
<li>interfaces nas quais o usuário precisa perceber progresso.</li>
</ul>
<p>Para respostas curtas, tarefas em segundo plano ou automações que só podem agir depois de validar o resultado completo, uma chamada comum pode ser mais simples. Também é importante separar duas ideias: o fluxo pode exibir texto parcial, mas decisões críticas devem aguardar o evento de conclusão e as validações necessárias.</p>
<h2>Prepare o projeto sem colocar a chave no código</h2>
<p>Crie um ambiente isolado e instale o SDK. Se você acompanhou a aula sobre <a href="https://asllanmaciel.com.br/python-uv-pyproject-ambientes-reproduziveis/">ambientes com uv</a>, pode usar o mesmo padrão:</p>
<pre><code class="language-bash">uv init streaming-ia
cd streaming-ia
uv add openai python-dotenv fastapi uvicorn
</code></pre>
<p>Guarde a credencial em uma variável de ambiente. Um arquivo <code>.env</code> local é conveniente durante o desenvolvimento, desde que esteja no <code>.gitignore</code>:</p>
<pre><code class="language-env">OPENAI_API_KEY=sua_chave_aqui
OPENAI_MODEL=gpt-5.5
</code></pre>
<p>O modelo fica configurável porque nomes e opções disponíveis podem variar entre projetos. O código não precisa ser alterado quando você troca o valor no ambiente.</p>
<pre><code class="language-python">import os

from dotenv import load_dotenv
from openai import OpenAI

load_dotenv()

client = OpenAI()
MODEL = os.getenv(&quot;OPENAI_MODEL&quot;, &quot;gpt-5.5&quot;)
</code></pre>
<p>Nunca envie a chave ao navegador nem a inclua em JavaScript público. A interface deve conversar com seu backend; somente o backend chama o provedor de IA.</p>
<h2>Faça o primeiro streaming e filtre os eventos úteis</h2>
<p>A implementação mínima usa <code>stream=True</code> e percorre o objeto retornado. O fluxo contém eventos de tipos diferentes: início, deltas de texto, conclusão de itens, término da resposta e possíveis falhas. Para mostrar texto, o evento mais importante é <code>response.output_text.delta</code>.</p>
<pre><code class="language-python">from openai import OpenAI

client = OpenAI()

stream = client.responses.create(
    model=MODEL,
    input=&quot;Explique em cinco passos como revisar um pull request.&quot;,
    stream=True,
)

for event in stream:
    if event.type == &quot;response.output_text.delta&quot;:
        print(event.delta, end=&quot;&quot;, flush=True)
    elif event.type == &quot;response.completed&quot;:
        print(&quot;\n\nResposta concluída.&quot;)
    elif event.type == &quot;response.failed&quot;:
        print(&quot;\nA geração falhou.&quot;)
</code></pre>
<p>O <code>flush=True</code> evita que o terminal retenha pequenos fragmentos em um buffer. Em uma interface web, o equivalente é encaminhar cada delta imediatamente pela conexão aberta.</p>
<p>Evite imprimir todos os eventos para o usuário. Eles são úteis durante a depuração, mas podem incluir detalhes internos que poluem a interface. Trate explicitamente os tipos necessários e registre o restante de forma controlada.</p>
<h2>Acumule o texto e diferencie parcial de concluído</h2>
<p>Uma resposta parcial é ótima para leitura, mas não deve ser confundida com o resultado definitivo. A conexão pode cair, o usuário pode cancelar ou a geração pode terminar com erro. Por isso, acumule os deltas enquanto transmite e marque o resultado como concluído somente após receber o evento terminal esperado.</p>
<pre><code class="language-python">def gerar_resposta(pergunta: str) -&gt; str:
    partes: list[str] = []
    concluida = False

    stream = client.responses.create(
        model=MODEL,
        input=pergunta,
        stream=True,
    )

    for event in stream:
        if event.type == &quot;response.output_text.delta&quot;:
            partes.append(event.delta)
            print(event.delta, end=&quot;&quot;, flush=True)
        elif event.type == &quot;response.completed&quot;:
            concluida = True
        elif event.type == &quot;response.failed&quot;:
            raise RuntimeError(&quot;A API informou falha na resposta&quot;)

    if not concluida:
        raise RuntimeError(&quot;O fluxo terminou sem confirmação de conclusão&quot;)

    return &quot;&quot;.join(partes)
</code></pre>
<p>Esse cuidado é especialmente importante quando o texto será salvo, enviado por e-mail ou usado como entrada de outra automação. Você pode mostrar o conteúdo enquanto chega, mas só persiste a versão final depois da confirmação.</p>
<p>Também registre informações operacionais sem armazenar conteúdo sensível: duração, tipo do evento terminal, modelo configurado e um identificador interno da requisição. Logs devem ajudar a diagnosticar falhas, não criar uma cópia desnecessária dos dados do usuário.</p>
<h2>Exponha o fluxo para uma interface com FastAPI e SSE</h2>
<p>O navegador pode consumir eventos enviados pelo seu backend. Neste exemplo, o FastAPI recebe a pergunta, abre o streaming com o SDK e encaminha apenas deltas sanitizados. <code>StreamingResponse</code> mantém a conexão HTTP aberta com o tipo <code>text/event-stream</code>.</p>
<pre><code class="language-python">import json
import os

from fastapi import FastAPI, Request
from fastapi.responses import StreamingResponse
from openai import AsyncOpenAI
from pydantic import BaseModel, Field

app = FastAPI()
client = AsyncOpenAI()
MODEL = os.getenv(&quot;OPENAI_MODEL&quot;, &quot;gpt-5.5&quot;)


class Mensagem(BaseModel):
    pergunta: str = Field(min_length=2, max_length=4000)


@app.post(&quot;/chat/stream&quot;)
async def chat_stream(payload: Mensagem, request: Request):
    async def eventos():
        stream = await client.responses.create(
            model=MODEL,
            input=payload.pergunta,
            stream=True,
        )

        async for event in stream:
            if await request.is_disconnected():
                break

            if event.type == &quot;response.output_text.delta&quot;:
                data = json.dumps(
                    {&quot;tipo&quot;: &quot;delta&quot;, &quot;texto&quot;: event.delta},
                    ensure_ascii=False,
                )
                yield f&quot;data: {data}\n\n&quot;

            elif event.type == &quot;response.completed&quot;:
                yield 'data: {&quot;tipo&quot;:&quot;concluida&quot;}\n\n'

            elif event.type == &quot;response.failed&quot;:
                yield 'data: {&quot;tipo&quot;:&quot;erro&quot;}\n\n'

    return StreamingResponse(
        eventos(),
        media_type=&quot;text/event-stream&quot;,
        headers={
            &quot;Cache-Control&quot;: &quot;no-cache&quot;,
            &quot;X-Accel-Buffering&quot;: &quot;no&quot;,
        },
    )
</code></pre>
<p>Inicie o servidor com <code>uv run uvicorn main:app --reload</code>. O cabeçalho <code>X-Accel-Buffering: no</code> ajuda quando há um proxy compatível, mas a configuração real depende da sua infraestrutura. Teste o caminho completo em produção: aplicação, proxy, CDN e navegador. Um intermediário que acumula a resposta em buffer elimina o benefício do streaming.</p>
<p>Para uma aplicação pública, acrescente autenticação, limite por usuário, timeout, moderação adequada ao caso e proteção contra abuso. Também limite o tamanho da pergunta antes de iniciar uma chamada que gera custo.</p>
<h2>Checklist de produção e próximos passos</h2>
<p>Antes de liberar o recurso, verifique:</p>
<ul>
<li>[ ] a chave existe somente no backend e no gerenciador de segredos;</li>
<li>[ ] a entrada tem limite de tamanho e validação;</li>
<li>[ ] o frontend diferencia <code>delta</code>, conclusão e erro;</li>
<li>[ ] texto parcial não dispara ações irreversíveis;</li>
<li>[ ] desconexões interrompem o trabalho quando possível;</li>
<li>[ ] proxy e CDN não acumulam o fluxo em buffer;</li>
<li>[ ] timeouts e tentativas não duplicam uma operação;</li>
<li>[ ] logs evitam dados pessoais e segredos;</li>
<li>[ ] métricas acompanham tempo até o primeiro delta e tempo total;</li>
<li>[ ] a interface oferece cancelar e tentar novamente.</li>
</ul>
<p>Duas métricas ajudam bastante. <strong>Tempo até o primeiro delta</strong> mede a sensação de resposta. <strong>Tempo até a conclusão</strong> mede a duração real. Se o primeiro está baixo e o segundo alto, a interface parece ágil, mas talvez o prompt ou a tarefa ainda precisem ser otimizados.</p>
<p>O próximo passo natural é combinar streaming com ferramentas. Nesse caso, a interface precisa comunicar estados além do texto, como “consultando documentos” ou “verificando pedido”, sem expor argumentos internos nem fingir que uma ação terminou antes da validação.</p>
<p>Comece pelo script de terminal, confirme os eventos que sua aplicação realmente recebe e só então adicione FastAPI e frontend. Essa progressão torna os erros mais fáceis de localizar. Com o fluxo bem tratado, o streaming deixa de ser um efeito visual e vira uma camada confiável de entrega para produtos de IA mais responsivos.</p>
<p>O post <a href="https://asllanmaciel.com.br/streaming-responses-api-python-tempo-real/">Streaming com IA em Python: respostas em tempo real na prática</a> apareceu primeiro em <a href="https://asllanmaciel.com.br">Asllan Maciel | Tecnologia, IA e Produtos Digitais</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://asllanmaciel.com.br/streaming-responses-api-python-tempo-real/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		
		<series:name><![CDATA[Python + IA: Fundamentos e Projetos Práticos]]></series:name>
	</item>
		<item>
		<title>Web Search com IA em Python: respostas atuais com fontes verificáveis</title>
		<link>https://asllanmaciel.com.br/web-search-ia-python-fontes-citacoes/</link>
					<comments>https://asllanmaciel.com.br/web-search-ia-python-fontes-citacoes/#respond</comments>
		
		<dc:creator><![CDATA[Asllan Maciel]]></dc:creator>
		<pubDate>Tue, 11 Aug 2026 12:13:39 +0000</pubDate>
				<category><![CDATA[Cursos]]></category>
		<category><![CDATA[Guia para Iniciantes]]></category>
		<category><![CDATA[Programação]]></category>
		<guid isPermaLink="false">https://asllanmaciel.com.br/?p=5079</guid>

					<description><![CDATA[<p>Aprenda a usar Web Search na Responses API com Python, filtros de domínio, fontes retornadas e citações clicáveis para respostas atuais e auditáveis.</p>
<p>O post <a href="https://asllanmaciel.com.br/web-search-ia-python-fontes-citacoes/">Web Search com IA em Python: respostas atuais com fontes verificáveis</a> apareceu primeiro em <a href="https://asllanmaciel.com.br">Asllan Maciel | Tecnologia, IA e Produtos Digitais</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Uma aplicação de inteligência artificial que responde sobre preços, notícias, normas, lançamentos ou qualquer informação recente não pode depender apenas do conhecimento interno do modelo. Ela precisa buscar dados no momento da pergunta, selecionar fontes e mostrar de onde cada afirmação veio. É exatamente esse o papel do <strong>Web Search</strong> na Responses API.</p>
<p>Neste tutorial, você vai criar em Python uma pesquisa assistida por IA que consulta a Web, restringe domínios quando necessário, recupera a lista completa de fontes e preserva citações clicáveis. O objetivo não é construir mais um “chat que pesquisa”, mas uma base auditável para relatórios, atendimento, monitoramento e automações.</p>
<h2>Quando usar Web Search, File Search ou uma função própria</h2>
<p>Escolha a ferramenta pela origem da verdade. Use Web Search quando a resposta depende de conteúdo público e atual: documentação que muda, comunicados, notícias, indicadores ou páginas institucionais. Use <a href="https://asllanmaciel.com.br/file-search-ia-python-documentos-responses-api/">File Search</a> quando a informação está nos seus PDFs, manuais, contratos ou documentos internos. Já o <a href="https://asllanmaciel.com.br/function-calling-python-ia-ferramentas-seguranca/">function calling</a> é mais adequado quando o modelo precisa consultar ou alterar um sistema controlado por você.</p>
<p>Em muitos projetos, as três abordagens convivem. Um assistente de compras pode pesquisar informações públicas do produto, consultar a política interna da empresa e chamar uma função para registrar a solicitação. A separação importa porque cada fonte exige regras diferentes de segurança, atualização e autorização.</p>
<blockquote>
<p><strong>Princípio prático:</strong> a Web fornece evidências externas; seus arquivos fornecem contexto privado; suas funções executam ações. Não trate essas responsabilidades como se fossem equivalentes.</p>
</blockquote>
<h2>Prepare o projeto e faça a primeira pesquisa</h2>
<p>Crie um projeto Python, instale o SDK oficial e mantenha a chave apenas no ambiente do servidor. Se você acompanhou a aula sobre <a href="https://asllanmaciel.com.br/python-uv-pyproject-ambientes-reproduziveis/">ambientes com uv</a>, pode iniciar assim:</p>
<pre><code class="language-bash">uv init pesquisa-web
cd pesquisa-web
uv add openai
</code></pre>
<p>Defina <code>OPENAI_API_KEY</code> no ambiente e crie <code>main.py</code>:</p>
<pre><code class="language-python">from openai import OpenAI

client = OpenAI()

response = client.responses.create(
    model="gpt-5.6",
    tools=[{"type": "web_search"}],
    input=(
        "Pesquise as mudanças mais recentes na documentação oficial "
        "do Python sobre ambientes virtuais. Resuma em tópicos e cite as fontes."
    ),
)

print(response.output_text)
</code></pre>
<p>O item <code>{"type": "web_search"}</code> disponibiliza a pesquisa hospedada para o modelo. Com <code>tool_choice="auto"</code>, que é o comportamento padrão, o modelo decide se precisa pesquisar. Se a atualização for requisito obrigatório do seu fluxo, use <code>tool_choice="required"</code> e registre no log se um item <code>web_search_call</code> realmente apareceu na resposta.</p>
<p>A documentação atual recomenda <code>web_search</code> para novas integrações. O antigo <code>web_search_preview</code> permanece apenas para compatibilidade e não oferece todos os controles novos.</p>
<h2>Restrinja domínios e informe a localização do usuário</h2>
<p>Uma pesquisa ampla pode encontrar material útil, mas também páginas secundárias, agregadores ou conteúdo sem responsabilidade editorial. Em temas técnicos, financeiros ou regulatórios, prefira limitar a busca a fontes primárias. O filtro aceita domínios sem <code>https://</code> e inclui seus subdomínios.</p>
<pre><code class="language-python">response = client.responses.create(
    model="gpt-5.6",
    reasoning={"effort": "low"},
    tools=[
        {
            "type": "web_search",
            "filters": {
                "allowed_domains": [
                    "docs.python.org",
                    "peps.python.org",
                ],
                "blocked_domains": [
                    "reddit.com",
                    "quora.com",
                ],
            },
        }
    ],
    tool_choice="required",
    input="Quais mudanças recentes afetam a criação de ambientes virtuais?",
)
</code></pre>
<p>Para perguntas locais, acrescente uma localização aproximada. Isso é útil para legislação regional, eventos, serviços e recomendações geográficas:</p>
<pre><code class="language-python">tool = {
    "type": "web_search",
    "user_location": {
        "type": "approximate",
        "country": "BR",
        "city": "São Paulo",
        "region": "São Paulo",
    },
}
</code></pre>
<p>Envie apenas a precisão necessária. Para uma pesquisa estadual, não há motivo para coletar endereço. Localização é contexto, não prova de que o resultado está correto; valide datas, jurisdição e fonte antes de automatizar uma decisão.</p>
<h2>Recupere todas as fontes consultadas</h2>
<p>O texto final inclui as citações mais relevantes, mas elas não representam necessariamente tudo o que foi consultado. Para auditoria, solicite também <code>web_search_call.action.sources</code>:</p>
<pre><code class="language-python">response = client.responses.create(
    model="gpt-5.6",
    tools=[{"type": "web_search"}],
    include=["web_search_call.action.sources"],
    tool_choice="required",
    input="Pesquise a situação atual do suporte ao Python 3.13.",
)

data = response.model_dump()

for item in data.get("output", []):
    if item.get("type") != "web_search_call":
        continue

    action = item.get("action") or {}
    for source in action.get("sources", []):
        print(source.get("url"))
</code></pre>
<p>Armazene a consulta, o horário, o modelo, os domínios permitidos e as URLs retornadas. Isso permite reproduzir uma decisão, investigar uma resposta ruim e detectar quando uma fonte mudou. Não salve páginas inteiras indiscriminadamente: registre somente o necessário e respeite sua política de retenção.</p>
<h2>Transforme as anotações em citações clicáveis</h2>
<p>Quando a pesquisa é usada, a saída contém um item <code>message</code>. Dentro do trecho <code>output_text</code>, o campo <code>annotations</code> informa o título, a URL e a posição da citação no texto. A interface precisa apresentar essas referências de forma visível e clicável — não esconda as fontes em um log técnico.</p>
<pre><code class="language-python">def extrair_citacoes(response):
    citacoes = []
    data = response.model_dump()

    for item in data.get("output", []):
        if item.get("type") != "message":
            continue

        for part in item.get("content", []):
            if part.get("type") != "output_text":
                continue

            for annotation in part.get("annotations", []):
                if annotation.get("type") == "url_citation":
                    citacoes.append({
                        "titulo": annotation.get("title"),
                        "url": annotation.get("url"),
                        "inicio": annotation.get("start_index"),
                        "fim": annotation.get("end_index"),
                    })

    return citacoes
</code></pre>
<p>No front-end, valide o protocolo da URL, escape título e endereço e abra links externos com <code>rel="noopener noreferrer"</code>. Se você gerar HTML, não aceite marcação arbitrária produzida pelo modelo. Uma alternativa segura é renderizar o texto como conteúdo comum e criar a lista de referências usando somente os objetos estruturados de anotação.</p>
<h2>Proteja custo, qualidade e comportamento em produção</h2>
<p>Pesquisa na Web adiciona latência e custo de ferramenta. Não a acione em perguntas atemporais que seu sistema já responde com segurança. Defina um orçamento por requisição, limite tentativas e use cache por consulta quando a necessidade de atualização permitir. Em caso de timeout, mostre que a pesquisa falhou; não transforme uma resposta sem fonte em uma resposta “atual”.</p>
<p>Também trate o conteúdo recuperado como dado não confiável. Uma página pode conter instruções maliciosas, publicidade disfarçada ou afirmações sem evidência. Diga explicitamente ao modelo para usar as páginas como fontes, nunca como instruções; filtre domínios em fluxos sensíveis; e exija confirmação humana antes de pagamentos, exclusões ou mudanças de permissão.</p>
<p>Monitore pelo menos: taxa de pesquisas acionadas, tempo total, número de fontes, domínios mais citados, respostas sem citação e feedback do usuário. Qualidade não é “a resposta parece boa”; é a capacidade de verificar o caminho entre pergunta, fonte e conclusão.</p>
<h2>Checklist antes de colocar a pesquisa no ar</h2>
<ul>
<li>A chave da API permanece somente no servidor.</li>
<li>O projeto usa <code>web_search</code>, e não a variante preview em uma integração nova.</li>
<li><code>tool_choice</code> corresponde ao requisito: automático ou obrigatório.</li>
<li>Domínios primários são priorizados nos fluxos sensíveis.</li>
<li>Citações aparecem visíveis e clicáveis para o usuário.</li>
<li>A lista completa de fontes é registrada quando auditoria é necessária.</li>
<li>URLs e textos são escapados antes de entrar no HTML.</li>
<li>Timeout, cache, custo máximo e fallback estão definidos.</li>
<li>Conteúdo recuperado nunca recebe autorização para executar ações.</li>
</ul>
<h3>Próximo passo: transforme pesquisa em evidência auditável</h3>
<p>Comece com uma única consulta real do seu produto. Force a pesquisa, restrinja as fontes a domínios confiáveis, exiba as citações e registre as URLs consultadas. Depois compare a resposta com uma revisão humana. Esse ciclo simples revela problemas de consulta, cobertura e apresentação antes que a ferramenta seja conectada a decisões importantes.</p>
<p>O Web Search resolve a atualização da informação; ele não elimina sua responsabilidade sobre a qualidade. Quando combinado com <a href="https://asllanmaciel.com.br/saidas-estruturadas-ia-json-automacoes-python/">saídas estruturadas</a>, validação e observabilidade, torna-se uma peça sólida para construir aplicações que explicam não apenas <em>o que</em> responderam, mas <em>em quais fontes</em> se apoiaram.</p>
<p><strong>Fontes oficiais:</strong> <a href="https://developers.openai.com/api/docs/guides/tools-web-search" target="_blank" rel="noopener noreferrer">guia de Web Search da OpenAI</a> e <a href="https://developers.openai.com/api/docs/guides/tools" target="_blank" rel="noopener noreferrer">visão geral de ferramentas da Responses API</a>.</p>
<p>O post <a href="https://asllanmaciel.com.br/web-search-ia-python-fontes-citacoes/">Web Search com IA em Python: respostas atuais com fontes verificáveis</a> apareceu primeiro em <a href="https://asllanmaciel.com.br">Asllan Maciel | Tecnologia, IA e Produtos Digitais</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://asllanmaciel.com.br/web-search-ia-python-fontes-citacoes/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		
		<series:name><![CDATA[Python + IA: Fundamentos e Projetos Práticos]]></series:name>
	</item>
		<item>
		<title>Proposta de valor: transforme entrevistas em uma oferta clara</title>
		<link>https://asllanmaciel.com.br/proposta-valor-entrevistas-oferta-clara/</link>
					<comments>https://asllanmaciel.com.br/proposta-valor-entrevistas-oferta-clara/#comments</comments>
		
		<dc:creator><![CDATA[Asllan Maciel]]></dc:creator>
		<pubDate>Mon, 10 Aug 2026 22:38:19 +0000</pubDate>
				<category><![CDATA[Marketing Digital]]></category>
		<category><![CDATA[Empreendedorismo]]></category>
		<category><![CDATA[Value Proposition Canvas]]></category>
		<category><![CDATA[proposta de valor]]></category>
		<category><![CDATA[pesquisa com clientes]]></category>
		<category><![CDATA[validação de oferta]]></category>
		<category><![CDATA[empreendedorismo]]></category>
		<guid isPermaLink="false">https://asllanmaciel.com.br/?p=5052</guid>

					<description><![CDATA[<p>Transforme entrevistas de clientes em uma proposta de valor clara, priorizada e testável, conectando dores, ganhos, solução e mensagem de venda.</p>
<p>O post <a href="https://asllanmaciel.com.br/proposta-valor-entrevistas-oferta-clara/">Proposta de valor: transforme entrevistas em uma oferta clara</a> apareceu primeiro em <a href="https://asllanmaciel.com.br">Asllan Maciel | Tecnologia, IA e Produtos Digitais</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Entrevistar clientes não cria valor por si só. O resultado aparece quando você transforma relatos dispersos em uma decisão clara: <strong>para quem a oferta existe, qual problema prioritário resolve e por que alguém escolheria essa solução agora</strong>. Sem essa síntese, a equipe acumula anotações, mantém todas as ideias e volta a comunicar o produto por uma lista de funcionalidades.</p>
<p>Nesta aula, vamos partir das evidências coletadas na <a href="https://asllanmaciel.com.br/entrevista-problema-descobrir-dores-reais/">entrevista de problema</a> e construir uma proposta de valor que possa ser explicada, entregue e testada. O objetivo não é encontrar uma frase bonita. É criar uma hipótese de valor específica o bastante para orientar produto, marketing e venda.</p>
<h2>Transforme entrevistas em um perfil de cliente</h2>
<p>Comece reunindo somente evidências de um segmento. A estrutura do Value Proposition Canvas organiza o perfil em três partes: os trabalhos que o cliente tenta realizar, as dores que dificultam esse progresso e os ganhos que ele deseja obter. “Trabalho” não significa apenas uma tarefa operacional; pode existir uma dimensão funcional, social ou emocional.</p>
<p>Um dono de pequeno e-commerce, por exemplo, pode querer responder clientes rapidamente — trabalho funcional —, manter a reputação da loja — trabalho social — e terminar o dia sem a sensação de que esqueceu uma reclamação — trabalho emocional. A mesma solução pode contribuir para as três dimensões, mas a pesquisa deve revelar qual delas realmente move a decisão.</p>
<p>Revise as entrevistas e converta cada trecho relevante em uma nota curta:</p>
<ul>
<li><strong>Trabalho:</strong> o que a pessoa tenta concluir ou melhorar?</li>
<li><strong>Dor:</strong> qual obstáculo, custo, risco ou frustração aparece?</li>
<li><strong>Ganho:</strong> qual resultado ela espera, valoriza ou considera superior?</li>
<li><strong>Evidência:</strong> qual comportamento, situação ou consequência sustenta a nota?</li>
</ul>
<p>Prefira fatos como “perde duas horas por dia copiando respostas” a rótulos vagos como “quer produtividade”. Preserve as palavras usadas pelo cliente em um campo separado; elas serão úteis para a comunicação. Não converta um elogio à sua ideia em evidência de compra.</p>
<h2>Escolha um segmento e priorize o que realmente importa</h2>
<p>Uma proposta para “empreendedores que querem crescer” é ampla demais para orientar qualquer decisão. Separe perfis com contexto, urgência e critérios de compra diferentes. Usuário e pagador também podem precisar de mapas distintos. A própria Strategyzer aponta que misturar vários segmentos no mesmo perfil dificulta identificar as prioridades e desenhar uma proposta convincente.</p>
<p>Depois de agrupar notas semelhantes, ordene cada trabalho, dor e ganho. Use quatro perguntas práticas:</p>
<ol>
<li>Com que frequência essa situação aparece nas entrevistas?</li>
<li>Qual é a intensidade da consequência em tempo, dinheiro, risco ou estresse?</li>
<li>O cliente já tenta resolver o problema? Como?</li>
<li>Existe orçamento, autoridade e urgência para mudar agora?</li>
</ol>
<p>Frequência sem intensidade pode indicar uma irritação pequena. Intensidade sem comportamento pode revelar um problema raro ou ainda não prioritário. Procure a combinação de recorrência, consequência e tentativa real de solução. Registre também evidências contrárias: elas impedem que a equipe selecione apenas falas que confirmam a ideia inicial.</p>
<p>Para o exemplo do e-commerce, imagine que as entrevistas mostrem três sinais repetidos: perguntas chegam por canais diferentes, respostas dependem do dono e atrasos geram cancelamentos. Esse conjunto é mais útil que a afirmação genérica “atendimento dá trabalho”.</p>
<h2>Conecte dores e ganhos ao que sua oferta entrega</h2>
<p>Agora construa o mapa de valor. Liste os produtos e serviços da oferta, como eles aliviam dores específicas e como criam ganhos relevantes. O ponto central é o encaixe: cada componente importante deve responder a uma prioridade observada no perfil do cliente.</p>
<p>Uma automação de atendimento poderia incluir triagem das mensagens, base de respostas aprovadas e encaminhamento para uma pessoa quando houver exceção. Esses componentes não são valiosos por existirem; são valiosos quando:</p>
<ul>
<li>reduzem o tempo gasto copiando respostas;</li>
<li>diminuem o risco de uma reclamação ficar sem retorno;</li>
<li>mantêm consistência entre canais;</li>
<li>liberam o dono para tratar apenas casos que exigem decisão.</li>
</ul>
<p>Não tente ligar a oferta a todas as dores e ganhos do mapa. A recomendação oficial do Value Proposition Canvas é concentrar-se no que é mais importante para o cliente. Uma proposta forte escolhe; uma proposta que promete resolver tudo geralmente fica genérica e difícil de comprovar.</p>
<h2>Escreva uma proposta de valor que possa ser entendida</h2>
<p>Com as prioridades definidas, transforme o mapa em uma frase de trabalho. Use o modelo abaixo como diagnóstico, não como slogan obrigatório:</p>
<blockquote>
<p>Para <strong>[segmento em uma situação específica]</strong> que precisa <strong>[trabalho prioritário]</strong>, nossa oferta ajuda a <strong>[resultado relevante]</strong> ao <strong>[mecanismo concreto]</strong>, sem <strong>[dor ou risco da alternativa atual]</strong>.</p>
</blockquote>
<p>No exemplo:</p>
<blockquote>
<p>Para pequenos e-commerces cujo atendimento ainda depende do dono, implementamos uma operação assistida que organiza mensagens e sugere respostas aprovadas, reduzindo atrasos sem deixar casos sensíveis nas mãos de uma automação sem supervisão.</p>
</blockquote>
<p>A frase identifica segmento, situação, resultado, mecanismo e limite. Ela é mais confiável que “revolucione seu atendimento com inteligência artificial”, porque mostra o que muda e como. Evite números que ainda não foram medidos. Quando houver prova, substitua adjetivos por resultados verificáveis.</p>
<p>Teste a clareza com três perguntas: alguém do segmento reconhece o próprio contexto? Entende o resultado sem uma explicação adicional? Consegue perceber por que essa abordagem é diferente da alternativa atual? Se a resposta for não, volte ao mapa — trocar palavras no título não corrige uma hipótese de valor difusa.</p>
<h2>Converta a proposta em mensagem e oferta</h2>
<p>A proposta de valor orienta a comunicação, mas não precisa aparecer inteira como manchete. Em uma página simples, distribua seus elementos em uma sequência:</p>
<ol>
<li><strong>Contexto:</strong> mostre a situação que o cliente reconhece.</li>
<li><strong>Resultado:</strong> descreva a mudança desejada com linguagem concreta.</li>
<li><strong>Mecanismo:</strong> explique como a entrega produz essa mudança.</li>
<li><strong>Prova:</strong> apresente demonstração, caso, amostra ou evidência disponível.</li>
<li><strong>Próximo passo:</strong> convide para uma ação proporcional ao estágio da oferta.</li>
</ol>
<p>Se o produto ainda está em validação, a prova pode ser uma demonstração manual, um protótipo ou a transparência de um <a href="https://asllanmaciel.com.br/mvp-concierge-vender-aprender-antes-automatizar/">MVP concierge</a>. Não invente depoimentos nem apresente estimativas como resultados garantidos. Credibilidade nasce do alinhamento entre promessa, mecanismo e evidência.</p>
<p>A oferta também inclui escopo, prazo, participação do cliente, preço e redução de risco. Uma mensagem atraente sem uma entrega delimitada gera expectativas incompatíveis. Antes de anunciar, escreva claramente o que está incluído, o que não está e qual condição define sucesso.</p>
<h2>Teste a proposta antes de ampliar o investimento</h2>
<p>O canvas e a frase representam hipóteses. A Strategyzer recomenda testar a proposta porque o encaixe desenhado ainda não prova que o cliente se importa o suficiente para comprar. Use um experimento pequeno e defina antecipadamente qual comportamento contará como evidência.</p>
<p>Você pode criar duas versões de uma página, variar apenas a prioridade da mensagem e levar cada uma ao mesmo segmento. Outra opção é apresentar a proposta em conversas de venda e observar perguntas, objeções e avanço para o próximo passo. Para uma oferta nova, uma reserva, diagnóstico pago ou piloto fornece sinal mais forte que curtidas e elogios.</p>
<p>Registre uma hipótese no formato: “Acreditamos que <em>[segmento]</em> avançará para <em>[ação]</em> quando apresentarmos <em>[proposta]</em>, porque <em>[evidência]</em>.” Em seguida, defina volume, prazo e critério de decisão. Se o teste falhar, descubra qual parte está errada: segmento, prioridade, mecanismo, prova, preço ou canal.</p>
<p>Esse processo continua o trabalho de <a href="https://asllanmaciel.com.br/validar-oferta-digital-antes-de-criar-produto/">validar a oferta antes de construir</a>. A meta não é defender a primeira frase, mas aprender qual promessa sustentável merece virar produto e campanha.</p>
<h2>Checklist para sair do mapa e chegar ao mercado</h2>
<ul>
<li>Use evidências de um segmento por vez.</li>
<li>Separe trabalhos, dores, ganhos e fatos observados.</li>
<li>Priorize recorrência, intensidade, comportamento e urgência.</li>
<li>Conecte cada componente da oferta a uma prioridade real.</li>
<li>Escolha o que não será resolvido nesta versão.</li>
<li>Escreva segmento, resultado, mecanismo e risco evitado.</li>
<li>Transforme a proposta em mensagem, prova e próximo passo.</li>
<li>Defina o comportamento que validará ou rejeitará a hipótese.</li>
<li>Atualize o mapa com evidências novas, inclusive as contrárias.</li>
</ul>
<p>Uma boa proposta de valor não nasce de criatividade isolada. Ela é a síntese entre o progresso que um segmento busca, as dificuldades que enfrenta e uma entrega capaz de produzir um resultado relevante. Quando essa conexão está clara, produto, conteúdo e venda passam a contar a mesma história.</p>
<p>Na próxima etapa, transforme a proposta priorizada em uma página de teste e uma oferta-piloto. Continue a série <a href="https://asllanmaciel.com.br/series/negocios-digitais-na-pratica/">Negócios Digitais na Prática: da Ideia às Primeiras Vendas</a> para avançar da evidência à primeira venda com menos desperdício.</p>
<p><strong>Referências:</strong> <a href="https://www.strategyzer.com/library/the-value-proposition-canvas" rel="nofollow noopener" target="_blank">Value Proposition Canvas oficial</a>, <a href="https://www.strategyzer.com/library/5-common-mistakes-to-avoid-when-using-the-value-proposition-canvas" rel="nofollow noopener" target="_blank">erros comuns no uso do canvas</a> e <a href="https://www.strategyzer.com/library/how-to-acquire-customers-using-online-ads-that-connects-to-your-value-proposition-canvas" rel="nofollow noopener" target="_blank">teste de proposta de valor</a>.</p>
<p>O post <a href="https://asllanmaciel.com.br/proposta-valor-entrevistas-oferta-clara/">Proposta de valor: transforme entrevistas em uma oferta clara</a> apareceu primeiro em <a href="https://asllanmaciel.com.br">Asllan Maciel | Tecnologia, IA e Produtos Digitais</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://asllanmaciel.com.br/proposta-valor-entrevistas-oferta-clara/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		
		<series:name><![CDATA[Negócios Digitais na Prática: da Ideia às Primeiras Vendas]]></series:name>
	</item>
		<item>
		<title>File Search com IA em Python: consulte seus documentos na prática</title>
		<link>https://asllanmaciel.com.br/file-search-ia-python-documentos-responses-api/</link>
					<comments>https://asllanmaciel.com.br/file-search-ia-python-documentos-responses-api/#respond</comments>
		
		<dc:creator><![CDATA[Asllan Maciel]]></dc:creator>
		<pubDate>Mon, 10 Aug 2026 15:38:15 +0000</pubDate>
				<category><![CDATA[Guia para Iniciantes]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[Cursos]]></category>
		<category><![CDATA[vector store]]></category>
		<category><![CDATA[File Search]]></category>
		<category><![CDATA[Responses API]]></category>
		<category><![CDATA[OpenAI API]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[inteligência artificial]]></category>
		<guid isPermaLink="false">https://asllanmaciel.com.br/?p=5049</guid>

					<description><![CDATA[<p>Aprenda a usar File Search na Responses API para consultar documentos com IA, vector stores, citações e filtros em um projeto Python prático.</p>
<p>O post <a href="https://asllanmaciel.com.br/file-search-ia-python-documentos-responses-api/">File Search com IA em Python: consulte seus documentos na prática</a> apareceu primeiro em <a href="https://asllanmaciel.com.br">Asllan Maciel | Tecnologia, IA e Produtos Digitais</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Uma IA pode escrever bem e ainda assim responder com informações desatualizadas, porque o modelo não conhece automaticamente os manuais, políticas e documentos internos da sua aplicação. O <strong>File Search</strong> resolve esse problema ao permitir que a Responses API pesquise uma base de arquivos antes de produzir a resposta.</p>
<p>Nesta aula, você vai criar uma pequena central de suporte em Python. O sistema receberá um manual, localizará os trechos relevantes e responderá com referências ao arquivo consultado. É uma evolução natural depois de aprender <a href="https://asllanmaciel.com.br/function-calling-python-ia-ferramentas-seguranca/">function calling em Python</a>: em vez de executar uma função externa, o modelo usará uma ferramenta hospedada para recuperar conhecimento.</p>
<h2>O que o File Search faz — e quando vale a pena usar</h2>
<p>O File Search é uma ferramenta da Responses API que combina busca semântica e busca por palavras-chave. Os arquivos são organizados em um <em>vector store</em>, processados e recuperados conforme a pergunta. A ferramenta é hospedada pela OpenAI, portanto você não precisa implementar manualmente geração de embeddings, indexação, comparação vetorial e montagem do contexto.</p>
<p>Use esse recurso quando a resposta depender de uma coleção de documentos: central de ajuda, políticas comerciais, procedimentos operacionais, catálogo técnico, contratos padronizados ou documentação de produto. Ele é diferente de enviar um arquivo isolado em toda requisição: o vector store cria uma base reutilizável e evita reenviar o mesmo conteúdo a cada pergunta.</p>
<p>Também não é o mesmo que <a href="https://asllanmaciel.com.br/function-calling-python-ia-ferramentas-seguranca/">function calling</a>. File Search <strong>consulta conhecimento</strong>; function calling <strong>executa uma ação</strong>, como buscar um pedido no banco ou abrir um chamado. Em uma aplicação real, as duas ferramentas podem trabalhar juntas.</p>
<h2>Prepare o projeto e um documento de teste</h2>
<p>Crie uma pasta vazia, configure um ambiente virtual e instale o SDK oficial. Se você ainda organiza dependências manualmente, veja também o guia de <a href="https://asllanmaciel.com.br/python-uv-pyproject-ambientes-reproduziveis/">Python com uv e pyproject.toml</a>.</p>
<pre><code>uv init suporte-file-search
cd suporte-file-search
uv add openai python-dotenv</code></pre>
<p>Salve sua chave em um arquivo <code>.env</code> que não será enviado ao Git:</p>
<pre><code>OPENAI_API_KEY=sua_chave_aqui</code></pre>
<p>Agora crie <code>manual-suporte.txt</code>. Em produção, o conteúdo virá de documentos reais; aqui usaremos regras simples para conseguir verificar a qualidade da recuperação.</p>
<pre><code>POLÍTICA DE TROCAS — versão 3, agosto de 2026

Produtos físicos podem ser trocados em até 30 dias após o recebimento.
O item deve estar sem sinais de uso e acompanhado da nota fiscal.
Produtos digitais não são reembolsáveis após o primeiro acesso.
Casos de cobrança duplicada devem ser analisados em até 2 dias úteis.
O atendimento humano funciona de segunda a sexta, das 9h às 18h.</code></pre>
<p>Documentos com títulos claros, datas, seções curtas e linguagem consistente costumam produzir buscas melhores. Evite misturar versões conflitantes no mesmo arquivo sem identificar qual regra está vigente.</p>
<h2>Envie o arquivo e crie o vector store</h2>
<p>O primeiro script envia o documento pela Files API, cria o vector store e associa o arquivo à base. A documentação atual utiliza <code>purpose="assistants"</code> no upload. Depois da associação, aguarde o processamento antes de liberar perguntas na aplicação.</p>
<pre><code>import os
import time
from dotenv import load_dotenv
from openai import OpenAI

load_dotenv()
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])

with open("manual-suporte.txt", "rb") as documento:
    arquivo = client.files.create(
        file=documento,
        purpose="assistants",
    )

base = client.vector_stores.create(name="Manual de suporte")

vinculo = client.vector_stores.files.create(
    vector_store_id=base.id,
    file_id=arquivo.id,
)

while vinculo.status == "in_progress":
    time.sleep(2)
    vinculo = client.vector_stores.files.retrieve(
        vector_store_id=base.id,
        file_id=arquivo.id,
    )

if vinculo.status != "completed":
    raise RuntimeError(f"Falha ao indexar: {vinculo.status}")

print("VECTOR_STORE_ID=", base.id)</code></pre>
<p>Guarde o identificador da base em uma variável de ambiente. Não recrie o vector store em toda execução: além de duplicar conteúdo, isso dificulta controle de versões e custos. Em um fluxo de implantação, a indexação deve ser uma etapa separada da aplicação que responde aos usuários.</p>
<h2>Faça uma pergunta com a Responses API</h2>
<p>Com a base pronta, inclua a ferramenta <code>file_search</code> e informe os vector stores permitidos. O parâmetro <code>max_num_results</code> limita quantos resultados serão recuperados; valores menores podem reduzir latência e tokens, mas um limite agressivo pode retirar contexto importante.</p>
<pre><code>import os
from dotenv import load_dotenv
from openai import OpenAI

load_dotenv()
client = OpenAI()

response = client.responses.create(
    model="gpt-5.6",
    input=(
        "Responda somente com base no manual. "
        "Qual é o prazo para troca de um produto físico e "
        "quais condições precisam ser atendidas?"
    ),
    tools=[{
        "type": "file_search",
        "vector_store_ids": [os.environ["VECTOR_STORE_ID"]],
        "max_num_results": 3,
    }],
    include=["file_search_call.results"],
)

print(response.output_text)</code></pre>
<p>A resposta deverá mencionar os 30 dias, a ausência de sinais de uso e a nota fiscal. A saída também contém uma chamada <code>file_search_call</code> e uma mensagem com anotações do tipo <code>file_citation</code>. O parâmetro <code>include</code> acrescenta os resultados recuperados ao objeto retornado, algo útil para depuração, auditoria e avaliação.</p>
<p>Não confunda “há citação” com “a resposta está correta”. Exiba a fonte para o usuário e compare a afirmação com o trecho recuperado. Se sua automação precisa devolver dados estruturados para outro sistema, combine esta etapa com <a href="https://asllanmaciel.com.br/saidas-estruturadas-ia-json-automacoes-python/">Structured Outputs e JSON validado</a>.</p>
<h2>Melhore relevância, escopo e segurança</h2>
<p>A maior parte dos problemas de busca nasce na organização da base, não no prompt. Separe documentação por produto ou cliente, remova duplicatas e mantenha apenas versões vigentes. Em aplicações multiempresa, nunca dependa do texto da pergunta para isolar dados: use vector stores separados por tenant ou filtros de metadados controlados pelo servidor.</p>
<p>Os filtros permitem restringir resultados por atributos como categoria, região, versão ou status. Isso evita que uma pergunta sobre a política brasileira recupere uma regra de outro país. A escolha do filtro deve vir da identidade autenticada e das permissões da aplicação, e não de parâmetros livres enviados pelo navegador.</p>
<pre><code>tools=[{
    "type": "file_search",
    "vector_store_ids": [os.environ["VECTOR_STORE_ID"]],
    "filters": {
        "type": "in",
        "key": "categoria",
        "value": ["suporte", "politicas_vigentes"],
    },
}]</code></pre>
<p>Trate os documentos como dados sensíveis. Não faça upload de segredos, chaves, senhas ou informações pessoais sem necessidade e base legal. Defina responsáveis pela atualização, política de retenção e processo de exclusão. Registre qual versão do arquivo sustentou cada resposta importante.</p>
<h2>Teste a qualidade antes de colocar em produção</h2>
<p>Monte um conjunto de perguntas com respostas esperadas. Inclua casos fáceis, ambiguidades, informação inexistente e perguntas que deveriam ser recusadas. Avalie separadamente recuperação e geração: primeiro confirme se o trecho correto apareceu nos resultados; depois verifique se o modelo o interpretou sem inventar condições.</p>
<p>Um teste útil para este exemplo contém pelo menos estas perguntas:</p>
<ul>
<li>Qual é o prazo de troca para produto físico?</li>
<li>Um produto digital acessado pode ser reembolsado?</li>
<li>Em quanto tempo a cobrança duplicada é analisada?</li>
<li>O suporte funciona no sábado?</li>
<li>Qual é o prazo de garantia estendida? — a base não informa isso.</li>
</ul>
<p>Para perguntas sem resposta documental, instrua o modelo a declarar a ausência da informação e encaminhar o caso. Monitore latência, quantidade de resultados, taxa de respostas fundamentadas e dúvidas que chegam ao atendimento humano. Ajuste <code>max_num_results</code> com dados reais, não por intuição.</p>
<h2>Checklist de implementação e próximo passo</h2>
<ul>
<li>Crie um vector store por domínio de conhecimento ou limite de acesso.</li>
<li>Envie documentos limpos, versionados e com títulos descritivos.</li>
<li>Aguarde a indexação terminar antes de aceitar consultas.</li>
<li>Defina explicitamente os vector stores e filtros permitidos no servidor.</li>
<li>Inclua os resultados durante testes para inspecionar a recuperação.</li>
<li>Mostre citações e ofereça escalonamento quando a base não responder.</li>
<li>Teste perguntas conhecidas, negativas, ambíguas e adversariais.</li>
<li>Revise retenção, exclusão, custos e permissões periodicamente.</li>
</ul>
<p>O File Search transforma uma coleção de documentos em uma fonte consultável pela IA sem exigir que você construa toda a infraestrutura de recuperação. O ganho real, porém, vem da disciplina: base bem governada, acesso restrito, perguntas de avaliação e fontes visíveis.</p>
<p>Como próximo passo, adapte o exemplo a um manual real e crie dez perguntas de teste antes de conectá-lo a uma interface. Continue acompanhando a série <a href="https://asllanmaciel.com.br/series/python-ia/">Python + IA: Fundamentos e Projetos Práticos</a> para integrar essa busca a fluxos mais completos.</p>
<p><strong>Referências oficiais:</strong> <a href="https://developers.openai.com/api/docs/guides/tools-file-search" rel="nofollow noopener" target="_blank">File Search na Responses API</a> e <a href="https://developers.openai.com/api/docs/guides/retrieval" rel="nofollow noopener" target="_blank">Retrieval e vector stores</a>.</p>
<p>O post <a href="https://asllanmaciel.com.br/file-search-ia-python-documentos-responses-api/">File Search com IA em Python: consulte seus documentos na prática</a> apareceu primeiro em <a href="https://asllanmaciel.com.br">Asllan Maciel | Tecnologia, IA e Produtos Digitais</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://asllanmaciel.com.br/file-search-ia-python-documentos-responses-api/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		
		<series:name><![CDATA[Python + IA: Fundamentos e Projetos Práticos]]></series:name>
	</item>
		<item>
		<title>Function calling em Python: conecte a IA a ferramentas com segurança</title>
		<link>https://asllanmaciel.com.br/function-calling-python-ia-ferramentas-seguranca/</link>
					<comments>https://asllanmaciel.com.br/function-calling-python-ia-ferramentas-seguranca/#respond</comments>
		
		<dc:creator><![CDATA[Asllan Maciel]]></dc:creator>
		<pubDate>Mon, 10 Aug 2026 11:36:08 +0000</pubDate>
				<category><![CDATA[Guia para Iniciantes]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[Cursos]]></category>
		<category><![CDATA[OpenAI API]]></category>
		<category><![CDATA[function calling]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[automação]]></category>
		<category><![CDATA[inteligência artificial]]></category>
		<guid isPermaLink="false">https://asllanmaciel.com.br/?p=5046</guid>

					<description><![CDATA[<p>Aprenda a usar function calling na Responses API para permitir que uma IA consulte dados e acione funções Python com validação e controle.</p>
<p>O post <a href="https://asllanmaciel.com.br/function-calling-python-ia-ferramentas-seguranca/">Function calling em Python: conecte a IA a ferramentas com segurança</a> apareceu primeiro em <a href="https://asllanmaciel.com.br">Asllan Maciel | Tecnologia, IA e Produtos Digitais</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Uma IA que apenas escreve texto é útil. Uma IA que consulta um pedido, calcula um frete ou busca dados do seu sistema pode participar de fluxos reais. O recurso que conecta esses dois mundos é o <em>function calling</em>: o modelo identifica quando precisa de uma ferramenta, devolve uma solicitação estruturada e deixa seu código Python decidir se e como a função será executada.</p>
<p>Nesta aula 33 da série <a href="https://asllanmaciel.com.br/series/python-ia/">Python + IA: Fundamentos e Projetos Práticos</a>, vamos construir um assistente que consulta o status de um pedido. O exemplo usa a Responses API, esquema estrito, lista de funções permitidas e validação antes da execução. A implementação segue o fluxo atual da <a href="https://developers.openai.com/api/docs/guides/function-calling" rel="noopener" target="_blank">documentação oficial de function calling da OpenAI</a>.</p>
<h2>Do JSON estruturado para uma ação controlada</h2>
<p>Na aula anterior, vimos como gerar <a href="https://asllanmaciel.com.br/saidas-estruturadas-ia-json-automacoes-python/">JSON confiável com saídas estruturadas</a>. Ali, o formato organiza a resposta final do modelo. No function calling, o JSON tem outra função: descrever uma solicitação para que a sua aplicação execute uma ferramenta.</p>
<p>Essa diferença é fundamental. O modelo não chama diretamente o banco de dados e não executa uma função Python por conta própria. Ele pode responder algo equivalente a “use a ferramenta <code>consultar_pedido</code> com o número <code>AM-1042</code>”. Seu programa recebe a solicitação, verifica o nome, valida os argumentos, executa a função permitida e devolve o resultado ao modelo.</p>
<p>O fluxo completo tem cinco etapas:</p>
<ol>
<li>seu código oferece uma lista de ferramentas e seus esquemas;</li>
<li>o usuário faz uma pergunta;</li>
<li>o modelo produz uma chamada de ferramenta quando necessário;</li>
<li>a aplicação valida e executa a função;</li>
<li>o resultado volta ao modelo, que redige a resposta final.</li>
</ol>
<p>A separação mantém a aplicação no controle. O modelo propõe; o código autoriza e executa.</p>
<h2>Prepare o projeto e crie a função local</h2>
<p>Você pode continuar o ambiente organizado com <a href="https://asllanmaciel.com.br/python-uv-pyproject-ambientes-reproduziveis/">uv e pyproject.toml</a>. No terminal, crie um projeto e instale o SDK:</p>
<pre><code>uv init assistente-pedidos
cd assistente-pedidos
uv add openai</code></pre>
<p>Configure <code>OPENAI_API_KEY</code> no ambiente, sem gravar a chave no arquivo Python. Em seguida, crie uma fonte de dados local para o tutorial:</p>
<pre><code class="language-python">PEDIDOS = {
    "AM-1042": {"status": "em transporte", "previsao": "12/08/2026"},
    "AM-1057": {"status": "separando itens", "previsao": "13/08/2026"},
}


def consultar_pedido(numero: str) -&gt; dict:
    pedido = PEDIDOS.get(numero)
    if pedido is None:
        return {"encontrado": False, "numero": numero}

    return {
        "encontrado": True,
        "numero": numero,
        **pedido,
    }</code></pre>
<p>Em produção, essa função poderia consultar uma API interna. Para aprender o fluxo, o dicionário em memória elimina dependências e deixa claro onde termina a IA e começa a regra de negócio.</p>
<h2>Descreva a ferramenta com um esquema estrito</h2>
<p>O modelo precisa conhecer o nome da função, sua finalidade e os argumentos aceitos. Na Responses API, a ferramenta pode ser descrita assim:</p>
<pre><code class="language-python">tools = [
    {
        "type": "function",
        "name": "consultar_pedido",
        "description": "Consulta o status de um pedido pelo número.",
        "strict": True,
        "parameters": {
            "type": "object",
            "properties": {
                "numero": {
                    "type": "string",
                    "description": "Identificador no formato AM-1234",
                }
            },
            "required": ["numero"],
            "additionalProperties": False,
        },
    }
]</code></pre>
<p>Com <code>strict: True</code>, a chamada deve respeitar o esquema. A documentação oficial recomenda o modo estrito e exige que os campos sejam declarados em <code>required</code> e que objetos usem <code>additionalProperties: false</code>. Isso reduz argumentos inesperados, mas não substitui a validação da sua aplicação.</p>
<p>Uma string pode estar correta para o JSON Schema e ainda ser inválida para o negócio. <code>AM-1042</code> atende ao formato esperado; <code>qualquer-coisa</code> continua sendo uma string. Por isso, vamos verificar o padrão antes de consultar os dados.</p>
<h2>Detecte, valide e execute a chamada</h2>
<p>Agora envie a pergunta junto com a definição da ferramenta. Desativaremos chamadas paralelas para que este exemplo aceite no máximo uma função por rodada:</p>
<pre><code class="language-python">import json
import re

from openai import OpenAI

client = OpenAI()

funcoes_permitidas = {
    "consultar_pedido": consultar_pedido,
}

input_list = [
    {"role": "user", "content": "Onde está o pedido AM-1042?"}
]

response = client.responses.create(
    model="gpt-5.6",
    input=input_list,
    tools=tools,
    parallel_tool_calls=False,
)

input_list += response.output

for item in response.output:
    if item.type != "function_call":
        continue

    if item.name not in funcoes_permitidas:
        resultado = {"erro": "ferramenta_nao_permitida"}
    else:
        try:
            argumentos = json.loads(item.arguments)
            numero = argumentos["numero"].strip().upper()

            if not re.fullmatch(r"AM-\d{4}", numero):
                raise ValueError("Número de pedido inválido")

            resultado = funcoes_permitidas[item.name](numero=numero)
        except (KeyError, ValueError, json.JSONDecodeError) as erro:
            resultado = {"erro": str(erro)}

    input_list.append(
        {
            "type": "function_call_output",
            "call_id": item.call_id,
            "output": json.dumps(resultado, ensure_ascii=False),
        }
    )</code></pre>
<p>Nunca use <code>eval()</code> para executar o nome ou os argumentos enviados pelo modelo. O dicionário <code>funcoes_permitidas</code> é uma lista explícita de capacidades. Se aparecer outro nome, a aplicação recusa. O <code>call_id</code> liga o resultado à solicitação correta.</p>
<h2>Devolva o resultado e gere a resposta final</h2>
<p>O retorno de uma ferramenta deve ser uma string; JSON serializado funciona bem porque preserva campos e erros. Depois de adicionar <code>function_call_output</code> à lista, faça uma segunda chamada:</p>
<pre><code class="language-python">final = client.responses.create(
    model="gpt-5.6",
    input=input_list,
    tools=tools,
    instructions=(
        "Responda em português, de forma objetiva. "
        "Não invente status ou previsão ausentes no resultado da ferramenta."
    ),
)

print(final.output_text)</code></pre>
<p>Para o pedido do exemplo, a resposta poderá informar que ele está em transporte e apresentar a previsão. Se o número não existir, o modelo recebe <code>encontrado: false</code> e deve explicar isso, sem criar dados. A qualidade depende tanto das instruções quanto da clareza do resultado devolvido pela função.</p>
<p>Em uma aplicação real, encapsule esse ciclo em uma função ou serviço. Também trate falhas temporárias da API interna, tempo limite e respostas sem chamada de ferramenta. O modelo pode responder diretamente quando não precisa consultar nada.</p>
<h2>Proteja ferramentas com efeitos reais</h2>
<p>Consultar um pedido é uma operação de leitura e oferece um bom primeiro projeto. Cancelar compra, enviar e-mail, emitir reembolso ou alterar cadastro exige controles adicionais. Um argumento bem formatado não prova que o usuário tem permissão para a ação.</p>
<p>Adote estas regras antes de disponibilizar ferramentas de escrita:</p>
<ul>
<li><strong>Autorização fora do modelo:</strong> valide usuário, conta e escopo no backend.</li>
<li><strong>Confirmação explícita:</strong> mostre o efeito, o destinatário e o valor antes de uma ação irreversível.</li>
<li><strong>Idempotência:</strong> use uma chave para impedir reembolsos ou envios duplicados.</li>
<li><strong>Limites:</strong> defina valores máximos, formatos, tempo de execução e quantidade de chamadas.</li>
<li><strong>Logs seguros:</strong> registre ferramenta, resultado e duração, removendo chaves e dados sensíveis.</li>
<li><strong>Privilégio mínimo:</strong> cada ferramenta deve acessar apenas os dados necessários.</li>
</ul>
<p>Também separe ferramentas de leitura das que causam efeitos. Comece com consultas, observe erros reais e só depois adicione ações. Function calling não transforma o modelo em autoridade; ele cria uma interface estruturada entre a intenção do usuário e uma capacidade controlada pelo sistema.</p>
<h2>Checklist prático e próximo passo</h2>
<p>Antes de colocar o fluxo em produção, confirme:</p>
<ul>
<li>o nome e a descrição da ferramenta são específicos;</li>
<li>o esquema usa modo estrito, campos obrigatórios e bloqueio de propriedades extras;</li>
<li>os argumentos passam por validação de formato e regra de negócio;</li>
<li>apenas funções presentes na lista permitida podem ser executadas;</li>
<li>o resultado referencia o <code>call_id</code> recebido;</li>
<li>erros viram respostas controladas, sem expor segredos;</li>
<li>ações sensíveis exigem autorização, confirmação e idempotência;</li>
<li>logs e métricas permitem investigar o fluxo.</li>
</ul>
<p>Execute o exemplo, troque o número do pedido e teste três cenários: pedido existente, identificador inválido e pedido não encontrado. Depois, substitua o dicionário por uma função de leitura do seu próprio sistema. Na próxima evolução, você poderá oferecer mais de uma ferramenta e criar um roteador seguro, mantendo validação e observabilidade em cada chamada.</p>
<p>O post <a href="https://asllanmaciel.com.br/function-calling-python-ia-ferramentas-seguranca/">Function calling em Python: conecte a IA a ferramentas com segurança</a> apareceu primeiro em <a href="https://asllanmaciel.com.br">Asllan Maciel | Tecnologia, IA e Produtos Digitais</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://asllanmaciel.com.br/function-calling-python-ia-ferramentas-seguranca/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		
		<series:name><![CDATA[Python + IA: Fundamentos e Projetos Práticos]]></series:name>
	</item>
		<item>
		<title>Entrevista de problema: como descobrir dores reais sem vender a solução</title>
		<link>https://asllanmaciel.com.br/entrevista-problema-descobrir-dores-reais/</link>
					<comments>https://asllanmaciel.com.br/entrevista-problema-descobrir-dores-reais/#comments</comments>
		
		<dc:creator><![CDATA[Asllan Maciel]]></dc:creator>
		<pubDate>Sun, 09 Aug 2026 22:38:33 +0000</pubDate>
				<category><![CDATA[Marketing Digital]]></category>
		<category><![CDATA[Empreendedorismo]]></category>
		<category><![CDATA[entrevista de problema]]></category>
		<category><![CDATA[negócios digitais]]></category>
		<category><![CDATA[validação de negócio]]></category>
		<category><![CDATA[customer discovery]]></category>
		<category><![CDATA[pesquisa com clientes]]></category>
		<guid isPermaLink="false">https://asllanmaciel.com.br/?p=5028</guid>

					<description><![CDATA[<p>Aprenda a conduzir entrevistas de problema, evitar perguntas enviesadas e transformar conversas com clientes em evidências para sua próxima decisão.</p>
<p>O post <a href="https://asllanmaciel.com.br/entrevista-problema-descobrir-dores-reais/">Entrevista de problema: como descobrir dores reais sem vender a solução</a> apareceu primeiro em <a href="https://asllanmaciel.com.br">Asllan Maciel | Tecnologia, IA e Produtos Digitais</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Uma boa ideia não começa com uma apresentação impecável. Começa quando você entende, com detalhes, como uma pessoa lida hoje com um problema que vale a pena resolver. A entrevista de problema serve exatamente para isso: trocar suposições por evidências antes de investir em produto, campanha ou automação.</p>
<p>Esta é a terceira aula da série <a href="https://asllanmaciel.com.br/series/negocios-digitais-na-pratica/">Negócios Digitais na Prática</a>. Depois de aprender a <a href="https://asllanmaciel.com.br/validar-oferta-digital-antes-de-criar-produto/">validar uma oferta antes de criar o produto</a> e testar a entrega com um <a href="https://asllanmaciel.com.br/mvp-concierge-vender-aprender-antes-automatizar/">MVP concierge</a>, agora vamos melhorar a qualidade do aprendizado: entrevistar clientes sem induzir respostas e transformar conversas em decisões.</p>
<h2>Por que a entrevista vem antes da solução</h2>
<p>Quando alguém se apaixona pela própria ideia, a tendência é procurar confirmação. Perguntas como “você usaria este aplicativo?” ou “pagaria por uma plataforma que economiza tempo?” parecem úteis, mas produzem respostas frágeis. A pessoa pode querer ser gentil, imaginar uma versão perfeita da solução ou dizer que compraria sem enfrentar a decisão real de compra.</p>
<p>A entrevista de problema muda o foco do futuro hipotético para o comportamento passado. Em vez de perguntar se o cliente gostaria de algo, você investiga a última vez em que o problema aconteceu, o que ele fez, quanto tempo perdeu, quais alternativas tentou e o que o impediu de resolver melhor.</p>
<p>O objetivo não é sair da conversa com elogios. É descobrir três pontos: se o problema acontece com frequência, se provoca uma consequência relevante e se a pessoa já investe algum recurso para contorná-lo. Esse recurso pode ser dinheiro, tempo, trabalho manual, risco assumido ou dependência de outra pessoa.</p>
<h2>Escolha quem entrevistar e defina uma hipótese</h2>
<p>Entrevistar “qualquer pessoa” mistura contextos e dificulta enxergar padrões. Comece com um perfil específico e uma situação observável. Por exemplo: “profissionais autônomos que recebem pelo menos dez pedidos de orçamento por mês e ainda organizam o acompanhamento em mensagens e planilhas”.</p>
<p>Antes da primeira conversa, escreva uma hipótese em uma frase:</p>
<blockquote>
<p>Acredito que profissionais autônomos perdem oportunidades porque não conseguem acompanhar propostas e retornos com consistência.</p>
</blockquote>
<p>Em seguida, liste o que precisaria ser verdade para essa hipótese merecer um experimento. Talvez o problema tenha ocorrido nas últimas duas semanas, causado perda de receita ou horas de retrabalho e levado o profissional a criar algum controle improvisado. Esses critérios evitam que uma história isolada pareça validação.</p>
<p>Procure pessoas que viveram a situação recentemente. Clientes atendidos manualmente no MVP concierge são ótimos candidatos, assim como contatos indicados por eles. Cinco entrevistas com o perfil correto ensinam mais do que cinquenta respostas de um público genérico.</p>
<h2>Um roteiro de perguntas que busca comportamento real</h2>
<p>Use um roteiro curto, mas trate a conversa como investigação, não como questionário. Estas sete perguntas funcionam bem em diferentes negócios:</p>
<ol>
<li><strong>Conte sobre a última vez em que isso aconteceu.</strong> Peça uma situação concreta, com começo, meio e fim.</li>
<li><strong>O que desencadeou o problema?</strong> Descubra o evento que torna a necessidade urgente.</li>
<li><strong>Como você resolveu naquele momento?</strong> A solução atual é seu concorrente real, mesmo que seja uma planilha ou trabalho manual.</li>
<li><strong>Qual foi a parte mais difícil?</strong> Explore o custo emocional, operacional ou financeiro.</li>
<li><strong>Quanto tempo ou dinheiro isso consumiu?</strong> Busque uma ordem de grandeza, sem exigir precisão artificial.</li>
<li><strong>O que você já tentou fazer diferente?</strong> Tentativas anteriores revelam prioridade e barreiras.</li>
<li><strong>Quem mais participa da decisão ou é afetado?</strong> Identifique usuários, compradores, influenciadores e bloqueadores.</li>
</ol>
<p>Depois de cada resposta ampla, use perguntas de aprofundamento: “o que aconteceu depois?”, “pode me dar um exemplo?” e “por que isso foi importante?”. O detalhe costuma aparecer na segunda ou terceira camada.</p>
<h2>Como conduzir sem vender sua ideia</h2>
<p>Abra a conversa explicando que você está pesquisando o processo atual e que não há resposta certa. Peça autorização para anotar. Se quiser gravar, solicite consentimento explícito e informe como o arquivo será usado. Uma entrevista de 20 a 30 minutos costuma ser suficiente quando o recorte é claro.</p>
<p>Durante a conversa, fale pouco. Não complete frases, não defenda uma funcionalidade e não transforme cada dor em promessa. Se a pessoa perguntar sobre sua solução, diga que você contará no final, mas que primeiro precisa compreender como ela trabalha hoje.</p>
<p>Evite três armadilhas comuns:</p>
<ul>
<li><strong>Pergunta que contém a resposta:</strong> “Seria melhor receber lembretes automáticos, certo?” Troque por “como você se lembra de fazer o retorno?”.</li>
<li><strong>Pedido de opinião sobre uma ideia:</strong> “o que achou do meu produto?” Troque por perguntas sobre o último episódio do problema.</li>
<li><strong>Excesso de explicação:</strong> se você fala por dez minutos, está apresentando, não entrevistando.</li>
</ul>
<p>Observe contradições sem confrontar. Alguém pode dizer que o problema é urgente e, ao mesmo tempo, nunca ter tentado resolvê-lo. Registre as duas informações. A ausência de ação também é evidência.</p>
<h2>Transforme respostas em evidências comparáveis</h2>
<p>Não confie apenas na memória ou na sensação de que “a conversa foi ótima”. Logo após cada entrevista, registre os mesmos campos: perfil, contexto, episódio recente, solução atual, frequência, impacto, tentativa anterior, barreira, frase marcante e próximo contato.</p>
<p>Separe fatos de interpretações. “Perdeu duas propostas no último mês porque esqueceu o retorno” é fato relatado. “Precisa de um CRM com inteligência artificial” é interpretação. A primeira informação ajuda a decidir; a segunda pode limitar prematuramente as alternativas.</p>
<p>Crie uma matriz simples com as entrevistas nas linhas e os sinais nas colunas. Marque a presença de quatro evidências:</p>
<ul>
<li>o problema ocorreu recentemente;</li>
<li>há impacto mensurável ou consequência relevante;</li>
<li>existe um método atual, ainda que improvisado;</li>
<li>a pessoa aceitou avançar para uma ação concreta.</li>
</ul>
<p>A ação concreta vale mais do que entusiasmo. Pode ser apresentar você a outro profissional, compartilhar um exemplo real, testar um protótipo, reservar horário para uma demonstração ou aceitar uma proposta paga. “Parece interessante” não tem o mesmo peso.</p>
<h2>Decida o próximo experimento</h2>
<p>Depois de cinco a oito entrevistas do mesmo perfil, procure padrões. Se a mesma situação, impacto e solução improvisada aparecem repetidamente, transforme o aprendizado em um experimento pequeno. Você pode oferecer uma entrega manual, criar uma página com uma promessa específica ou testar uma pré-venda com escopo limitado.</p>
<p>Se as dores forem diferentes, não force uma média. Talvez o segmento esteja amplo demais. Recorte por contexto, frequência ou maturidade. Um autônomo com dois orçamentos por mês vive uma realidade diferente de uma pequena agência com cinquenta oportunidades abertas.</p>
<p>Se ninguém tomou qualquer iniciativa para resolver o problema, reavalie a prioridade. Isso não significa que o tema seja irrelevante, mas indica que talvez não sustente uma oferta agora. Voltar à hipótese custa menos do que construir algo que dependerá de muita persuasão para ser usado.</p>
<p>O resultado ideal da entrevista não é uma lista de funcionalidades. É uma decisão mais nítida: aprofundar o mesmo problema, mudar o segmento, testar uma promessa ou abandonar uma hipótese fraca.</p>
<h2>Checklist prático e próximo passo</h2>
<p>Antes de entrevistar, confirme:</p>
<ul>
<li>defini um perfil específico e uma situação recente;</li>
<li>escrevi a hipótese e os sinais que poderiam confirmá-la ou enfraquecê-la;</li>
<li>preparei perguntas sobre fatos passados, não intenções futuras;</li>
<li>reservei mais tempo para ouvir do que para explicar;</li>
<li>criei um modelo único para registrar todas as conversas;</li>
<li>defini uma ação concreta que pode indicar interesse real;</li>
<li>vou comparar padrões antes de escolher funcionalidades.</li>
</ul>
<p>Seu próximo passo é simples: selecione cinco pessoas do mesmo perfil, convide-as para uma conversa de 25 minutos e conduza as entrevistas ao longo de uma semana. Ao final, escolha apenas uma hipótese para testar. Na próxima etapa da série, vamos converter essas evidências em uma proposta de valor específica, compreensível e difícil de confundir com promessas genéricas.</p>
<p>O post <a href="https://asllanmaciel.com.br/entrevista-problema-descobrir-dores-reais/">Entrevista de problema: como descobrir dores reais sem vender a solução</a> apareceu primeiro em <a href="https://asllanmaciel.com.br">Asllan Maciel | Tecnologia, IA e Produtos Digitais</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://asllanmaciel.com.br/entrevista-problema-descobrir-dores-reais/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
		
		<series:name><![CDATA[Negócios Digitais na Prática: da Ideia às Primeiras Vendas]]></series:name>
	</item>
		<item>
		<title>MVP concierge: como vender e aprender antes de automatizar</title>
		<link>https://asllanmaciel.com.br/mvp-concierge-vender-aprender-antes-automatizar/</link>
					<comments>https://asllanmaciel.com.br/mvp-concierge-vender-aprender-antes-automatizar/#comments</comments>
		
		<dc:creator><![CDATA[Asllan Maciel]]></dc:creator>
		<pubDate>Fri, 07 Aug 2026 23:55:26 +0000</pubDate>
				<category><![CDATA[Marketing Digital]]></category>
		<category><![CDATA[Empreendedorismo]]></category>
		<category><![CDATA[automação]]></category>
		<category><![CDATA[produto mínimo viável]]></category>
		<category><![CDATA[MVP concierge]]></category>
		<category><![CDATA[validação]]></category>
		<category><![CDATA[negócios digitais]]></category>
		<guid isPermaLink="false">https://asllanmaciel.com.br/?p=5016</guid>

					<description><![CDATA[<p>Aprenda a entregar um MVP concierge, atender os primeiros clientes manualmente e descobrir o que realmente vale padronizar e automatizar.</p>
<p>O post <a href="https://asllanmaciel.com.br/mvp-concierge-vender-aprender-antes-automatizar/">MVP concierge: como vender e aprender antes de automatizar</a> apareceu primeiro em <a href="https://asllanmaciel.com.br">Asllan Maciel | Tecnologia, IA e Produtos Digitais</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Depois de validar que existe interesse por uma oferta, o erro mais comum é desaparecer por meses para construir uma plataforma completa. Nesse intervalo, as hipóteses continuam sendo hipóteses: você ainda não sabe quais etapas o cliente valoriza, quais dúvidas travam a compra nem onde a entrega exige atenção humana.</p>
<p>O <strong>MVP concierge</strong> resolve esse problema de maneira direta. Em vez de automatizar tudo desde o início, você entrega manualmente uma versão pequena da solução para poucos clientes, acompanha o uso de perto e transforma o aprendizado em um processo repetível. O cliente compra o resultado; a operação, nos bastidores, ainda pode usar planilhas, mensagens e trabalho especializado.</p>
<p>Esta é a parte 2 da série <a href="https://asllanmaciel.com.br/series/negocios-digitais-na-pratica/">Negócios Digitais na Prática: da Ideia às Primeiras Vendas</a>. Se ainda não confirmou a demanda, comece pela aula sobre <a href="https://asllanmaciel.com.br/validar-oferta-digital-antes-de-criar-produto/">como validar uma oferta antes de criar o produto</a>. Aqui, vamos avançar do sinal de interesse para uma entrega real, paga e controlada.</p>
<h2>O que é um MVP concierge e quando usar</h2>
<p>Um MVP concierge é uma versão inicial em que parte relevante da entrega acontece manualmente, embora a experiência do cliente seja organizada como um produto. Você não finge que existe uma tecnologia pronta. Explica o escopo, o prazo e como o serviço funciona, mas evita investir em software antes de entender o trabalho que merece ser automatizado.</p>
<p>Imagine uma solução que cria um plano editorial para pequenos negócios. A visão final pode incluir painel, integrações, geração com IA e calendário automático. No MVP concierge, o cliente responde a um formulário, você analisa o posicionamento, monta o plano com ferramentas existentes e apresenta as recomendações em uma reunião curta. A promessa é a mesma — sair com um plano aplicável —, mas o mecanismo inicial é humano.</p>
<p>Esse formato é útil quando o problema exige descoberta, julgamento ou personalização; quando você ainda não conhece todas as exceções; e quando construir a automação custaria mais do que executar alguns ciclos manualmente. Não é uma desculpa para entregar de qualquer jeito. É um método para aprender com proximidade sem confundir atividade com produto validado.</p>
<h2>Defina uma promessa pequena e verificável</h2>
<p>O MVP precisa de uma transformação clara. “Ajudar empresas a crescer” é amplo demais. “Entregar em 48 horas um diagnóstico de conteúdo com três prioridades e um plano de 14 dias” estabelece resultado, prazo e limite.</p>
<p>Escreva a oferta em uma frase usando esta estrutura:</p>
<blockquote>
<p>Eu ajudo [perfil específico] a alcançar [resultado observável] por meio de [entrega principal], em [prazo], sem [objeção relevante].</p>
</blockquote>
<p>Depois, descreva o que está incluído e o que não está. No exemplo do plano editorial, a primeira versão pode incluir diagnóstico, três pilares, dez ideias e uma revisão. Não inclui publicação, criação de artes, gestão de anúncios nem suporte ilimitado. Esses limites protegem a margem, reduzem mal-entendidos e tornam os ciclos comparáveis.</p>
<p>Escolha também um critério de conclusão. A entrega termina quando o cliente recebe o plano e participa da revisão? Quando aprova as prioridades? Sem esse marco, cada cliente transforma o MVP em um projeto diferente, e você perde a capacidade de aprender sobre um processo comum.</p>
<h2>Desenhe o fluxo manual de ponta a ponta</h2>
<p>Mapeie a experiência antes de vender. Um fluxo simples pode ter seis etapas:</p>
<ol>
<li><strong>Qualificação:</strong> confirme perfil, problema, urgência e capacidade de decisão.</li>
<li><strong>Pagamento:</strong> use um meio confiável e registre condições, prazo e política de cancelamento.</li>
<li><strong>Onboarding:</strong> colete apenas as informações necessárias para começar.</li>
<li><strong>Produção:</strong> execute uma lista de tarefas com responsável e prazo.</li>
<li><strong>Entrega:</strong> apresente o resultado em um formato consistente.</li>
<li><strong>Aprendizado:</strong> registre dúvidas, ajustes, tempo gasto e próximo passo.</li>
</ol>
<p>Para cada etapa, defina entrada, ação e saída. Se o onboarding começa com um formulário, a saída pode ser um briefing completo ou uma solicitação automática de complemento. Se a produção depende de uma entrevista, determine quem agenda, quanto dura e quais perguntas são obrigatórias.</p>
<p>Use ferramentas simples: formulário, agenda, documento, planilha e um quadro de tarefas. A sofisticação agora deve estar na clareza, não na quantidade de aplicativos. O fluxo precisa ser visível para que você descubra onde há espera, retrabalho ou informação faltando.</p>
<h2>Venda o primeiro ciclo com escopo claro</h2>
<p>O objetivo não é distribuir uma amostra indefinidamente. Uma cobrança real testa prioridade, expectativa e disposição para assumir compromisso. O valor pode ser introdutório, desde que cubra a entrega combinada e seja apresentado como condição daquela fase.</p>
<p>Comece com poucos clientes que compartilhem um perfil semelhante. Misturar um profissional autônomo, uma loja local e uma empresa grande pode produzir pedidos incompatíveis e esconder o padrão. Convide pessoas que já demonstraram o problema durante a validação e descreva a proposta sem prometer recursos futuros.</p>
<p>Uma mensagem direta pode seguir este roteiro:</p>
<blockquote>
<p>Estou abrindo poucas vagas para uma primeira versão acompanhada de [solução]. Em [prazo], você recebe [entregáveis]. Como esta fase é próxima e manual, vou pedir feedback em dois momentos. O investimento é [valor] e o escopo inclui [limites].</p>
</blockquote>
<p>Registre a concordância com entregáveis, datas e responsabilidades. Se sua oferta envolve um trabalho técnico, o guia sobre <a href="https://asllanmaciel.com.br/primeiro-cliente-programacao/">como transformar um projeto em proposta para o primeiro cliente</a> ajuda a estruturar esse compromisso sem criar uma apresentação excessiva.</p>
<h2>Aprenda com comportamento, não apenas com elogios</h2>
<p>Uma conversa final é útil, mas o comportamento durante a entrega revela mais. Observe quais perguntas aparecem antes do pagamento, onde o cliente demora a responder, quais partes da entrega ele usa primeiro e quais recomendações viram ação.</p>
<p>Mantenha um diário operacional por ciclo com cinco registros:</p>
<ul>
<li>tempo gasto em cada etapa;</li>
<li>dúvidas e objeções repetidas;</li>
<li>informações que faltaram no onboarding;</li>
<li>ajustes solicitados e sua causa;</li>
<li>resultado ou decisão tomada pelo cliente após a entrega.</li>
</ul>
<p>Faça perguntas específicas. Em vez de “você gostou?”, pergunte: “qual parte você aplicaria amanhã?”, “o que quase fez você desistir?” e “qual etapa ainda depende de explicação?”. Separe pedidos isolados de padrões. Uma sugestão pode ser interessante, mas só deve alterar o produto quando reforçar a promessa central ou se repetir no público escolhido.</p>
<p>A cada ciclo, atualize um documento de decisões: o que permanece, o que muda, o que foi recusado e por quê. Essa memória impede que a operação seja redesenhada pela última conversa.</p>
<h2>Padronize antes de automatizar</h2>
<p>Automatizar um fluxo instável apenas acelera confusão. Primeiro, transforme as partes recorrentes em padrões: roteiro de qualificação, formulário, checklist de produção, modelo de entrega, mensagens de acompanhamento e critérios de qualidade.</p>
<p>Classifique cada atividade em três grupos:</p>
<ul>
<li><strong>Manter humana:</strong> exige julgamento, negociação, empatia ou decisão sensível.</li>
<li><strong>Padronizar:</strong> repete-se, mas ainda está amadurecendo e precisa de checklist.</li>
<li><strong>Automatizar:</strong> possui entrada previsível, regra clara, saída verificável e volume suficiente para justificar o esforço.</li>
</ul>
<p>Por exemplo, enviar confirmação de pagamento e criar uma tarefa são bons candidatos à automação. Interpretar uma objeção complexa ou aprovar uma recomendação estratégica pode continuar humano. Quando chegar a hora de conectar sistemas, consulte o comparativo sobre <a href="https://asllanmaciel.com.br/n8n-ou-programacao-automatizar-processos/">quando usar n8n ou programação</a>.</p>
<p>Antes de automatizar, calcule o benefício concreto: horas poupadas, redução de erro, menor tempo de resposta ou capacidade adicional. Se uma integração leva semanas para economizar poucos minutos em uma etapa rara, ela não é prioridade.</p>
<h2>Checklist para executar seu MVP concierge</h2>
<ul>
<li>Validei que o problema é frequente e relevante para um público específico.</li>
<li>Defini uma promessa observável, prazo, entregáveis e exclusões.</li>
<li>Estabeleci pagamento, capacidade máxima e critério de conclusão.</li>
<li>Mapeei qualificação, onboarding, produção, entrega e feedback.</li>
<li>Preparei modelos simples sem construir uma plataforma antecipadamente.</li>
<li>Selecionei poucos clientes com perfil semelhante.</li>
<li>Registrei tempo, objeções, ajustes e uso real da entrega.</li>
<li>Separei exceções individuais de padrões recorrentes.</li>
<li>Padronizei o processo antes de escolher automações.</li>
<li>Defini o que continuará humano por segurança ou qualidade.</li>
</ul>
<p>O MVP concierge não é o produto final, mas também não é improvisação. Ele é uma operação pequena, transparente e desenhada para produzir duas coisas ao mesmo tempo: valor para o cliente e evidência para o negócio.</p>
<p>Seu próximo passo é escolher uma promessa que possa ser entregue em poucos dias, mapear o fluxo em uma página e convidar os primeiros clientes validados. Execute três ciclos sem adicionar funcionalidades no meio. Ao final, compare o que se repetiu. Essa repetição — e não a ansiedade por parecer escalável — mostrará o que merece virar produto, processo ou automação.</p>
<p>O post <a href="https://asllanmaciel.com.br/mvp-concierge-vender-aprender-antes-automatizar/">MVP concierge: como vender e aprender antes de automatizar</a> apareceu primeiro em <a href="https://asllanmaciel.com.br">Asllan Maciel | Tecnologia, IA e Produtos Digitais</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://asllanmaciel.com.br/mvp-concierge-vender-aprender-antes-automatizar/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
		
		<series:name><![CDATA[Negócios Digitais na Prática: da Ideia às Primeiras Vendas]]></series:name>
	</item>
		<item>
		<title>Saídas estruturadas com IA: JSON confiável para automações em Python</title>
		<link>https://asllanmaciel.com.br/saidas-estruturadas-ia-json-automacoes-python/</link>
					<comments>https://asllanmaciel.com.br/saidas-estruturadas-ia-json-automacoes-python/#respond</comments>
		
		<dc:creator><![CDATA[Asllan Maciel]]></dc:creator>
		<pubDate>Fri, 07 Aug 2026 15:38:01 +0000</pubDate>
				<category><![CDATA[Guia para Iniciantes]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[Cursos]]></category>
		<category><![CDATA[OpenAI API]]></category>
		<category><![CDATA[Structured Outputs]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[inteligência artificial]]></category>
		<guid isPermaLink="false">https://asllanmaciel.com.br/?p=5009</guid>

					<description><![CDATA[<p>Aprenda a transformar texto em dados validados com Structured Outputs, Pydantic e a Responses API para criar automações Python mais confiáveis.</p>
<p>O post <a href="https://asllanmaciel.com.br/saidas-estruturadas-ia-json-automacoes-python/">Saídas estruturadas com IA: JSON confiável para automações em Python</a> apareceu primeiro em <a href="https://asllanmaciel.com.br">Asllan Maciel | Tecnologia, IA e Produtos Digitais</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Uma automação deixa de ser confiável no instante em que precisa “adivinhar” o formato da resposta de uma inteligência artificial. Um campo que muda de nome, um valor fora do padrão ou uma frase antes do JSON pode quebrar o fluxo inteiro. Para sair do protótipo e chegar a uma rotina que toma decisões com segurança, o modelo precisa responder dentro de um contrato verificável.</p>
<p>Nesta aula da série <a href="https://asllanmaciel.com.br/series/python-ia/">Python + IA: Fundamentos e Projetos Práticos</a>, vamos usar <strong>Structured Outputs</strong>, Pydantic e a Responses API da OpenAI para transformar uma solicitação de suporte em dados tipados. O resultado poderá alimentar uma fila, um banco de dados, um webhook ou uma automação no n8n sem depender de expressões regulares frágeis.</p>
<p>O objetivo não é apenas obter um JSON válido. É garantir que os campos esperados existam, que os valores respeitem o schema e que o código Python saiba o que fazer quando a resposta não puder ser processada.</p>
<h2>Por que “responda em JSON” não basta</h2>
<p>Pedir JSON no prompt ajuda, mas não cria um contrato. O modelo ainda pode devolver uma chave diferente, omitir um campo obrigatório ou escolher um valor que sua aplicação não reconhece. O modo JSON resolve parte do problema porque produz JSON sintaticamente válido, mas não garante aderência ao formato de negócio.</p>
<p>Structured Outputs acrescenta essa garantia de schema. Segundo a <a href="https://developers.openai.com/api/docs/guides/structured-outputs" target="_blank" rel="noopener">documentação oficial da OpenAI</a>, a resposta segue o JSON Schema fornecido, incluindo chaves obrigatórias e enumerações compatíveis com os recursos suportados. No SDK Python, podemos declarar o formato com um modelo Pydantic e receber o objeto já analisado.</p>
<p>Essa distinção muda a arquitetura. Em vez de extrair texto e tentar corrigi-lo depois, definimos primeiro o que a aplicação aceita. A IA passa a preencher esse contrato. Ainda precisamos validar regras de negócio e tratar falhas operacionais, mas eliminamos uma grande classe de erros de formatação.</p>
<h2>Prepare o projeto e proteja a chave</h2>
<p>Crie um ambiente isolado e instale o SDK da OpenAI e o Pydantic. Se você acompanhou a aula anterior sobre <a href="https://asllanmaciel.com.br/python-uv-pyproject-ambientes-reproduziveis/">ambientes reproduzíveis com uv e pyproject.toml</a>, pode continuar no mesmo padrão:</p>
<pre><code class="language-bash">uv init triagem-ia
cd triagem-ia
uv add openai pydantic</code></pre>
<p>A <a href="https://developers.openai.com/api/docs/quickstart" target="_blank" rel="noopener">introdução oficial da API</a> orienta configurar <code>OPENAI_API_KEY</code> como variável de ambiente; o SDK a lê automaticamente. Não coloque a chave no arquivo Python, no repositório ou em uma captura de tela. Em produção, use o gerenciador de segredos da sua infraestrutura e conceda acesso apenas ao serviço que executa a automação.</p>
<p>O projeto deste tutorial terá um arquivo <code>main.py</code>. A entrada será uma mensagem livre enviada por um cliente. A saída deverá conter categoria, prioridade, resumo, indicação de atendimento humano e tags.</p>
<h2>Modele o contrato com Pydantic</h2>
<p>Comece pelos valores que não podem variar livremente. A prioridade será uma enumeração, enquanto o restante será descrito em um modelo Pydantic:</p>
<pre><code class="language-python">from enum import Enum
from pydantic import BaseModel, Field


class Prioridade(str, Enum):
    baixa = "baixa"
    media = "media"
    alta = "alta"


class Triagem(BaseModel):
    categoria: str = Field(
        description="Fila curta: financeiro, acesso, suporte ou comercial"
    )
    prioridade: Prioridade
    resumo: str = Field(
        description="Resumo objetivo da solicitação em até duas frases"
    )
    requer_humano: bool
    tags: list[str]</code></pre>
<p>O schema é a fronteira entre o modelo e o restante do sistema. Quanto mais previsível ele for, mais simples será integrar. Uma enumeração é melhor que instruções como “use baixa, média ou alta”, pois impede variações inesperadas. Para categoria, poderíamos criar outra enumeração; deixamos como texto neste exemplo para demonstrar uma validação de negócio posterior.</p>
<p>Evite transformar o schema em um espelho de toda a sua base. Inclua somente os dados necessários para a próxima decisão. Campos demais aumentam complexidade, manutenção e risco de armazenar informações que não deveriam circular.</p>
<h2>Gere a resposta estruturada com a Responses API</h2>
<p>Agora crie o cliente e use <code>responses.parse</code>. A documentação atual recomenda começar novos projetos com a Responses API e mostra o parâmetro <code>text_format</code> para informar o modelo Pydantic:</p>
<pre><code class="language-python">from openai import OpenAI

client = OpenAI()

solicitacao = """
Não consigo acessar minha conta desde ontem.
Já redefini a senha duas vezes e preciso emitir uma nota hoje.
"""

response = client.responses.parse(
    model="gpt-5.6",
    input=[
        {
            "role": "system",
            "content": (
                "Classifique solicitações de suporte. "
                "Não invente dados. Marque requer_humano como verdadeiro "
                "quando houver urgência, bloqueio de acesso ou ambiguidade."
            ),
        },
        {"role": "user", "content": solicitacao},
    ],
    text_format=Triagem,
)

triagem = response.output_parsed

if triagem is None:
    raise RuntimeError("A resposta não pôde ser convertida para o schema.")

print(triagem.model_dump_json(indent=2))</code></pre>
<p>O atributo <code>output_parsed</code> entrega uma instância de <code>Triagem</code>, não uma string para ser decodificada manualmente. O editor, os testes e o analisador de tipos passam a conhecer os campos disponíveis. Se o schema mudar, o ponto de integração fica explícito.</p>
<p>O prompt de sistema continua importante. Structured Outputs garante a forma, mas não torna verdadeira uma classificação ruim. Descreva critérios objetivos, forneça contexto suficiente e teste exemplos reais antes de automatizar uma consequência relevante.</p>
<h2>Transforme o resultado em uma decisão de automação</h2>
<p>Com o objeto validado, a aplicação pode decidir a fila sem interpretar linguagem natural novamente:</p>
<pre><code class="language-python">CATEGORIAS_PERMITIDAS = {
    "financeiro",
    "acesso",
    "suporte",
    "comercial",
}


def decidir_fila(triagem: Triagem) -&gt; str:
    categoria = triagem.categoria.strip().lower()

    if categoria not in CATEGORIAS_PERMITIDAS:
        return "revisao-manual"

    if triagem.requer_humano or triagem.prioridade is Prioridade.alta:
        return "atendimento-humano"

    return f"fila-{categoria}"


fila = decidir_fila(triagem)
print({"fila": fila, "dados": triagem.model_dump()})</code></pre>
<p>Observe que ainda validamos as categorias permitidas. O schema resolve o formato; a função protege uma regra local. Essa separação é saudável: o modelo organiza e classifica, enquanto o código controla quais ações podem acontecer.</p>
<p>O dicionário retornado pode ser enviado a um endpoint, gravado em uma tabela ou passado a uma ferramenta de automação. Se você estiver decidindo entre um fluxo visual e código, veja também <a href="https://asllanmaciel.com.br/n8n-ou-programacao-automatizar-processos/">quando usar n8n ou programação para automatizar processos</a>. Uma arquitetura comum usa Python para a classificação tipada e n8n para orquestrar notificações, CRM e filas.</p>
<h2>Trate recusas, falhas e validações operacionais</h2>
<p>Uma resposta estruturada não elimina indisponibilidade de rede, limites da API, recusa do modelo ou entrada maliciosa. Em produção, trate esses casos como estados esperados, nunca como exceções impossíveis.</p>
<ul>
<li><strong>Ausência de resultado analisado:</strong> não execute a ação. Envie o item para revisão ou uma fila de retentativa.</li>
<li><strong>Falha temporária:</strong> aplique tentativas limitadas com espera progressiva. Não crie um ciclo infinito.</li>
<li><strong>Regra sensível:</strong> pagamentos, bloqueios, decisões legais e alterações irreversíveis exigem confirmação humana.</li>
<li><strong>Dados pessoais:</strong> envie apenas o mínimo necessário e evite registrar a mensagem completa em logs.</li>
<li><strong>Observabilidade:</strong> registre identificador, duração, versão do schema, fila escolhida e tipo de falha, sem expor segredos.</li>
<li><strong>Testes:</strong> mantenha exemplos de mensagens urgentes, vagas, contraditórias e fora de escopo.</li>
</ul>
<p>Também defina um limite de tamanho para a entrada e normalize o texto antes do envio. Em vez de aceitar qualquer categoria produzida, use enumerações sempre que o domínio for estável. Quando o objetivo for chamar funções ou ferramentas durante a resposta, use function calling; quando o objetivo for estruturar a resposta do próprio modelo, use Structured Outputs em <code>text.format</code>. Essa é a separação recomendada na documentação.</p>
<h2>Checklist prático e próximo passo</h2>
<ul>
<li>Criei um ambiente isolado e instalei <code>openai</code> e <code>pydantic</code>.</li>
<li>Configurei <code>OPENAI_API_KEY</code> fora do código.</li>
<li>Defini um modelo Pydantic pequeno e orientado à próxima decisão.</li>
<li>Usei <code>responses.parse</code> com <code>text_format</code>.</li>
<li>Verifiquei se <code>output_parsed</code> existe antes de agir.</li>
<li>Separei aderência ao schema de validação das regras de negócio.</li>
<li>Criei uma rota segura para falhas, recusas e categorias desconhecidas.</li>
<li>Adicionei logs mínimos, testes e revisão humana para ações sensíveis.</li>
</ul>
<p>O salto de qualidade acontece quando a IA deixa de entregar “um texto que parece certo” e passa a participar de um sistema com contratos, limites e rotas de segurança. Structured Outputs torna a integração mais previsível; Pydantic aproxima o schema do código; e a função de decisão mantém a autoridade final na aplicação.</p>
<p>Como exercício, adapte <code>Triagem</code> ao seu contexto: leads, pedidos, currículos ou tickets internos. Separe dez entradas reais, defina a saída mínima que o próximo passo exige e teste os casos ambíguos. Na próxima evolução, esse mesmo objeto poderá alimentar uma API ou um fluxo completo de automação sem perder a rastreabilidade.</p>
<p>O post <a href="https://asllanmaciel.com.br/saidas-estruturadas-ia-json-automacoes-python/">Saídas estruturadas com IA: JSON confiável para automações em Python</a> apareceu primeiro em <a href="https://asllanmaciel.com.br">Asllan Maciel | Tecnologia, IA e Produtos Digitais</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://asllanmaciel.com.br/saidas-estruturadas-ia-json-automacoes-python/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		
		<series:name><![CDATA[Python + IA: Fundamentos e Projetos Práticos]]></series:name>
	</item>
	</channel>
</rss>