Agente ReAct no watsonx Orchestrate — API REST real + RAG, construído com IBM Bob
Pedi para o agente “me reserva nesse voo” e ele não reservou. Em vez de preencher a chamada com um user_id qualquer para satisfazer o schema, ele percebeu que faltava cadastro e me perguntou nome e e-mail. Quando respondi, executou duas ferramentas em sequência sozinho: registrou o passageiro, pegou o ID que voltou na resposta e só então fez a reserva.
Esse é o comportamento que separa um agente de verdade de um chatbot com acesso a API. O modelo não tinha o user_id, e a alternativa fácil — inventar um número — é exatamente o que quebra sistemas em produção. Este lab monta esse cenário: um agente ReAct no IBM watsonx Orchestrate ligado a uma API REST real e a uma base de conhecimento (RAG) com documentos corporativos.
O cenário e a API de reservas vêm do projeto IBM/galaxium-travels, uma aplicação de demonstração publicada pela IBM sob Apache-2.0 — o backend em FastAPI já vinha pronto. O que construí em cima disso foi a camada de agente: ferramentas, base de conhecimento e o YAML do agente, usando o ADK do watsonx Orchestrate. Essa parte foi feita com o IBM Bob, o assistente de código da IBM — das specs OpenAPI aos YAMLs de agente e knowledge base.
Objetivo do Lab
Construir um agente único que age sobre um sistema real (sistema de reservas de viagens espaciais, via FastAPI + SQLite) e consulta documentos internos (catálogo de pacotes, FAQ, guia de preparação) para responder dúvidas de política — decidindo sozinho qual dos dois caminhos usar em cada pergunta.
O ponto central é a orquestração de fluxos de múltiplas etapas: a API exige que o passageiro exista antes de reservar, e é o agente que descobre e resolve essa dependência.
Antes de Começar — O Que Você Precisa
Este lab é reproduzível em casa, e tudo que ele usa tem versão gratuita. São quatro coisas para preparar antes de escrever qualquer YAML.
1. Conta no watsonx Orchestrate (trial de 30 dias)
O Orchestrate é um produto pago, mas oferece trial gratuito de 30 dias — suficiente com folga para este lab. Cadastre-se pela página do produto usando um IBMid (que também é grátis e serve para o Bob depois).
Com o ambiente provisionado, pegue as duas credenciais que o ADK vai pedir:
- Faça login na sua instância do watsonx Orchestrate
- Clique no ícone de usuário no canto superior direito e vá em Settings
- Abra a aba API details
- Copie a service instance URL
- Clique em Generate API key e guarde a chave
Guarde a API key com cuidado: dependendo do provedor ela não é recuperável depois — se perder, é preciso gerar outra.
2. Python 3.11+ e o ADK
O ADK (Agent Development Kit) é o orchestrate CLI, e exige Python 3.11 ou superior:
python3 --version # precisa ser >= 3.11
pip install --upgrade ibm-watsonx-orchestrate
orchestrate --help # confirma a instalação
Agora conecte o CLI ao seu ambiente, usando as credenciais do passo anterior:
# registra o ambiente (a URL da aba API details)
orchestrate env add -n meu-wxo -u <service-instance-url>
# ativa (vai pedir a API key; ou passe com --api-key)
orchestrate env activate meu-wxo
Confira se está tudo certo:
orchestrate env list
orchestrate agents list
A autenticação remota expira a cada ~2 horas. Quando os comandos começarem a falhar com erro de token, rode o orchestrate env activate de novo — é o motivo mais comum de “parou de funcionar do nada” no meio do lab.
3. O IBM Bob (opcional, mas foi como fiz)
O Bob é o assistente de código da IBM — um fork do VS Code com um agente integrado. Tem trial de 30 dias com 40 Bobcoins; depois é assinatura paga. Baixe em bob.ibm.com/download:
- macOS —
.pkg(escolha ARM para M1/M2/M3, Intel para os mais antigos) - Windows —
.exe, instalação por wizard - Linux — instaladores para Debian e Red Hat/Fedora
Requer 4 GB de RAM (8 GB recomendado), 500 MB de disco e login com IBMid no primeiro início.
O lab funciona sem o Bob — os YAMLs estão todos neste post. Ele entra como acelerador para escrever spec, YAMLs e instruções.
4. O repositório da Galaxium Travels
O cenário e a API vêm do projeto da IBM:
git clone https://github.com/IBM/galaxium-travels.git
cd galaxium-travels
O repositório completo traz um frontend React e um serviço Java de holds, mas para este lab só o backend Python importa — é ele que vira as ferramentas do agente. Você pode ignorar o resto.
Tecnologias Utilizadas
Antes do código, vale entender cada peça — inclusive porque algumas são específicas do ecossistema IBM.
IBM watsonx Orchestrate
Plataforma da IBM para criar e executar agentes de IA que integram sistemas corporativos. Em vez de você escrever o laço de raciocínio do agente na mão (chamar o modelo, interpretar a resposta, executar a ferramenta, devolver o resultado, repetir), o Orchestrate cuida disso. Você declara o agente em YAML: qual modelo usar, quais ferramentas ele tem, qual base de conhecimento consultar e quais instruções seguir.
O trabalho é feito pelo orchestrate CLI, o ADK (Agent Development Kit), que importa ferramentas, bases de conhecimento e agentes para o ambiente.
Agente ReAct
ReAct significa Reasoning + Acting — raciocinar e agir. É um padrão em que o modelo alterna entre pensar e executar: analisa o pedido, decide qual ferramenta chamar, observa o resultado, pensa de novo com essa informação nova e decide o próximo passo.
A diferença prática em relação a um modelo que só responde texto: o agente ReAct pode encadear chamadas, usando a saída de uma como entrada da próxima. É o que permite resolver “registrar → reservar” sem que ninguém tenha programado essa sequência.

OpenAPI Specification
Formato padrão (JSON ou YAML) que descreve uma API REST: quais endpoints existem, que parâmetros aceitam, o que retornam. É a forma como o Orchestrate transforma uma API em ferramentas do agente — sem escrever uma linha de código de integração.
Cada endpoint da spec vira uma ferramenta, e a descrição de cada campo é o que o modelo lê para decidir quando e como usá-la. Descrição ruim na spec significa ferramenta usada errado pelo agente.
RAG (Retrieval-Augmented Generation)
Geração aumentada por recuperação. O modelo responde a partir dos seus documentos, não apenas do que aprendeu no treinamento. Os documentos são quebrados em pedaços (chunks), convertidos em vetores numéricos (embeddings) e indexados. Na hora da pergunta, o sistema busca os trechos mais parecidos semanticamente e injeta no contexto antes de gerar a resposta.
O ganho é direto: preço de pacote e política de cancelamento saem do catálogo real da empresa, não da imaginação do modelo.
FastAPI + SQLite
FastAPI é o framework Python que expõe o sistema de reservas como API REST. Ele gera a spec OpenAPI automaticamente a partir do código — o que economiza justamente o passo mais chato deste lab. SQLite é o banco em arquivo único que guarda voos, usuários e reservas, sem exigir servidor de banco.
IBM Bob
Assistente de código da IBM, usado aqui para construir a camada de agente sobre a aplicação existente: ajustar a spec OpenAPI para o formato que o Orchestrate aceita, escrever os YAMLs do agente e da base de conhecimento, redigir as instruções de roteamento e montar o script de subida da API.
Arquitetura
[ Usuário via chat ]
│
▼
[ galaxium_travel_agent (ReAct) ]
granite-3-8b-instruct
│ │
┌──────────┘ └──────────┐
▼ ▼
[ Ferramentas OpenAPI ] [ Base de conhecimento ]
FastAPI + SQLite :8001 RAG · 3 documentos
flights / register / user pacotes · FAQ ·
book / bookings / cancel preparação
| Componente | Função |
|---|---|
galaxium_travel_agent |
Agente ReAct que decide entre agir (API) e consultar (RAG) |
granite-3-8b-instruct |
Modelo IBM Granite que faz o raciocínio do agente |
| Ferramentas OpenAPI | 6 endpoints da API de reservas, importados via spec |
galaxium-travels-kb |
Base vetorial com os 3 documentos corporativos |
| FastAPI + SQLite | Sistema de reservas real, na porta 8001 |
orchestrate CLI |
Importa ferramentas, KB e agente para o ambiente |
O diagrama abaixo percorre o processo inteiro, etapa por etapa: o Bob preparando os documentos da base de conhecimento, a ingestão no RAG (chunking, embeddings, índice), a API virando ferramentas via OpenAPI, a montagem do agente e — no final — a conversa real em que ele registra o passageiro e efetiva a reserva.

As cinco etapas que o diagrama percorre são exatamente as deste post:
| Etapa | O que acontece | Comando |
|---|---|---|
| 1. Documentos | Catálogo, FAQ e guia (do repositório da IBM) viram a matéria-prima do RAG | — |
| 2. RAG | Chunking, embeddings e índice vetorial | orchestrate knowledge-bases import |
| 3. API | A spec OpenAPI vira 6 ferramentas do agente | orchestrate tools import |
| 4. Agente | ReAct ligando ferramentas + base de conhecimento | orchestrate agents import |
| 5. Reserva | O agente encadeia register → book sozinho |
orchestrate chat start |
Há também uma versão interativa do diagrama, com as mesmas cinco etapas em HTML.
Como as Partes se Conectam
O fluxo começa no chat. O agente recebe a mensagem e o modelo Granite decide o caminho com base nas instruções do YAML:
Se a pergunta depende do estado atual do sistema — quais voos existem, quantos assentos sobraram, quais reservas o cliente tem — ele chama uma ferramenta. Os dados vêm do SQLite via FastAPI, sempre atuais.
Se a pergunta é sobre política ou catálogo — quanto custa o pacote lunar, qual a regra de cancelamento, o que pode levar na bagagem — ele consulta o RAG. A resposta sai dos documentos indexados.
E quando o pedido exige as duas coisas, ou várias etapas encadeadas, o laço ReAct entra em ação: age, observa o retorno, raciocina de novo e decide o próximo passo.
Estrutura do Projeto
Organizei o lab assim — os itens marcados com [IBM] vêm do repositório original, os demais são a camada de agente que construí:
wxo-galaxium-travels-agent/
├── start_api.sh # atalho meu: venv + seed + uvicorn
├── galaxium-openapi.json # OpenAPI spec ajustado p/ o Orchestrate
├── galaxium-knowledge-base.yaml # definição da base RAG
├── galaxium-travel-agent.yaml # definição do agente ReAct
├── knowledge-bases/ # [IBM] documentos indexados no RAG
│ ├── travel_packages_catalog.md # pacotes e preços
│ ├── passenger_faq.md # perguntas frequentes
│ └── passenger_preparation_guide.md
├── booking_system_backend/ # [IBM] a API REST
│ ├── server.py # endpoints FastAPI
│ ├── models.py # tabelas (User, Flight, Booking)
│ ├── schemas.py # contratos de entrada/saída
│ ├── seed.py # dados de demonstração
│ └── services/ # regras de negócio
└── diagrama/ # diagrama animado do fluxo
├── gerar_gif.py # gera o GIF das 5 etapas (Pillow)
├── wxo-galaxium-travels-agent.gif
└── wxo-galaxium-travels-agent.html
A API de Reservas
O agente só é interessante se tiver um sistema real para controlar. O backend define três tabelas — usuários, voos e reservas — com o detalhe que gera a dependência interessante: Booking tem uma foreign key para User.
class Booking(Base):
__tablename__ = 'bookings'
booking_id = Column(Integer, primary_key=True, autoincrement=True)
user_id = Column(Integer, ForeignKey('users.user_id'), nullable=False)
flight_id = Column(Integer, ForeignKey('flights.flight_id'), nullable=False)
status = Column(String, nullable=False)
seat_class = Column(String, nullable=False, default='economy')
price_paid = Column(Integer, nullable=False)
user_id é obrigatório e referencia um usuário existente. Reservar sem cadastro é impossível — e o sistema não inventa passageiro. Essa restrição de banco é o que força o agente a planejar.
Para subir a API, direto do repositório clonado:
cd galaxium-travels/booking_system_backend
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
python server.py # sobe na porta 8001
Na primeira execução o banco é populado com dados de demonstração — 10 voos (Terra → Marte, Terra → Lua, Júpiter → Europa…) e 10 usuários. A semeadura é idempotente: só roda se o banco estiver vazio, então reiniciar não apaga o que você cadastrou.
Deixe este terminal aberto — a API precisa continuar no ar durante todo o lab.
Confirme que subiu abrindo o Swagger no navegador:
curl -s http://localhost:8001/flights | head -c 200
Sobre o endereço do Swagger, atenção a uma pegadinha: depende de como o backend foi configurado. No repositório oficial ele responde em http://localhost:8001/docs. Nesta cópia do lab o server.py define root_path="/api" (um ajuste para roteamento por load balancer), o que empurra tudo para baixo de /api — e aí o Swagger fica em http://localhost:8001/api/docs.
Se /docs der 404, tente /api/docs, e vice-versa. Isso importa além do Swagger: é o mesmo prefixo que precisa entrar no servers.url da spec OpenAPI — se errar aqui, o agente importa as ferramentas mas toda chamada volta 404.
Testando a dependência à mão
Vale reproduzir no Swagger o problema que o agente vai ter que resolver. Tente reservar sem cadastro:
POST /book
{ "user_id": 99, "name": "Felipe", "flight_id": 1, "seat_class": "economy" }
Retorna erro — o usuário 99 não existe. Agora cadastre:
POST /register
{ "name": "Felipe", "email": "felipe@email.com" }
Guarde o user_id retornado e refaça o POST /book com ele: funciona. Essa sequência manual é exatamente o que o agente vai fazer sozinho.
O OpenAPI Spec
O FastAPI gera a spec automaticamente, mas ela precisa de dois ajustes para o Orchestrate:
| Ajuste | O que muda | Por quê |
|---|---|---|
| Versão | 3.1.0 → 3.0.3 |
O Orchestrate aceita apenas OpenAPI 3.0.x |
servers |
URL base = http://localhost:8001/api |
O Orchestrate precisa saber para onde chamar |
Os seis endpoints que viram ferramentas:
| Método | Endpoint | operationId | O que faz |
|---|---|---|---|
| GET | /flights |
get_flights_flights_get |
Listar voos disponíveis |
| POST | /register |
register_user_endpoint_register_post |
Cadastrar passageiro |
| GET | /user |
get_user_endpoint_user_get |
Buscar usuário por nome + e-mail |
| POST | /book |
book_flight_endpoint_book_post |
Reservar voo |
| GET | /bookings/{user_id} |
get_user_bookings_bookings__user_id__get |
Ver reservas |
| POST | /cancel/{booking_id} |
cancel_booking_endpoint_cancel__booking_id__post |
Cancelar reserva |
O operationId é o nome pelo qual o agente referencia a ferramenta no YAML — por isso ele aparece nessa forma verbosa gerada pelo FastAPI.

orchestrate tools import -k openapi -f galaxium-openapi.json
orchestrate tools list
Se o seu Orchestrate roda em SaaS, ele não enxerga localhost. Nesse caso é preciso expor a API com um túnel HTTPS público (ngrok http 8001) e trocar o servers.url da spec pela URL pública — incluindo o /api no final — antes de reimportar.
A Base de Conhecimento (RAG)
A KB referencia os três documentos Markdown. O Orchestrate faz chunking, gera embeddings e indexa:
spec_version: v1
kind: knowledge_base
name: galaxium-travels-kb
description: >
Documentos internos da Galaxium Travels usados para responder dúvidas de
clientes via RAG: catálogo de pacotes e preços, políticas de cancelamento,
FAQ do passageiro e o guia de preparação para o voo.
documents:
- "knowledge-bases/travel_packages_catalog.md"
- "knowledge-bases/passenger_faq.md"
- "knowledge-bases/passenger_preparation_guide.md"
vector_index:
chunk_size: 500
chunk_overlap: 50
embeddings_model_name: "default"
chunk_size: 500 define o tamanho de cada pedaço indexado, e chunk_overlap: 50 faz pedaços vizinhos compartilharem 50 caracteres. Esse overlap existe para evitar que uma informação seja cortada bem na fronteira entre dois chunks e acabe recuperada pela metade.

Os caminhos em documents são relativos ao diretório de onde você roda o comando, não ao arquivo YAML. Rodando de outra pasta, o import falha dizendo que não encontrou os documentos — é o erro mais bobo e mais comum aqui.
Dois pontos onde este YAML difere do exemplo da documentação, e que valem atenção se algo não funcionar no seu ambiente:
embeddings_model_name: "default" — a documentação oficial usa o nome explícito do modelo, ibm/slate-125m-english-rtrvr-v2. Se o "default" for rejeitado na sua versão do ADK, troque pelo nome completo.
Documentos em Markdown — a documentação lista PDF, DOCX, PPTX, XLSX, CSV, HTML e TXT, sem citar .md explicitamente. Funcionou aqui, mas se o seu import reclamar do formato, renomear para .txt resolve sem alterar o conteúdo — os documentos são texto puro de qualquer forma.
Feito isso, importe:
orchestrate knowledge-bases import -f galaxium-knowledge-base.yaml
orchestrate knowledge-bases list # confirma que apareceu
A indexação não é instantânea: o Orchestrate precisa quebrar os documentos, gerar os embeddings e subir tudo para o índice vetorial. Se testar o agente imediatamente e ele responder que não sabe, espere um pouco e pergunte de novo antes de sair mexendo nas instruções.
O Agente
Aqui está o núcleo do lab. O YAML declara modelo, estilo, ferramentas, base de conhecimento e — o mais importante — as instruções que ensinam o agente a escolher entre agir e consultar:
spec_version: v1
kind: native
name: galaxium_travel_agent
title: Galaxium Travel Agent
llm: watsonx/ibm/granite-3-8b-instruct
style: react
hide_reasoning: false
style: react é o que ativa o laço raciocinar-agir-observar. hide_reasoning: false deixa o raciocínio visível na interface — essencial para conferir se o agente usou a ferramenta certa.
O bloco de instruções faz o roteamento:
instructions: |
## Quando usar as FERRAMENTAS (API) vs. a BASE DE CONHECIMENTO
- Use as **ferramentas** (API) sempre que a pergunta envolver dados vivos do
sistema: listar voos, registrar passageiro, buscar usuário, reservar,
ver reservas ou cancelar.
- Use a **base de conhecimento** (RAG) para perguntas gerais sobre políticas,
pacotes de viagem, preços de catálogo, regras de cancelamento e preparação.
- Na dúvida, prefira a ferramenta quando a resposta depender do estado atual
do sistema (assentos, IDs, reservas do cliente).
## Fluxo de reserva (planeje antes de agir)
Para reservar um voo, a API exige um `user_id`. Portanto:
1. Se o cliente ainda não tem cadastro, registre-o primeiro (nome + e-mail).
2. Se o cliente diz que já tem conta, busque o usuário para recuperar o `user_id`.
3. Só então reserve o voo, usando o `user_id` obtido no passo anterior.
Nunca invente um `user_id` — obtenha-o sempre de uma ferramenta.
## Recuperação de erro
Se uma chamada retornar erro, não repita a mesma chamada. Investigue:
confirme nome e e-mail, busque o usuário, ou ofereça um novo cadastro.
A frase “nunca invente um user_id” parece óbvia, mas é ela que evita o comportamento mais comum de um modelo pressionado a preencher um schema: chutar um valor plausível. Escrita assim, a instrução transforma o campo faltante em pergunta ao usuário.
As ferramentas e a KB são referenciadas por nome:
tools:
- get_flights_flights_get
- register_user_endpoint_register_post
- get_user_endpoint_user_get
- book_flight_endpoint_book_post
- get_user_bookings_bookings__user_id__get
- cancel_booking_endpoint_cancel__booking_id__post
knowledge_base:
- galaxium-travels-kb
orchestrate agents import -f galaxium-travel-agent.yaml
A ordem importa: o YAML do agente referencia ferramentas e KB pelo nome, então importe os dois antes do agente — caso contrário a importação falha.
Executando — O Roteiro Completo
Juntando tudo, do zero até o agente respondendo. Você vai precisar de dois terminais: um para a API, outro para o orchestrate.
Terminal 1 — a API no ar
git clone https://github.com/IBM/galaxium-travels.git
cd galaxium-travels/booking_system_backend
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
python server.py # deixe rodando
Terminal 2 — expor a API (só se o Orchestrate for SaaS)
Se o seu Orchestrate é o da nuvem — o caso de quem usa o trial — ele não enxerga o seu localhost. É preciso um túnel público antes de importar as ferramentas:
ngrok http 8001
Copie a URL https:// que o ngrok mostrar e use no servers.url da spec (com o mesmo sufixo de path do seu Swagger — /api ou nada):
"servers": [
{ "url": "https://xxxx-xxxx.ngrok-free.dev/api" }
]
Pulei esse passo na primeira tentativa e as ferramentas importaram normalmente — só para dar timeout em toda chamada depois. O erro não aparece na importação, só no uso.
Terminal 2 — importar e testar
A ordem aqui não é opcional: o YAML do agente referencia ferramentas e base de conhecimento pelo nome. Se elas ainda não existirem, a importação do agente falha.
# 0. ambiente ativo? (o token expira a cada ~2h)
orchestrate env activate meu-wxo
# 1. ferramentas a partir da spec OpenAPI
orchestrate tools import -k openapi -f galaxium-openapi.json
# 2. base de conhecimento (chunking + embeddings + índice)
orchestrate knowledge-bases import -f galaxium-knowledge-base.yaml
# 3. o agente, que referencia os dois acima
orchestrate agents import -f galaxium-travel-agent.yaml
# 4. conferir que os três existem
orchestrate tools list
orchestrate knowledge-bases list
orchestrate agents list
# 5. abrir o chat
orchestrate chat start
No chat, selecione galaxium_travel_agent e siga para os testes abaixo.
Refazendo do zero
Se quiser recomeçar limpo — útil ao ajustar instruções e comparar comportamento:
orchestrate agents remove -n galaxium_travel_agent
orchestrate knowledge-bases remove -n galaxium-travels-kb
Para zerar também os dados de reserva, apague o arquivo SQLite do backend e suba a API de novo; a semeadura roda outra vez por encontrar o banco vazio.
Testando o Agente
Pergunta de política (RAG)
Prompt: Quais pacotes vocês oferecem para ir à Lua?
O agente consulta a base de conhecimento e responde com os pacotes lunares do catálogo — Lunar Escape (250.000 GXC), Lunar Royale (490.000 GXC) e Honeymoon on the Moon — com os preços que estão nos documentos. Abrindo o raciocínio dá para confirmar que ele usou o RAG, e não a API.
Consulta à API
Prompt: Quais são os próximos voos disponíveis?
Aqui ele chama GET /flights, recebe o JSON com origem, destino, preço e assentos por classe, e formata numa lista legível. Dado vivo, vindo do banco.
Fluxo de múltiplas etapas
Este é o teste que importa.
Prompt: Me reserva nesse voo, por favor.
O agente não executa nada. Ele vê que a ferramenta de reserva exige user_id, não tem esse dado e pede o que falta. Isso é planejamento — ele inspecionou o schema da ferramenta antes de tentar usá-la.
Prompt: Não tenho user ID.
Ele entende que precisa registrar primeiro e pede nome e e-mail.
Prompt: Meu nome é Felipe, email felipe@email.com
Agora ele executa duas ferramentas em sequência, sozinho:
POST /register→ recebe ouser_idna respostaPOST /book→ usa esseuser_idcomo parâmetro
Uma etapa alimentando a outra, sem ninguém ter programado a sequência. A dependência estava no banco de dados; o agente a descobriu pelo schema e pelas instruções.

Recuperação de erro
Tente reservar com um nome que não bate com o cadastro. A API retorna erro, e o comportamento interessante é o que o agente não faz: repetir a mesma chamada esperando resultado diferente. Ele busca o usuário, confere os dados e sugere o recadastro.
RAG de preparação
Prompt: O que preciso levar numa viagem para Marte? Posso levar plantas?
Resposta ancorada no guia de preparação e no FAQ: limite de bagagem, itens proibidos (organismos vivos, solo lunar) e requisitos médicos específicos de Marte.
Monitoramento e Troubleshooting
| Sintoma | Causa provável | Solução |
|---|---|---|
Address already in use na 8001 |
API já rodando | lsof -ti:8001 | xargs kill -9 e suba de novo |
Swagger não abre em /docs |
O backend usa root_path="/api" |
Tente http://localhost:8001/api/docs (ou o inverso) |
orchestrate: command not found |
ADK não instalado ou fora do PATH | pip install --upgrade ibm-watsonx-orchestrate no venv ativo |
| ADK falha ao instalar | Python abaixo de 3.11 | python3 --version — o ADK exige 3.11+ |
| Import do agente falha | KB ou ferramentas ainda não existem | Importe tools e KB antes do agente |
| Import da KB não acha os arquivos | Caminhos são relativos ao diretório atual | Rode o comando da raiz do lab, onde está knowledge-bases/ |
| Ferramentas importam mas dão timeout | Orchestrate SaaS não alcança localhost |
Exponha via ngrok e atualize servers.url na spec |
| Toda chamada de ferramenta volta 404 | servers.url sem o prefixo certo |
Inclua (ou remova) o /api conforme o seu Swagger |
| Erro de token / 401 no meio do lab | Autenticação remota expira (~2h) | orchestrate env activate <ambiente> de novo |
| Agente diz não saber sobre pacotes | Índice ainda processando | Aguarde a indexação terminar e pergunte de novo |
| Agente responde política pela API | Instrução de roteamento fraca | Reforce no YAML: ferramenta = dado vivo, RAG = política |
Agente inventa um user_id |
Falta a instrução explícita | Adicione “nunca invente um user_id” nas instruções |
Com hide_reasoning: false, a própria interface é a melhor ferramenta de diagnóstico: dá para ver qual ferramenta o agente escolheu, com quais parâmetros e o que voltou.
Para Que Serve no Mercado
O padrão deste lab — agente com ferramentas de API real mais RAG sobre documentos internos — é a forma mais direta de aplicar IA agêntica em cenário corporativo.
Atendimento que resolve, não só responde. A maioria dos assistentes consulta FAQ e encaminha para um humano quando é preciso agir. Aqui o agente executa a ação no sistema — abre chamado, agenda, cancela — usando a API que a empresa já tem.
Integração sem projeto de integração. A API vira ferramenta pela spec OpenAPI. Se a empresa já expõe REST documentado, o caminho até o agente é importar a spec, não escrever camada de integração.
Resposta ancorada em documento. Preço, política e prazo saem do documento oficial via RAG. Isso muda a conversa sobre risco: a resposta é rastreável até a fonte, em vez de depender do que o modelo memorizou.
Fluxos com pré-requisito. Cadastro antes de pedido, aprovação antes de provisionamento, validação antes de emissão — o agente descobre a dependência pelo schema e resolve, em vez de falhar ou inventar dados.
Conclusão
O que ficou mais claro rodando este lab não foi o poder do modelo, mas o peso das instruções e do schema. O mesmo Granite, com as mesmas seis ferramentas, se comporta de forma completamente diferente conforme o YAML diz “nunca invente um user_id” ou fica calado sobre isso.
A restrição de foreign key no SQLite, a descrição de cada campo na spec OpenAPI e três parágrafos de instrução em português foram o que produziu o comportamento correto — pedir o dado que falta em vez de chutar um valor. Isso é engenharia de contrato, não mágica de IA. Vale lembrar disso antes de culpar o modelo quando um agente age errado: normalmente o que faltou foi descrição na ferramenta ou instrução no agente.
E a parte que mais me surpreendeu foi o quanto o IBM Bob acelerou o caminho até aqui — ajustar a spec, escrever os YAMLs e montar o script de subida foi tudo conversa com ele.
Créditos
O cenário da Galaxium Travels e o sistema de reservas não são meus: vêm do projeto IBM/galaxium-travels, publicado pela IBM sob licença Apache-2.0. A API em FastAPI, o modelo de dados e os documentos da agência já vinham prontos no repositório — é uma aplicação de demonstração criada justamente para exercitar agentes de IA sobre uma base de código realista.
O que fiz aqui foi a camada de agente em cima disso: importar a API como ferramentas via OpenAPI spec, montar a base de conhecimento (RAG) a partir dos documentos, escrever o YAML do agente ReAct com as instruções de roteamento e testar o fluxo de múltiplas etapas usando o ADK do watsonx Orchestrate.
Essa parte foi construída com o IBM Bob, que escreveu os YAMLs do agente e da knowledge base, ajustou o OpenAPI spec para o formato aceito pelo Orchestrate e redigiu as instruções de roteamento — coube a mim revisar e executar.
Referências
- IBM watsonx Orchestrate — página do produto e trial de 30 dias
- watsonx Orchestrate ADK — o
orchestrateCLI - Instalando o ADK — pré-requisitos e
pip install - Configurando o ambiente —
env addeenv activate - Obtendo as credenciais — onde achar API key e service instance URL
- Criando knowledge bases — schema do YAML e opções do índice
- Autoria de ferramentas OpenAPI — requisitos da spec
- IBM Bob — download e trial de 30 dias
- IBM Granite — família de modelos usada pelo agente
- OpenAPI Specification — formato das ferramentas
- FastAPI — framework da API de reservas
- ReAct: Synergizing Reasoning and Acting in Language Models — artigo original do padrão
- Galaxium Travels — projeto da IBM (Apache-2.0) que fornece o cenário e a API de reservas