LangGraph API¶
Execução de grafos LangGraph via HTTP — orquestração de fluxos com estado, ramificação condicional e retentativa. Roda no IBM Code Engine, escalando a zero quando ninguém usa.
Endpoints¶
| Recurso | URL |
|---|---|
| API | https://langgraph-api.2d3xg120feyh.br-sao.codeengine.appdomain.cloud |
| Documentação interativa (Swagger UI) | /docs |
Autenticação¶
Todas as chamadas exigem o header X-Api-Key (exceto /health e /docs). Sem a chave a API responde 401.
X-Api-Key: <chave>
Onde está a chave?
A chave é armazenada em segurança pela equipe de desenvolvimento. Solicite acesso ao responsável pelo serviço.
Rotas¶
| Rota | O que faz |
|---|---|
GET /health |
Liveness (sem auth) — lista os grafos carregados |
GET /graphs |
Grafos disponíveis, com exemplo de entrada de cada um |
POST /graphs/{nome}/invoke |
Executa o grafo até o fim e devolve o estado final |
POST /graphs/{nome}/stream |
Executa emitindo um evento SSE por nó concluído |
GET /graphs/{nome}/state?thread_id= |
Estado salvo de uma thread |
Grafos disponíveis¶
doc_triage — extração de documento com correção automática de OCR¶
Converte um documento para Markdown usando o Docling OCR, detecta camada de texto quebrada e, se encontrar, reprocessa automaticamente com force_ocr=true.
flowchart LR
A([início]) --> B["extract<br>converte via docling-serve"]
B --> C{"inspect<br>texto embaralhado?"}
C -->|"sim, e ainda não tentou OCR"| D["retry_force_ocr<br>liga force_ocr"]
D --> B
C -->|"não, ou já tentou"| E["finalize<br>gera recomendação"]
E --> F([fim])
Resolve na origem o problema descrito em Qualidade da extração: quem chama não precisa saber de antemão se o PDF tem camada de texto confiável — o grafo descobre e corrige.
Uso¶
curl -X POST \
-H "X-Api-Key: <chave>" \
-H "Content-Type: application/json" \
-d '{"input":{"url":"https://exemplo.gov.br/deliberacao.pdf"}}' \
"https://langgraph-api.2d3xg120feyh.br-sao.codeengine.appdomain.cloud/graphs/doc_triage/invoke"
Também aceita o documento embutido, em vez de URL:
{"input": {"base64_content": "<base64>", "filename": "deliberacao.pdf"}}
Resposta¶
{
"graph": "doc_triage",
"thread_id": "ephemeral-3148e9bd4d5a",
"output": {
"markdown": "# TÍTULO: POLÍTICA CORPORATIVA...",
"attempts": 2,
"force_ocr": true,
"garbled_lines": [],
"stats": {
"docling_status": "success",
"elapsed_s": 50.4,
"warmup_s": 19.4,
"queue_wait_s": 30.8,
"chars": 34220,
"headings": 22,
"garbled_count": 0,
"force_ocr_used": true,
"recommendation": "camada de texto estava quebrada; markdown final veio de OCR forçado"
},
"trace": ["extract#1: ...", "inspect: ...", "retry: ...", "extract#2: ...", "finalize: ..."]
}
}
O trace mostra o caminho percorrido no grafo e o stats diz onde o tempo foi gasto — útil porque o processing_time do docling cobre só a conversão, não o cold start nem a espera na fila.
Como a detecção funciona¶
Uma linha é considerada suspeita quando o comprimento médio dos tokens fica abaixo de 3,5 caracteres e ao menos 40% dos tokens têm 1–2 caracteres. É a assinatura do texto picado:
suspeita: ## TIT PA D D D DPIO DPO AIS
correta: ## TÍTULO: POLÍTICA CORPORATIVA DE PRIVACIDADE E PROTEÇÃO DE DADOS PESSOAIS
Os dois sinais são exigidos juntos porque a proporção de tokens curtos, isolada, acusaria frases normais em português — cheias de "a", "de", "os".
echo¶
Grafo mínimo de dois nós, sem dependências externas. Serve para verificar se o serviço e a autenticação estão de pé.
curl -X POST -H "X-Api-Key: <chave>" -H "Content-Type: application/json" \
-d '{"input":{"message":"olá","upper":true}}' \
"https://langgraph-api.2d3xg120feyh.br-sao.codeengine.appdomain.cloud/graphs/echo/invoke"
Streaming (SSE)¶
/stream emite um evento por nó concluído — útil para acompanhar grafos longos:
curl -N -X POST -H "X-Api-Key: <chave>" -H "Content-Type: application/json" \
-d '{"input":{"url":"https://exemplo.gov.br/doc.pdf"}}' \
"https://langgraph-api.2d3xg120feyh.br-sao.codeengine.appdomain.cloud/graphs/doc_triage/stream"
data: {"extract": {"markdown": "...", "trace": ["extract#1: ..."]}}
data: {"inspect": {"garbled_lines": [], "trace": ["inspect: 0 linha(s) ..."]}}
data: {"finalize": {"stats": {...}}}
data: [DONE]
O thread_id usado vem no header X-Thread-Id da resposta.
Estado e threads¶
thread_id é opcional:
- omitido — a API gera um efêmero e a execução não guarda nada
- informado — o estado acumula entre chamadas e pode ser consultado em
/graphs/{nome}/state
O estado é volátil
O checkpointer é em memória: o estado de uma thread existe apenas enquanto a instância estiver viva e desaparece quando o serviço escala a zero. Para fluxos que precisam retomar de onde pararam, o estado tem de ser guardado do lado do cliente.
Arquitetura¶
LangGraph aqui é usado como biblioteca, dentro de uma aplicação FastAPI própria — não é o LangGraph Platform. Na prática o serviço é um container HTTP comum, o que permite escalar a zero e dispensa banco de dados, licença e verificação externa.
flowchart LR
A["Cliente<br>(app, script)"]
subgraph CE["IBM Code Engine — br-sao"]
B["langgraph-api<br>0,5 vCPU / 1 GB · escala 0 → 3<br>auth: X-Api-Key"]
C["docling-serve<br>API de conversão"]
D["docling-worker<br>conversão"]
end
A -->|"POST /graphs/doc_triage/invoke"| B
B -->|"1. GET /health (warmup)"| C
B -->|"2. POST convert async + polling"| C
C <--> D
| Componente | Configuração |
|---|---|
langgraph-api |
0,5 vCPU / 1 GB RAM, escala 0 → 3, porta 8000, timeout de request 600 s |
O trade-off assumido: o LangGraph Platform self-hosted traria /threads, /assistants, cron e o LangGraph Studio prontos, mas exige Postgres e Redis obrigatórios, chave de licença com verificação externa, e seus background runs não sobrevivem ao scale-to-zero — nada acorda o container para retomar a fila. Como biblioteca, o serviço fica mais simples e realmente serverless.
Comportamento¶
- Cold start: poucos segundos (imagem leve, sem modelos)
doc_triage: ~50 s ponta a ponta para um PDF de 7–10 páginas, incluindo o cold start do docling; ~30 s se o docling já estiver quente- Timeout: o Code Engine encerra requests em 600 s. Documentos que passem disso devem ser quebrados em partes
- Residência: processamento em
br-sao(São Paulo) — o documento não sai do Brasil
Troubleshooting¶
| Sintoma | Causa provável | Ação |
|---|---|---|
401 Unauthorized |
Chave ausente ou inválida | Conferir header X-Api-Key |
503 com "LANGGRAPH_API_KEY não configurada" |
Serviço subiu sem a chave | Conferir o secret vinculado ao app |
404 grafo '...' não existe |
Nome errado | GET /graphs lista os disponíveis |
| Execução demora minutos além do esperado | Cold start do docling | Ver warmup_s no stats — o serviço já aquece o docling antes de enfileirar |
error com docling não concluiu em ...s |
Documento grande demais ou fila cheia | Reenviar; documentos muito grandes devem ir direto no endpoint assíncrono do docling |
| Estado de uma thread desapareceu | Instância escalou a zero | Esperado — o checkpointer é em memória |