Ollama API na prática: guia para clientes em Python e Node.js

Você digita ollama run gemma3 no terminal, e a primeira resposta aparece na tela. O modelo local está funcionando.
Logo vem a pergunta: dá para conectar isso ao seu próprio projeto? Sem API Key, sem cobrança e executando localmente — parece uma ótima ideia.
Depois de consultar a documentação, descobri que o projeto oferece SDKs oficiais para Python e JavaScript. Também dá para conectar o SDK da OpenAI alterando apenas duas linhas de código. É mais simples do que parece.
Mas simples não significa livre de armadilhas. Como acumular respostas em streaming? Como escrever o Agent Loop das chamadas de ferramentas? Como separar o raciocínio da resposta no modo thinking? Encontrei todos esses obstáculos na prática.
Este artigo resolve essas questões. Vamos comparar Python e Node.js e explicar tanto os SDKs nativos quanto a opção compatível com a OpenAI, formando um guia completo para desenvolver seu cliente.
Se você ainda não instalou o Ollama, comece pelo primeiro artigo da série, Integração entre LangChain e Ollama na prática, para colocar o modelo local em execução.
Capítulo 1: fundamentos da API do Ollama
Primeiro, vamos entender como a API funciona.
Por padrão, o Ollama inicia localmente um serviço de API REST no endereço http://localhost:11434/api. Ao abrir esse endereço no navegador, você verá apenas a mensagem “Ollama is running” — isso confirma que o serviço está funcionando.
Principais endpoints
Você precisa conhecer dois endpoints principais:
| Endpoint | Finalidade | Características |
|---|---|---|
/api/chat | Conversa com várias mensagens | Aceita um array messages e mantém o contexto |
/api/generate | Geração única | Simples e direto, ideal para tarefas pontuais |
Há também /v1/chat/completions, o endpoint compatível com a OpenAI. Se você já tem um projeto baseado na OpenAI, basta alterar base_url. Veremos isso em detalhes mais adiante.
Teste com curl
Primeiro, experimente a API da forma mais direta:
curl http://localhost:11434/api/chat -d '{
"model": "gemma3",
"messages": [
{ "role": "user", "content": "Por que o céu é azul?" }
]
}'
O terminal exibirá vários dados em JSON. O campo mais importante é message.content, que contém a resposta do modelo.
A estrutura da resposta é parecida com esta:
{
"model": "gemma3",
"created_at": "2026-04-18T01:23:45.678Z",
"message": {
"role": "assistant",
"content": "O céu parece azul principalmente porque..."
},
"done": true
}
O campo done é importante. Durante uma resposta em streaming, cada chunk traz done como false; apenas o último chunk traz true. Usaremos isso depois, ao tratar o streaming.
Respostas em streaming
Por padrão, a API espera o modelo terminar toda a geração para então retornar a resposta. Se você quiser mostrar ao usuário um efeito de texto sendo digitado, adicione stream: true:
curl http://localhost:11434/api/chat -d '{
"model": "gemma3",
"messages": [{ "role": "user", "content": "Por que o céu é azul?" }],
"stream": true
}'
Desta vez, o terminal exibirá o JSON linha por linha. Cada linha é um pequeno chunk, e você precisa reuni-los para formar a resposta completa.
Processar todos esses chunks manualmente dá trabalho. É justamente por isso que existem os SDKs oficiais: eles abstraem esses detalhes.
Capítulo 2: SDK para Python na prática
O SDK para Python é mantido oficialmente e muito fácil de instalar:
pip install ollama
Depois disso, ele já está pronto para uso. O suporte a Python 3.8 ou superior ajuda bastante.
Chamada básica
A forma mais simples exige poucas linhas:
from ollama import chat
response = chat(
model='gemma3',
messages=[{'role': 'user', 'content': 'Por que o céu é azul?'}]
)
print(response.message.content)
É só isso. A função chat() é um atalho oferecido pelo SDK e cria internamente um Client padrão conectado ao serviço local do Ollama.
Se quiser personalizar os parâmetros de conexão — por exemplo, quando o Ollama está em outra máquina — crie seu próprio Client:
from ollama import Client
client = Client(host='http://192.168.1.100:11434')
response = client.chat(model='gemma3', messages=[...])
Respostas em streaming
O streaming merece atenção. Em vez de fazer o usuário esperar e mostrar tudo de uma vez, você pode exibir o texto conforme ele é gerado.
from ollama import chat
stream = chat(
model='gemma3',
messages=[{'role': 'user', 'content': 'Por que o céu é azul?'}],
stream=True,
)
for chunk in stream:
print(chunk['message']['content'], end='', flush=True)
Aqui existe uma armadilha: chunk é um dicionário, não um objeto. Portanto, o acesso correto é chunk['message']['content'], não chunk.message.content. Eu mesmo perdi algum tempo com esse erro no início.
Cliente assíncrono
Se sua aplicação usa uma arquitetura assíncrona — com FastAPI ou aiohttp, por exemplo — use o cliente assíncrono:
import asyncio
from ollama import AsyncClient
async def main():
client = AsyncClient()
# Sem streaming
response = await client.chat(
model='gemma3',
messages=[{'role': 'user', 'content': 'Olá'}]
)
print(response.message.content)
# Com streaming
stream = await client.chat(
model='gemma3',
messages=[{'role': 'user', 'content': 'Por que o céu é azul?'}],
stream=True,
)
async for chunk in stream:
print(chunk['message']['content'], end='', flush=True)
asyncio.run(main())
O streaming assíncrono retorna um async generator, percorrido com async for. A lógica é igual à versão síncrona, com o acréscimo de await e async.
Cloud Models
Um recurso interessante é o suporte do SDK do Ollama a modelos na nuvem. Alguns modelos grandes demais para rodar localmente — como o gpt-oss de 120B — estão disponíveis na nuvem.
from ollama import chat
response = chat(
model='gpt-oss:120b-cloud',
messages=[{'role': 'user', 'content': 'Olá'}]
)
Um nome de modelo com o sufixo -cloud direciona a chamada para a API na nuvem. Naturalmente, você precisa de uma conta na nuvem do Ollama e de uma API Key; a configuração é um pouco diferente da versão local. Consulte a documentação oficial se quiser explorar o recurso.
Na prática, é uma opção útil: modelos menores rodam localmente e economizam dinheiro; modelos maiores rodam na nuvem e poupam hardware. Uma abordagem híbrida funciona bem.
Capítulo 3: SDK para Node.js na prática
O SDK para Node.js é igualmente simples:
npm i ollama
O mesmo pacote funciona tanto no Node.js quanto no navegador. Para a versão do navegador, use uma importação específica:
// Node.js
import ollama from 'ollama'
// Navegador
import ollama from 'ollama/browser'
Chamada básica
No Node.js, o fluxo já é assíncrono por padrão e fica bastante natural:
import ollama from 'ollama'
const response = await ollama.chat({
model: 'gemma3',
messages: [{ role: 'user', content: 'Por que o céu é azul?' }],
})
console.log(response.message.content)
Compare com a versão em Python: Python usa um dicionário em messages, enquanto Node.js usa um objeto. Os nomes dos parâmetros são praticamente iguais, então você não precisa reaprender os conceitos ao trocar de linguagem.
Respostas em streaming
O streaming no Node.js usa naturalmente um generator assíncrono:
import ollama from 'ollama'
const stream = await ollama.chat({
model: 'gemma3',
messages: [{ role: 'user', content: 'Por que o céu é azul?' }],
stream: true,
})
for await (const chunk of stream) {
process.stdout.write(chunk.message.content)
}
Usamos process.stdout.write em vez de console.log, pois console.log adiciona uma quebra de linha automaticamente. Você não quer uma nova linha a cada trecho gerado.
Configuração personalizada
O SDK aceita host e headers personalizados:
import ollama from 'ollama'
// Host personalizado
const client = new ollama.Ollama({ host: 'http://192.168.1.100:11434' })
// Ou configuração global
ollama.setDefaultHost('http://192.168.1.100:11434')
// Adiciona headers, por exemplo, para autenticação
const stream = await ollama.chat({
model: 'gemma3',
messages: [{ role: 'user', content: 'Olá' }],
headers: { Authorization: 'Bearer xxx' },
})
O parâmetro headers é útil. Se o seu serviço Ollama estiver atrás de um proxy de autenticação, você poderá enviar o token nesse campo.
Cancelamento de uma geração em streaming
O método abort() cancela uma geração em streaming que esteja em andamento:
import ollama from 'ollama'
const stream = await ollama.chat({
model: 'gemma3',
messages: [{ role: 'user', content: 'Escreva um artigo longo...' }],
stream: true,
})
// O usuário clicou no botão de parar
ollama.abort()
for await (const chunk of stream) {
// O loop termina antes do fim após abort
process.stdout.write(chunk.message.content)
}
Esse recurso é indispensável em uma interface de chat. Se o usuário não quiser esperar o modelo terminar um texto longo, pode interromper a geração com um botão.
Versão para navegador
O uso no navegador é semelhante, mas tem algumas diferenças:
import ollama from 'ollama/browser'
// No navegador, use streaming, pois a API nativa não aceita uma solicitação sem streaming entre origens
const stream = await ollama.chat({
model: 'gemma3',
messages: [{ role: 'user', content: 'Olá' }],
stream: true,
})
for await (const chunk of stream) {
document.getElementById('output').textContent += chunk.message.content
}
A versão para navegador tem uma limitação: é necessário usar o modo streaming. Uma requisição sem streaming da API do Ollama retorna um JSON grande de uma só vez, e uma requisição entre origens pode expirar ou ser bloqueada. Como o streaming divide a resposta em chunks, esses problemas são menos frequentes.
Essa escolha faz sentido. Uma interface de chat no navegador normalmente já precisa exibir a geração em tempo real.
Capítulo 4: chamadas de ferramentas na prática
Chamadas de ferramentas são a base para criar agentes. O Ollama permite que o modelo chame funções definidas por você e continue gerando a resposta com base nos resultados dessas funções.
O SDK para Python tem um recurso bastante prático: você pode passar diretamente uma função Python como ferramenta, e o SDK interpreta automaticamente sua docstring e os tipos dos parâmetros.
Interpretação automática de funções Python
def get_weather(city: str) -> str:
"""Retorna informações meteorológicas de uma cidade
Args:
city: Nome da cidade, como "Pequim" ou "Xangai"
Returns:
String com a descrição do tempo
"""
# Dados simulados
weather_data = {
'Pequim': 'Ensolarado, temperatura de 18 °C',
'Xangai': 'Nublado, temperatura de 22 °C',
'Guangzhou': 'Chuva, temperatura de 26 °C',
}
return weather_data.get(city, f'Não há dados meteorológicos para {city}')
from ollama import chat
response = chat(
model='qwen3',
messages=[{'role': 'user', 'content': 'Como está o tempo hoje em Pequim?'}],
tools=[get_weather],
)
print(response.message.content)
O SDK transforma automaticamente a função na definição de uma ferramenta: o nome vem da função, a descrição vem da docstring e os parâmetros vêm das anotações de tipo. Isso evita escrever o JSON Schema manualmente.
Padrão Agent Loop
Mas a situação pode ser mais complexa. O modelo pode chamar várias ferramentas ou querer chamar outra ferramenta depois de receber o primeiro resultado. Nesse caso, você precisa de um ciclo de processamento.
Esse ciclo é o Agent Loop:
from ollama import chat
def add(a: int, b: int) -> int:
"""Operação de adição"""
return a + b
def multiply(a: int, b: int) -> int:
"""Operação de multiplicação"""
return a * b
tools = [add, multiply]
tool_map = {'add': add, 'multiply': multiply}
messages = [{'role': 'user', 'content': 'Calcule (3 + 5) * 2'}]
while True:
response = chat(model='qwen3', messages=messages, tools=tools)
if response.message.tool_calls:
# O modelo quer chamar uma ferramenta
for call in response.message.tool_calls:
func_name = call.function.name
func_args = call.function.arguments
result = tool_map[func_name](**func_args)
# Adiciona o resultado da ferramenta ao histórico de mensagens
messages.append({
'role': 'tool',
'content': str(result),
'tool_name': func_name,
})
else:
# Nenhuma ferramenta foi chamada, então o processamento terminou
print(response.message.content)
break
A lógica é esta:
- Envie uma mensagem ao modelo junto com as definições das ferramentas.
- Se o modelo retornar
tool_calls, execute as funções correspondentes. - Adicione os resultados das funções ao histórico e envie-o novamente ao modelo.
- Repita até o modelo parar de solicitar ferramentas.
Esse padrão é indispensável ao criar agentes. Você define um conjunto de funções, e o modelo decide quando chamá-las, quais usar e em que ordem.
Modo thinking
Alguns modelos, como o qwen3, oferecem o modo thinking. O modelo primeiro “pensa” e depois produz uma resposta.
from ollama import chat
stream = chat(
model='qwen3',
messages=[{'role': 'user', 'content': 'Por que o céu é azul?'}],
stream=True,
think=True,
)
thinking = ''
content = ''
for chunk in stream:
if chunk.message.thinking:
thinking += chunk.message.thinking
elif chunk.message.content:
content += chunk.message.content
print('=== Processo de raciocínio ===')
print(thinking)
print('=== Resposta final ===')
print(content)
No modo thinking, cada chunk ganha um campo thinking. Você precisa acumular separadamente o raciocínio e a resposta final.
Esse recurso é interessante porque permite observar como o modelo chega à resposta passo a passo. Ele é útil em aplicações educacionais e durante a depuração de prompts.
Capítulo 5: SDK nativo ou API compatível com a OpenAI
Agora você tem duas opções:
- Usar o SDK nativo do Ollama, apresentado anteriormente.
- Usar o SDK da OpenAI e alterar o endereço para se conectar ao Ollama.
Qual é a melhor? Depende do seu cenário.
Solução compatível com a OpenAI
Se você já tem um projeto OpenAI, a migração mais simples consiste em alterar base_url:
from openai import OpenAI
client = OpenAI(
base_url='http://localhost:11434/v1',
api_key='ollama', # Obrigatório, mas ignorado
)
response = client.chat.completions.create(
model='gemma3',
messages=[{'role': 'user', 'content': 'Por que o céu é azul?'}],
)
print(response.choices[0].message.content)
É simples assim. O SDK da OpenAI não precisa saber que o Ollama está por trás da requisição; para ele, trata-se apenas de uma API compatível com a OpenAI.
A versão em Node.js funciona da mesma forma:
import OpenAI from 'openai'
const client = new OpenAI({
baseURL: 'http://localhost:11434/v1',
apiKey: 'ollama',
})
const completion = await client.chat.completions.create({
model: 'gemma3',
messages: [{ role: 'user', content: 'Por que o céu é azul?' }],
})
console.log(completion.choices[0].message.content)
Comparação entre as duas opções
| Aspecto | SDK nativo | Compatibilidade com a OpenAI |
|---|---|---|
| Instalação | pip install ollama | Basta ter o SDK da OpenAI |
| Chamadas de ferramentas | Interpreta automaticamente a docstring da função | Exige JSON Schema escrito manualmente |
| Respostas em streaming | Chunks em formato de dicionário | Formato padrão da OpenAI |
| Cloud Models | Compatível | Não compatível |
| Custo de migração | Nenhum em projetos novos | Muito baixo em projetos existentes |
Como escolher
Projeto novo: use o SDK nativo.
Motivos:
- A chamada de ferramentas é mais conveniente: você passa uma função Python diretamente.
- Há suporte a mais recursos, como Cloud Models e o modo thinking.
- A documentação e os exemplos são oficiais, o que facilita a solução de problemas.
Migração de um projeto OpenAI existente: use a solução compatível com a OpenAI.
Motivos:
- Duas alterações de código já são suficientes para executar o projeto.
- Não é necessário reescrever a lógica existente.
- Também é fácil voltar para a OpenAI no futuro.
Em resumo: o SDK nativo tem mais recursos; a solução compatível com a OpenAI permite uma migração mais rápida. Escolha de acordo com as necessidades do projeto.
Testei as duas opções. A chamada de ferramentas do SDK nativo realmente poupa trabalho, pois você não precisa escrever as definições em JSON Schema: basta documentar bem a função. Mas, se o projeto já usa a OpenAI, não há motivo para refatorar tudo apenas para adotar o Ollama.
Conclusão
Depois de tudo isso, estes são os pontos principais:
Chamada básica: os SDKs para Python e Node.js oferecem uma ótima abstração, e poucas linhas de código são suficientes. Para respostas em streaming, lembre-se de ativar stream=True.
Chamadas de ferramentas: o Agent Loop é o padrão central — processe tool_calls em um ciclo até o modelo parar de solicitar ferramentas. O SDK para Python aceita uma função diretamente como ferramenta, evitando a criação manual de um JSON Schema.
Modo thinking: modelos como o qwen3 permitem visualizar o processo de raciocínio. Trate separadamente os campos thinking e content de cada chunk.
Escolha da solução: em um projeto novo, use o SDK nativo para ter mais recursos; em um projeto OpenAI existente, use a opção compatível e apenas altere o endereço.
Próximos passos recomendados:
- Se você ainda não instalou o Ollama, comece pelo primeiro artigo da série e coloque o modelo local em execução.
- Escolha a opção mais adequada ao projeto — nativa ou compatível com a OpenAI — e faça um teste.
- A documentação oficial recebe novos recursos continuamente, então vale a pena consultá-la de tempos em tempos.
Executar LLMs localmente está cada vez mais acessível. O Ollama esconde a complexidade por trás de uma API simples: você só precisa saber como chamá-la e pode deixar o restante por conta da ferramenta.
Este é o segundo artigo da série. No próximo, veremos como personalizar modelos com um Modelfile e ajustá-los ao comportamento desejado.
Desenvolvimento de clientes para a API do Ollama
Guia completo para chamar a API de modelos locais do Ollama com os SDKs para Python ou Node.js
⏱️ Estimated time: 45 min
- 1
Step 1: Instale o SDK e teste uma chamada básica
Quem usa Python deve executar `pip install ollama`; quem usa Node.js, `npm i ollama`.
Depois da instalação, teste a conexão com o código mais simples possível:
```python
from ollama import chat
response = chat(model='gemma3', messages=[{'role': 'user', 'content': 'Olá'}])
print(response.message.content)
```
Verifique se o serviço do Ollama está em execução, por padrão na porta 11434, e se o modelo correspondente já foi baixado. - 2
Step 2: Implemente respostas em streaming
Ative o streaming para que o usuário acompanhe a resposta conforme ela é gerada:
```python
from ollama import chat
stream = chat(model='gemma3', messages=[...], stream=True)
for chunk in stream:
print(chunk['message']['content'], end='', flush=True)
```
Observe que cada chunk é um dicionário; acesse o conteúdo com `chunk['message']['content']`. - 3
Step 3: Configure chamadas de ferramentas (opcional)
Defina uma função Python como ferramenta; o SDK interpreta automaticamente a docstring e as anotações de tipo:
```python
def get_weather(city: str) -> str:
"""Retorna informações meteorológicas de uma cidade"""
return f'{city}: ensolarado'
response = chat(model='qwen3', messages=[...], tools=[get_weather])
```
Implemente um Agent Loop para processar várias chamadas de ferramentas até o modelo retornar a resposta final. - 4
Step 4: Escolha entre a solução nativa e a compatível com a OpenAI
Para projetos novos, o SDK nativo é recomendado por oferecer mais recursos, como Cloud Models e o modo thinking.
Em um projeto OpenAI existente, basta alterar duas linhas:
```python
client = OpenAI(base_url='http://localhost:11434/v1', api_key='ollama')
```
O custo de migração é muito baixo, e você pode voltar para a OpenAI quando quiser.
FAQ
Qual é a porta e o endereço padrão da API do Ollama?
Que tipo de dado o streaming do SDK para Python retorna?
Quais são as limitações do SDK para Node.js no navegador?
O que é o padrão Agent Loop?
Como separar o raciocínio da resposta final no modo thinking?
Como escolher entre o SDK nativo e a solução compatível com a OpenAI?
13 min de leitura · Publicado em: 18 abr 2026 · Atualizado em: 4 set 2026
Guia Ollama LLM local
Se você chegou pela busca, o caminho mais rápido é ir para o post anterior ou próximo desta série.
Anterior
Chamadas à API do Ollama: do curl à interface compatível com o SDK da OpenAI
Aprenda duas formas de chamar a API do Ollama: a API REST nativa com curl e a interface compatível com o SDK da OpenAI. Inclui exemplos completos, processamento de respostas em streaming e boas práticas.
Parte 8 de 13
Próximo
LangChain + Ollama na prática: guia completo para criar aplicações com LLM local
Aprenda a integrar LangChain e Ollama com exemplos de Chat, RAG e Agent, além de estratégias para alternar entre modelos locais e a OpenAI.
Parte 10 de 13



Comentários
Entre com GitHub para comentar