How to Create an AI Agent: A Practical Guide for Developers
Disclosure: This post contains one or more links to providers we have a real, registered affiliate/referral relationship with. We may earn a commission at no extra cost to you if you sign up through them.
If you’ve spent any time reading DevOps forums or Hacker News in the last year, you’ve seen the term “AI agent” thrown around constantly. Most of the explanations stop at theory. This guide doesn’t. We’re going to build a working AI agent in Python, wrap it in Docker, and deploy it to a real Linux server — the same way you’d ship any other production service.
By the end of this article you’ll understand what an AI agent actually is (beyond the marketing buzzword), how to structure one, how to give it tool-use capabilities, and how to run it reliably in production — including logging, monitoring, and basic security hardening.
What Is an AI Agent, Really?
An AI agent is a program that uses a large language model (LLM) as its reasoning engine, combined with a loop that lets it take actions, observe results, and decide what to do next — without a human manually scripting every step.
The key difference between an AI agent and a simple chatbot wrapper is autonomy through iteration. A chatbot takes input and returns output once. An agent can:
This is why agents are useful for DevOps and infrastructure work specifically — tasks like “check if this container is healthy, and restart it if not” or “summarize last night’s error logs and file a ticket” are naturally iterative and benefit from an LLM’s ability to reason over unstructured text.
Core Components of an Agent
Every functional AI agent, regardless of framework, has the same four pieces:
You can build this from scratch in under 150 lines of Python, which is exactly what we’ll do below.
Prerequisites
Before you start, make sure you have:
If you don’t already have a VPS, DigitalOcean is a solid choice for running small agent workloads — their basic droplets are cheap enough to experiment with without committing to a large monthly bill.
Building the Agent Step by Step
Setting Up the Environment
Start with a clean virtual environment and the minimal dependencies. We’re deliberately avoiding a heavyweight framework for the first pass so you understand exactly what’s happening under the hood.
mkdir ai-agent && cd ai-agent
python3 -m venv venv
source venv/bin/activate
pip install openai python-dotenv
Create a .env file to hold your API key — never hardcode credentials into your source:
echo "OPENAI_API_KEY=sk-your-key-here" > .env
Writing the Agent Core Loop
This is the heart of the system: a loop that sends the current state to the model, checks whether it wants to call a tool, executes that tool if so, and feeds the result back in.
# agent.py
import os
import json
from dotenv import load_dotenv
from openai import OpenAI
load_dotenv()
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
def get_disk_usage():
import shutil
total, used, free = shutil.disk_usage("/")
return {
"total_gb": round(total / (2**30), 2),
"used_gb": round(used / (2**30), 2),
"free_gb": round(free / (2**30), 2),
}
TOOLS = [
{
"type": "function",
"function": {
"name": "get_disk_usage",
"description": "Return current disk usage stats for the root filesystem.",
"parameters": {"type": "object", "properties": {}},
},
}
]
AVAILABLE_FUNCTIONS = {"get_disk_usage": get_disk_usage}
def run_agent(user_goal, max_iterations=5):
messages = [
{"role": "system", "content": "You are an infrastructure monitoring agent. Use tools when needed."},
{"role": "user", "content": user_goal},
]
for _ in range(max_iterations):
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=messages,
tools=TOOLS,
)
msg = response.choices[0].message
if msg.tool_calls:
messages.append(msg)
for call in msg.tool_calls:
fn = AVAILABLE_FUNCTIONS[call.function.name]
result = fn()
messages.append({
"role": "tool",
"tool_call_id": call.id,
"content": json.dumps(result),
})
continue
return msg.content
return "Max iterations reached without a final answer."
if __name__ == "__main__":
result = run_agent("Check disk usage and tell me if we're at risk of running out of space.")
print(result)
Run it:
python agent.py
The model will call get_disk_usage, receive real data from your machine, and respond with an actual assessment — not a hallucinated guess. This tool-calling pattern is the foundation every serious agent framework (LangChain, LangGraph, CrewAI) builds on top of.
Adding More Tools
Once the loop works, expanding capability is just a matter of adding functions and registering them:
Each tool should do one narrow thing and return structured data — resist the temptation to have a single “do everything” tool, since the model reasons much better with clearly scoped functions.
Dockerizing the Agent
Once the core loop works, package it so it runs the same way everywhere. Here’s a minimal production Dockerfile:
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY agent.py .
ENV PYTHONUNBUFFERED=1
CMD ["python", "agent.py"]
Build and run it:
docker build -t ai-agent:latest .
docker run --rm --env-file .env ai-agent:latest
For anything beyond a one-off script, mount a volume for logs and pass secrets via environment variables rather than baking them into the image. If you’re new to container networking and volumes, our Docker networking deep dive covers the patterns you’ll need before going further.
Deploying the Agent to a VPS
Once containerized, deployment is straightforward. SSH into your server, pull the image (or build it there), and run it as a systemd-managed service or via docker run --restart unless-stopped for simplicity:
ssh user@your-vps-ip
docker pull yourregistry/ai-agent:latest
docker run -d
--name ai-agent
--restart unless-stopped
--env-file /opt/ai-agent/.env
yourregistry/ai-agent:latest
For anything running continuously (rather than a one-shot script), wrap the loop in a scheduler or a long-running process that sleeps between iterations, and make sure docker logs ai-agent gives you enough context to debug failures without SSHing in and guessing.
Monitoring and Logging
An agent that silently fails is worse than no agent at all — you need visibility into what it’s doing and why. At minimum:
For production deployments, a dedicated uptime and log monitoring service pays for itself the first time your agent silently stops working at 3 a.m. BetterStack is worth evaluating here — their log aggregation and uptime monitoring integrate cleanly with containerized services and will page you before your users notice something’s wrong.
Security Considerations
Giving an LLM the ability to execute code or call APIs is powerful and dangerous in equal measure. Follow these rules:
Treat every tool the agent can call as a potential attack surface, the same way you’d treat a user-facing API endpoint.
Scaling Beyond a Single Agent
Once your first agent works reliably, the natural next step is running several agents for different tasks — one for log triage, one for cost reporting, one for deployment verification. At this point:
Running multiple containers reliably means your underlying infrastructure needs to keep up. If you’re outgrowing a single small droplet, DigitalOcean‘s managed Kubernetes or larger droplet tiers are a straightforward upgrade path without re-architecting everything from scratch.
Recommended: Want to explore DigitalOcean yourself? DigitalOcean is a direct vendor link (not an affiliate/tracked link).
FAQ
Do I need LangChain or CrewAI to build an AI agent?
No. Those frameworks are useful once you have many tools and complex branching logic, but you can build a fully functional agent with plain Python and the OpenAI or Anthropic SDK, as shown above. Frameworks add convenience, not capability.
Which LLM should I use for an agent?
For tool-calling reliability, GPT-4o-mini, GPT-4o, and Claude models all support structured function calling well. Start with a cheaper model for development and upgrade only if you see reasoning failures in production.
Can I run an AI agent without paying for API access?
Yes — tools like Ollama let you run open models locally, though tool-calling support and reasoning quality vary by model. It’s a good option for prototyping or privacy-sensitive workloads.
How do I stop an agent from looping forever?
Always set a max_iterations cap in your control loop, as shown in the example above. Never let an agent run in an unbounded while loop in production.
Is it safe to let an agent execute shell commands?
Only with strict guardrails — an explicit allowlist of commands, no direct shell interpolation of model output, and execution inside an isolated container with minimal permissions.
How is an AI agent different from a cron job with an API call?
A cron job runs a fixed set of steps. An agent decides its own steps based on what it observes, and can adapt its plan mid-execution — that’s the core distinction.
Wrapping Up
Building an AI agent isn’t magic — it’s a control loop, a handful of well-scoped tools, and disciplined engineering around logging, security, and deployment. Start small: one tool, one clear goal, a hard iteration cap. Containerize it, deploy it to a real server, and monitor it like you would any other production service. Once that foundation is solid, adding more tools and more agents is incremental work, not a redesign.
If you’re setting this up on your own infrastructure, revisit our Docker basics guide and Docker networking deep dive to make sure your container setup is production-ready before you put an agent in charge of anything that matters.
Leave a Reply