Guias

Ollama agente IA local: tutorial completo 2026

La mayoría de la gente usa ChatGPT o Claude. Pero tus datos van a la nube y dependes de que OpenAI/Anthropic siga abierto. Con Ollama puedes correr modelos LLM localmente y armar agentes completos sin Internet.

TL;DR — Lo que vas a tener al final

  • Tiempo de setup: 2-3 horas para el primer LLM funcionando.
  • Requisitos: GPU NVIDIA con 12+ GB VRAM (RTX 3060 mínimo).
  • Resultado: LLM local con API OpenAI-compatible, integrable con n8n/Open WebUI.
  • Troubleshooting: nvidia-smi, ollama ps, OOM con modelos grandes.

¿Qué es Ollama?

Ollama es una herramienta que simplifica correr modelos LLM en tu máquina. Antes necesitabas Python + llama.cpp + config manual. Ollama lo hace con un comando.

¿Qué modelos puedes correr?

Modelo Tamaño RAM mínima Calidad
Llama 3.2 1B 1 GB 2 GB Baja
Llama 3.2 3B 2 GB 4 GB Media
Phi-3.5 Mini 2.3 GB 4 GB Media-alta
Llama 3.1 8B 4.7 GB 8 GB Alta
Mistral 7B 4.1 GB 8 GB Alta
Qwen 2.5 14B 9 GB 16 GB Muy alta
Llama 3.1 70B 40 GB 48 GB Excelente
DeepSeek V3 671B 400 GB 512 GB State-of-the-art

Para empezar, te recomiendo: llama3.2:3b (cualquier laptop moderna lo corre).

Instalación

Linux

curl -fsSL https://ollama.com/install.sh | sh

macOS

brew install ollama
# O bajar de ollama.com

Verificar

ollama --version

Tu primer chat

ollama run llama3.2:3b

Te aparece el prompt interactivo. prueba:

>>> ¿Cuál es la capital de Francia?
La capital de Francia es París.
>>> ¿Y de Canadá?
Ottawa. 
>>> /bye

Models: cómo gestionar

Bajar un modelo

ollama pull llama3.2:3b
ollama pull phi3.5:3.8b
ollama pull mistral:7b

Listar descargados

ollama list

Borrar

ollama rm llama3.2:3b

Modelos custom

puedes crear tu propio modelo con un Modelfile:

mkdir mi-modelo
cat > mi-modelo/Modelfile <<'EOF'
FROM llama3.2:3b
SYSTEM """eres un experto en Linux y DevOps.
Respondés en español rioplatense, con ejemplos concretos y comandos."""
PARAMETER temperature 0.7
PARAMETER top_p 0.9
EOF
ollama create linux-expert -f mi-modelo/Modelfile
ollama run linux-expert

HTTP API

Ollama expone una API REST en http://localhost:11434:

Chat completion

curl http://localhost:11434/api/chat -d '{
    "model": "llama3.2:3b",
    "messages": [
        {"role": "user", "content": "Explicame Docker en una frase"}
    ]
}'

Generate

curl http://localhost:11434/api/generate -d '{
    "model": "llama3.2:3b",
    "prompt": "Cuál es la diferencia entre SQL y NoSQL?"
}'

Streaming

Por defecto la API responde con NDJSON (un JSON por línea). Para streaming en una línea continua y mostrar tokens a medida que se generan, agregá "stream": true explícito y procesá cada JSON line en el cliente. Ejemplo con curl + jq:

curl -N http://localhost:11434/api/generate -d '{
    "model": "llama3.2:3b",
    "prompt": "Contame un chiste corto",
    "stream": true
}' | jq -r '.response // empty'

Function calling (tools)

Esto es lo que hace que un agente funcione. El modelo puede llamar funciones externas.

1. Definí las tools

import requests
import json
def get_weather(city: str) -> str:
    """Obtiene el clima actual de una ciudad"""
    return f"En {city} hace 22°C y está soleado"
def get_news(topic: str) -> str:
    """Obtiene las últimas noticias sobre un tema"""
    return f"Noticias sobre {topic}: hay 3 resultados relevantes"
# Schema para Ollama
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Obtiene el clima de una ciudad",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {"type": "string", "description": "Nombre de la ciudad"}
                },
                "required": ["city"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "get_news",
            "description": "Obtiene noticias sobre un tema",
            "parameters": {
                "type": "object",
                "properties": {
                    "topic": {"type": "string", "description": "Tema"}
                },
                "required": ["topic"]
            }
        }
    }
]
available_functions = {
    "get_weather": get_weather,
    "get_news": get_news,
}

2. Loop del agente

import ollama
MAX_ITER = 8  # tope de iteraciones para evitar loops infinitos
def run_agent(user_message: str, model: str = "llama3.2:3b"):
    messages = [{"role": "user", "content": user_message}]
    for _ in range(MAX_ITER):
        # Llamar al modelo
        response = ollama.chat(
            model=model,
            messages=messages,
            tools=tools,
        )
        # Agregar response a messages
        messages.append(response['message'])
        # ¿El modelo quiere llamar tools?
        if response['message'].get('tool_calls'):
            for tool_call in response['message']['tool_calls']:
                function_name = tool_call['function']['name']
                function_args = tool_call['function']['arguments']
                print(f"🔧 Llamando {function_name}({function_args})")
                # Si el modelo inventó una tool que no existe, no rompemos
                fn = available_functions.get(function_name)
                if fn is None:
                    messages.append({
                        'role': 'tool',
                        'content': f"Error: función {function_name} no existe",
                    })
                    continue
                # Ejecutar la función
                function_response = fn(**function_args)
                # Agregar el resultado
                messages.append({
                    'role': 'tool',
                    'content': str(function_response),
                })
                print(f"📋 Resultado: {function_response}")
        else:
            # El modelo respondió con texto
            return response['message']['content']
    # Si llegamos acá, el modelo entró en loop o se quedó en tools
    return response['message'].get('content') or "(sin respuesta tras agotar iteraciones)"
# Probar
result = run_agent("¿Qué clima hace en Buenos Aires y dame noticias de tecnología?")
print(result)

3. Modelos con buen tool support

No todos los modelos siguen tools de forma confiable. Para producción recomiendo:

  • qwen2.5:7b o qwen2.5:14b — el mejor tool-calling open source en su tamaño (Excelente seguimiento de schema JSON).
  • llama3.1:8b — buen balance calidad/recursos.
  • mistral-nemo:12b — alternativa sólida con buen soporte de tools.
  • nemotron-mini:4b — sorprendentemente bueno para tool calling en tamaño chico.

Evitar para tools: llama3.2:1b, phi3.5:3.8b — siguen instrucciones JSON de forma inconsistente.

MCP (Model Context Protocol): el estándar 2026

MCP es el protocolo abierto que Anthropic lanzó a fines de 2024 y que se convirtió en el estándar de facto para conectar LLMs a herramientas externas (lectura de archivos, búsqueda web, bases de datos, GitHub, etc.). Ollama 0.4+ lo soporta nativamente.

¿Qué cambia con MCP?

En vez de escribir un loop de function calling a mano (sección anterior), Ollama puede conectarse a servidores MCP que exponen tools automáticamente. tú escribís el server MCP una vez y cualquier modelo compatible los usa.

Instalación

Ollama ya trae cliente MCP integrado. Solo necesitas instalar servidores. Los más populares:

  • filesystem — leer/escribir archivos locales.
  • fetch — hacer requests HTTP desde el agente.
  • git — inspeccionar repos git, diff, history.
  • github — search de issues, crear PRs, leer código.
  • postgres / sqlite — queries SQL sobre bases de datos.

Ejemplo con el servidor oficial filesystem

# 1. Instalar uv (gestor de paquetes Python moderno)
curl -LsSf https://astral.sh/uv/install.sh | sh
# 2. Agregar el server MCP filesystem al config de Ollama
mkdir -p ~/.config/ollama
cat > ~/.config/ollama/mcp.json <<'EOF'
{
  "mcp_servers": {
    "filesystem": {
      "command": "uvx",
      "args": ["mcp-server-filesystem", "/home/tu-usuario"]
    }
  }
}
EOF
# 3. Reiniciar Ollama
systemctl --user restart ollama
# 4. Ahora tu agente puede leer archivos locales automáticamente.

Cliente MCP en Python

Si quieres controlar el flujo tú mismo, usa el cliente MCP oficial. Acá un ejemplo de agente que combina Ollama + tools MCP remotas:

import asyncio
import ollama
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
async def run_mcp_agent():
    # Conectar a un server MCP (ejemplo: filesystem)
    server_params = StdioServerParameters(
        command="uvx",
        args=["mcp-server-filesystem", "/home/tu-usuario"],
    )
    async with stdio_client(server_params) as (read, write):
        async with ClientSession(read, write) as session:
            await session.initialize()
            # Listar tools que expone el server MCP
            tools_resp = await session.list_tools()
            mcp_tools = [
                {
                    "type": "function",
                    "function": {
                        "name": t.name,
                        "description": t.description,
                        "parameters": t.inputSchema,
                    }
                }
                for t in tools_resp.tools
            ]
            # Combinar MCP tools + tus tools locales
            all_tools = mcp_tools + tools
            messages = [{"role": "user", "content": "Listame los archivos en mi home"}]
            while True:
                response = ollama.chat(
                    model="qwen2.5:7b",
                    messages=messages,
                    tools=all_tools,
                )
                messages.append(response["message"])
                if not response["message"].get("tool_calls"):
                    print(response["message"]["content"])
                    return
                for tc in response["message"]["tool_calls"]:
                    fn_name = tc["function"]["name"]
                    fn_args = tc["function"]["arguments"]
                    print(f"🔧 MCP: {fn_name}({fn_args})")
                    # Si la tool viene de MCP, despachar por JSON-RPC
                    if any(t["function"]["name"] == fn_name for t in mcp_tools):
                        result = await session.call_tool(fn_name, fn_args)
                        content = str(result.content)
                    else:
                        # Si es local, usar tu diccionario de funciones
                        content = str(available_functions[fn_name](**fn_args))
                    messages.append({"role": "tool", "content": content})
asyncio.run(run_mcp_agent())

Por qué MCP importa: es el protocolo que estandarizó la integración agente-herramientas. La mayoría de los proveedores (Anthropic, OpenAI, Google, Mistral, Ollama) ya lo soportan. Si vas a construir un agente serio, MCP es el camino.

Caso real: agente que controla tu homelab

import subprocess
import ollama
def run_command(cmd: str) -> str:
    """Ejecuta un comando en el server y devuelve output"""
    try:
        result = subprocess.run(
            cmd, shell=True, capture_output=True, text=True, timeout=30
        )
        return result.stdout[:2000] or "(sin output)"
    except Exception as e:
        return f"Error: {e}"
def restart_service(service: str) -> str:
    """Reinicia un servicio systemd"""
    result = subprocess.run(
        f"sudo systemctl restart {service}",
        shell=True, capture_output=True, text=True
    )
    return f"Servicio {service} reiniciado. Output: {result.stdout[:500]}"
def check_disk() -> str:
    """Verifica uso de disco"""
    result = subprocess.run("df -h", shell=True, capture_output=True, text=True)
    return result.stdout
tools = [
    {
        "type": "function",
        "function": {
            "name": "run_command",
            "description": "Ejecuta un comando shell y devuelve output",
            "parameters": {
                "type": "object",
                "properties": {
                    "cmd": {"type": "string"}
                },
                "required": ["cmd"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "restart_service",
            "description": "Reinicia un servicio systemd",
            "parameters": {
                "type": "object",
                "properties": {
                    "service": {"type": "string"}
                },
                "required": ["service"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "check_disk",
            "description": "Verifica el espacio en disco",
            "parameters": {"type": "object", "properties": {}}
        }
    }
]
functions = {
    "run_command": run_command,
    "restart_service": restart_service,
    "check_disk": check_disk,
}
SYSTEM = """eres un agente DevOps que controla un servidor Linux.
- usa las tools cuando haga falta.
- Si el usuario pide reiniciar nginx, usa restart_service("nginx").
- Si pide info de disco, usa check_disk().
- Si pide algo más, usa run_command().
- Respondés en español."""
MAX_ITER = 10
def devops_agent(message: str):
    messages = [
        {"role": "system", "content": SYSTEM},
        {"role": "user", "content": message}
    ]
    for _ in range(MAX_ITER):
        response = ollama.chat(
            model="llama3.1:8b",   # 8B para tareas más complejas
            messages=messages,
            tools=tools,
        )
        messages.append(response['message'])
        if not response['message'].get('tool_calls'):
            return response['message']['content']
        for tc in response['message']['tool_calls']:
            fn = functions[tc['function']['name']]
            args = tc['function'].get('arguments', {})
            result = fn(**args) if args else fn()
            messages.append({'role': 'tool', 'content': str(result)})
# Uso interactivo
while True:
    user = input("tú: ")
    if user.lower() in ['exit', 'quit']:
        break
    response = devops_agent(user)
    print(f"Bot: {response}")

UI para usar el agente

Si quieres algo gráfico, hay opciones:

Open WebUI (recomendado)

docker run -d -p 3000:8080 
    -e OLLAMA_BASE_URL=http://host.docker.internal:11434 
    --name open-webui 
    --restart always 
    ghcr.io/open-webui/open-webui:main

Accedés a http://localhost:3000. UI tipo ChatGPT, conectada a tu Ollama.

Otros

  • Page Assist — extensión de Chrome.
  • LibreChat — UI completa con multi-modelo.

Performance tips

Cuánta RAM necesitas

Modelo RAM mínima RAM recomendada
3B 4 GB 8 GB
7B 8 GB 16 GB
14B 16 GB 24 GB
70B 48 GB 64 GB

GPU acceleration

Ollama detecta automáticamente tu GPU NVIDIA/AMD. verifica:

ollama run llama3.2:3b
# Output: "loaded in X.Xs" - si ves CUDA/Metal/ROCm, está usando GPU

Modelos cuantizados

Por default Ollama descarga el modelo cuantizado a q4_0 (4-bit). Si quieres más calidad, puedes pedir un quant específico — Ollama 0.4+ soporta la familia q2_K, q3_K, q4_0, q4_K_M, q5_K_M, q6_K, q8_0 y f16. Ejemplo:

ollama pull llama3.1:8b-instruct-q6_K   # 6-bit, mejor calidad

Configuración del server

/etc/systemd/system/ollama.service.d/override.conf:

[Service]
Environment="OLLAMA_NUM_PARALLEL=2"
Environment="OLLAMA_MAX_LOADED_MODELS=2"
Environment="OLLAMA_KEEP_ALIVE=10m"

OLLAMA_KEEP_ALIVE controla cuánto tiempo se mantiene el modelo cargado en RAM después de usarlo.

Casos de uso reales

1. Asistente de código local

ollama run codellama:13b
>>> #include <stdio.h>
...     int main() {
...         printf("Hello, World!n");
...         return 0;
...     }
Explicame este código

2. Resumir documentos largos

import ollama
def summarize(text):
    response = ollama.chat(
        model='llama3.1:8b',
        messages=[{
            'role': 'user',
            'content': f'Resumí este documento en 3 párrafos:nn{text}'
        }]
    )
    return response['message']['content']
with open('documento.txt') as f:
    text = f.read()
print(summarize(text))

3. Clasificar emails / tickets

def classify_email(subject, body):
    response = ollama.chat(
        model='llama3.2:3b',
        messages=[{
            'role': 'user',
            'content': f'''Clasificá este email en una de estas categorías:
- bug
- feature_request
- question
- spam
Subject: {subject}
Body: {body}
Respondé SOLO con la categoría, sin explicación.'''
        }]
    )
    return response['message']['content'].strip()

4. Análisis de logs

def analyze_logs(log_lines):
    response = ollama.chat(
        model='llama3.1:8b',
        messages=[{
            'role': 'user',
            'content': f'''Analizá estos logs y decime:
1. ¿Hay errores críticos?
2. ¿Hay patrones sospechosos?
3. Recomendación inmediata
Logs:
{chr(10).join(log_lines[:100])}'''
        }]
    )
    return response['message']['content']

Limitaciones

  • Modelos chicos son menos precisos. Un 7B local no compite con GPT-4.
  • No tienes multimodal (imágenes) out-of-the-box — para eso está llava o llama3.2-vision en Ollama.
  • Setup inicial requiere tiempo.
  • No hay historial de búsqueda web sin tools adicionales (o MCP servers como fetch).

Para tareas críticas (medicina, legal, financiero), no confíes solo en modelos locales sin verificar.

Preguntas frecuentes

¿Por qué Ollama agente IA local: tutorial completo 2026 es relevante para sysadmins Linux?

Forma parte del flujo diario de administración. Los conceptos explicados se aplican directamente a servidores en producción y resuelven problemas reales que enfrentan sysadmins hispanohablantes.

¿Qué necesito para empezar con Ollama agente IA local: tutorial?

Distribución Linux actualizada (Debian, Ubuntu, RHEL, Fedora o Arch), acceso root, y conexión a internet. Para producción: entorno de staging separado antes de aplicar cambios.

¿Cuáles son los errores más comunes con Ollama agente IA local: tutorial?

Los tres más frecuentes: (1) saltar la lectura de logs, (2) aplicar cambios directos en producción sin probar, (3) olvidar permisos y ownership. La documentación y un plan de rollback siempre.

¿Cuándo usar Ollama agente IA local: tutorial y cuándo una alternativa?

Esta solución es ideal para el caso descrito. Alternativas como Docker, Ansible o configuración manual pueden ser mejores según contexto: portabilidad, escala y reproducibilidad son los factores clave.

¿Cómo migro desde una configuración previa a Ollama agente IA local: tutorial?

Documentar el estado actual, probar la nueva configuración en staging, validar funcionalmente, y aplicar en producción con rollback plan listo. Los posts de SoyLinux incluyen troubleshooting para los problemas más comunes.

Lee también

Alfonso Moreno | Sysadmin Senior

Soy Alfonso, sysadmin senior con RHCE y más de 10 años administrando sistemas Linux para empresas y proyectos personales. Me especializo en infraestructura, redes, virtualización, monitoring, automation y self-hosting. Sobre SoyLinux.com SoyLinux.com es un blog técnico en español sobre Linux, software libre y self-hosting. Lo mantengo en mi tiempo libre. Áreas de expertise - Linux server administration: RHEL, CentOS, Rocky, Alma, Fedora, Debian, Ubuntu - Network services: Postfix, BIND, Samba, NFS, Squid - Virtualización y containers: KVM, Proxmox, Docker, Podman - Monitoring: Prometheus, Grafana, Zabbix - Automation: Ansible, Bash scripting - Self-hosting: Vaultwarden, Nextcloud, Jellyfin, Immich, Homelab Contacto - Email: [email protected]

One thought on “Ollama agente IA local: tutorial completo 2026”

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *