Blog / Tutorials

Run a Local AI Agent on a VPS: Autonomous Task Execution with Ollama

By the NoctHost TeamJuly 9, 20263 min read

AI agents go beyond single-turn responses. They plan, take actions, observe results, and keep going until a task is complete. Most agent frameworks — AutoGPT, CrewAI, LangGraph — are designed around cloud APIs. But they work with local Ollama models too.

This guide sets up a basic agent loop on a VPS: a local LLM that can execute Python code, read files, and complete multi-step tasks without leaving your server.

What an Agent Actually Is

At its core, an agent is a loop:

  1. Receive a task
  2. Think about what to do
  3. Take an action (run code, read a file, search)
  4. Observe the result
  5. Decide what to do next
  6. Repeat until done

The LLM handles steps 2, 3, and 5. Your code handles the rest.

Setup

pip3 install ollama --break-system-packages
ollama pull llama3.1:8b

A Minimal Agent

# agent.py
import ollama
import subprocess
import json
import re

MODEL = "llama3.1:8b"

SYSTEM_PROMPT = """You are an AI agent that completes tasks by writing and running Python code.

When you want to run code, output it in this format:
<code>
your python code here
</code>

After seeing the output, continue thinking and either run more code or give your final answer.
When you're done, output: DONE: [your final answer]"""

def run_code(code: str) -> str:
    try:
        result = subprocess.run(
            ["python3", "-c", code],
            capture_output=True,
            text=True,
            timeout=30
        )
        output = result.stdout + result.stderr
        return output[:2000] if output else "(no output)"
    except subprocess.TimeoutExpired:
        return "Error: code timed out after 30 seconds"
    except Exception as e:
        return f"Error: {e}"

def extract_code(text: str):
    match = re.search(r'<code>(.*?)</code>', text, re.DOTALL)
    return match.group(1).strip() if match else None

def run_agent(task: str, max_steps: int = 10):
    messages = [
        {"role": "system", "content": SYSTEM_PROMPT},
        {"role": "user", "content": task}
    ]

    for step in range(max_steps):
        print(f"\n--- Step {step + 1} ---")

        response = ollama.chat(model=MODEL, messages=messages)
        assistant_message = response['message']['content']
        print(f"Agent: {assistant_message[:500]}")

        messages.append({
            "role": "assistant",
            "content": assistant_message
        })

        if "DONE:" in assistant_message:
            final = assistant_message.split("DONE:")[-1].strip()
            print(f"\nFinal answer: {final}")
            return final

        code = extract_code(assistant_message)
        if code:
            print(f"\nRunning code...")
            output = run_code(code)
            print(f"Output: {output}")

            messages.append({
                "role": "user",
                "content": f"Code output:\n{output}\n\nContinue with the task."
            })

    return "Max steps reached"

# Example
result = run_agent(
    "Calculate the first 20 Fibonacci numbers and find which ones are prime."
)

Running It

python3 agent.py

The agent will write code, run it, see the output, and keep going until it has an answer.

Safe Execution

The example above runs code directly on your server. For production use, sandbox the execution:

# Run code inside a Docker container with no network access
docker run --rm --network none python:3.11-slim python3 -c "your code here"

Replace the subprocess.run call with a Docker-based sandbox for untrusted code.

Extending the Agent

Add more tools by giving the agent new action formats:

# Read a file
def read_file(path: str) -> str:
    try:
        return open(path).read()[:3000]
    except Exception as e:
        return f"Error: {e}"

# Web search (requires requests)
def search_web(query: str) -> str:
    import requests
    response = requests.get(
        f"https://api.duckduckgo.com/?q={query}&format=json"
    )
    data = response.json()
    return data.get('AbstractText', 'No result found')

Document the tools in your system prompt and parse the agent's output for the corresponding action tags.

Running this on NoctHost

An agent loop is only as fast as its model, so budget by model size: a 7B model on the Pro plan (4 vCPU, 8 GB) gives responsive tool-use, while lighter agents run on the Standard plan (2 vCPU, 4 GB). NoctHost bills hourly from a prepaid balance you top up with crypto, no card and no KYC, and the sandbox from earlier keeps an autonomous agent safely boxed in.

Spin one up in about a minute

Email signup, pay with crypto, hourly billing. Trying a box costs cents — destroy it when you are done.

Deploy a server

Frequently asked

Which model works best for agents?
Larger models follow instructions more reliably. Llama 3.3 8B works for simple tasks. For complex multi-step reasoning, DeepSeek R1 7B or Qwen 2.5 14B give better results if your RAM allows.
Is this safe to run on a server?
The example runs arbitrary code on your server — only use it for tasks you control. For any production agent, use Docker-based sandboxing with no network access and strict resource limits.
Can I build a web interface for it?
Yes — wrap the agent in a FastAPI endpoint and add a simple frontend. Open WebUI also has experimental agent support that connects directly to Ollama.

Keep reading