Autonomous AI Agent Tutorial: Build a Self-Running Agent That Works While You Sleep

TutorialsBy Ivern AI Team13 min read

Autonomous AI Agent Tutorial: Build a Self-Running Agent That Works While You Sleep

An autonomous AI agent doesn't wait for your instructions between steps. You give it a goal, and it plans the approach, executes each step, evaluates its own output, and iterates until the job is done.

This tutorial shows you how to build one. You'll learn the agent loop pattern, how to implement goal decomposition, self-correction mechanisms, and how to deploy agents that run reliably without supervision.

In this tutorial:

Related tutorials: Build AI Agent From Scratch · AI Agent Python Tutorial · Multi-Agent System Tutorial

What Makes an Agent Autonomous

A chatbot responds. An autonomous agent acts. Here's the difference:

Scroll to see full table

CapabilityChatbotAutonomous Agent
Needs human prompts for each stepYesNo
Breaks goals into subtasksNoYes
Uses tools without askingNoYes
Self-corrects errorsNoYes
Runs on a scheduleNoYes
Produces finished deliverablesNoYes

The key distinction is the agent loop -- a cycle of Plan → Execute → Evaluate → Iterate that runs without human intervention.

For more on agentic AI fundamentals, see our What Is Agentic AI guide.

The Autonomous Agent Loop

Every autonomous agent follows this pattern:

┌─────────┐     ┌─────────┐     ┌──────────┐     ┌───────────┐
│  PLAN    │────▶│ EXECUTE  │────▶│ EVALUATE │────▶│ ITERATE   │
│ Break    │     │ Run each │     │ Check    │     │ Fix issues│
│ goal     │     │ subtask  │     │ quality  │     │ Refine    │
└─────────┘     └─────────┘     └──────────┘     └───────────┘
      ▲                                                 │
      └─────────────────────────────────────────────────┘
                    (if quality < threshold)

Here's the implementation:

import json
from openai import OpenAI

client = OpenAI()

class AutonomousAgent:
    def __init__(self, goal: str, max_iterations: int = 5):
        self.goal = goal
        self.max_iterations = max_iterations
        self.context = []
        self.tools = self._define_tools()

    def plan(self) -> list[dict]:
        response = client.chat.completions.create(
            model="gpt-4o",
            messages=[
                {"role": "system", "content": "You are a task planner. Break the goal into specific, ordered subtasks. Return JSON array of {step, task, tool}."},
                {"role": "user", "content": f"Goal: {self.goal}"}
            ],
            response_format={"type": "json_object"}
        )
        plan = json.loads(response.choices[0].message.content)
        return plan.get("steps", [])

    def execute_step(self, step: dict) -> str:
        response = client.chat.completions.create(
            model="gpt-4o",
            messages=self.context + [
                {"role": "user", "content": f"Execute this step: {step['task']} using {step.get('tool', 'reasoning')}"}
            ]
        )
        result = response.choices[0].message.content
        self.context.append({"role": "assistant", "content": result})
        return result

    def evaluate(self, results: list[str]) -> dict:
        response = client.chat.completions.create(
            model="gpt-4o",
            messages=[
                {"role": "system", "content": "Evaluate the results against the goal. Return JSON: {quality_score: 0-10, issues: [], passed: bool}"},
                {"role": "user", "content": f"Goal: {self.goal}\n\nResults: {json.dumps(results)}"}
            ],
            response_format={"type": "json_object"}
        )
        return json.loads(response.choices[0].message.content)

    def run(self) -> str:
        for iteration in range(self.max_iterations):
            print(f"--- Iteration {iteration + 1} ---")

            # Plan
            steps = self.plan()
            print(f"Planned {len(steps)} steps")

            # Execute
            results = []
            for step in steps:
                result = self.execute_step(step)
                results.append(result)
                print(f"  Step: {step['task']} -> Done")

            # Evaluate
            evaluation = self.evaluate(results)
            print(f"Quality score: {evaluation['quality_score']}/10")

            if evaluation.get("passed", False):
                print("Goal achieved!")
                return "\n".join(results)

            print(f"Issues found: {evaluation.get('issues', [])}")
            self.context.append({
                "role": "user",
                "content": f"The previous attempt had issues: {evaluation.get('issues', [])}. Please fix and retry."
            })

        return "\n".join(results)

Building the Agent Core

Running Your First Autonomous Task

agent = AutonomousAgent(
    goal="Write a 500-word blog post about AI agents for small businesses, including 3 real examples with specific numbers",
    max_iterations=3
)

Get AI agent tips in your inbox

Multi-agent workflows, BYOK tips, and product updates. No spam.

result = agent.run() print(result)


The agent will:
1. Plan the article structure (introduction, 3 examples, conclusion)
2. Write each section
3. Evaluate word count, examples, and quality
4. Iterate if it falls short

### Adding Real Tools

The agent above uses reasoning only. Let's add web search:

```python
def search_web(query: str) -> str:
    import requests
    response = requests.get(
        "https://api.tavily.com/search",
        params={"query": query, "api_key": "your-tavily-key"}
    )
    results = response.json().get("results", [])
    return "\n".join([f"- {r['title']}: {r['content']}" for r in results[:3]])

Update the execute_step method to call real tools:

def execute_step(self, step: dict) -> str:
    tool = step.get("tool", "reasoning")
    
    if tool == "web_search":
        search_results = search_web(step["task"])
        self.context.append({"role": "user", "content": f"Search results: {search_results}"})
    
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=self.context + [
            {"role": "user", "content": f"Execute: {step['task']}"}
        ]
    )
    result = response.choices[0].message.content
    self.context.append({"role": "assistant", "content": result})
    return result

Adding Self-Correction

The evaluation loop is what makes an agent truly autonomous. Here are three patterns:

Pattern 1: Quality Gate

def quality_gate(output: str, criteria: list[str]) -> dict:
    prompt = f"""Evaluate this output against these criteria:
    {json.dumps(criteria)}
    
    Output: {output}
    
    Return JSON: {{"passed": bool, "score": 0-10, "fix_instructions": str}}"""
    
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": prompt}],
        response_format={"type": "json_object"}
    )
    return json.loads(response.choices[0].message.content)

Pattern 2: Output Validation

def validate_output(output: str, constraints: dict) -> bool:
    if "min_words" in constraints:
        word_count = len(output.split())
        if word_count < constraints["min_words"]:
            return False
    if "must_include" in constraints:
        for term in constraints["must_include"]:
            if term.lower() not in output.lower():
                return False
    return True

Pattern 3: Retry with Context

def retry_with_context(agent, failed_output: str, issues: list[str]) -> str:
    agent.context.append({
        "role": "user",
        "content": f"The previous output had these problems: {issues}. Fix them."
    })
    return agent.execute_step({"task": "Fix the issues", "tool": "reasoning"})

Running Agents on a Schedule

Autonomous agents shine when they run without any human trigger.

Cron-Based Agent with Python

import schedule
import time

def daily_competitor_report():
    agent = AutonomousAgent(
        goal="Analyze the top 3 competitors in the AI agent space and produce a brief report with pricing, features, and recent changes",
        max_iterations=3
    )
    report = agent.run()
    
    with open(f"reports/competitor-{time.strftime('%Y-%m-%d')}.md", "w") as f:
        f.write(report)

schedule.every().day.at("08:00").do(daily_competitor_report)

while True:
    schedule.run_pending()
    time.sleep(60)

Using Celery Beat for Production

from celery import Celery
from celery.schedules import crontab

app = Celery('agents', broker='redis://localhost:6379')

@app.task
def weekly_market_research():
    agent = AutonomousAgent(
        goal="Research this week's top AI agent news and summarize the 5 most important developments",
        max_iterations=2
    )
    return agent.run()

app.conf.beat_schedule = {
    'weekly-research': {
        'task': 'agents.weekly_market_research',
        'schedule': crontab(hour=9, minute=0, day_of_week=1),
    },
}

Monitoring Autonomous Agents

When agents run without supervision, you need monitoring to catch problems.

Logging Agent Actions

import logging

logging.basicConfig(
    filename='agent.log',
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s'
)

class MonitoredAgent(AutonomousAgent):
    def execute_step(self, step: dict) -> str:
        logging.info(f"Executing: {step['task']}")
        try:
            result = super().execute_step(step)
            logging.info(f"Completed: {step['task']} ({len(result)} chars)")
            return result
        except Exception as e:
            logging.error(f"Failed: {step['task']} - {str(e)}")
            raise

Setting Up Alerts

def alert_on_failure(agent_name: str, error: str):
    import requests
    requests.post("https://hooks.slack.com/services/YOUR/WEBHOOK", json={
        "text": f"Agent '{agent_name}' failed: {error}"
    })

For production monitoring best practices, see our AI Agent Monitoring Guide.

No-Code Autonomous Agents

Building autonomous agents in Python is powerful but time-consuming. Ivern AI provides autonomous agent squads out of the box:

  • Set a goal, agents execute -- describe what you want, the squad handles planning and execution
  • Self-correcting workflows -- agents review each other's output and iterate
  • Scheduled runs -- set agents to run daily or weekly without manual triggers
  • Bring Your Own Key -- use your existing API keys with zero markup
  • Monitoring dashboard -- see every agent action in real-time

Try it free: Create an account and set up your first autonomous squad in under 5 minutes.

Key Takeaways

  1. The agent loop (Plan → Execute → Evaluate → Iterate) is the core pattern for autonomy
  2. Self-correction through evaluation gates prevents garbage output
  3. Scheduling transforms one-off tasks into reliable automations
  4. Monitoring is essential -- autonomous agents need supervision even if they don't need step-by-step input
  5. Start simple -- get a basic loop working before adding tools and complexity

Next tutorials: AI Agent Collaboration · AI Agent RAG Tutorial · AI Agent Security Best Practices

Want to try multi-agent AI for free?

Generate a blog post, Twitter thread, LinkedIn post, and newsletter from one prompt. No signup required.

Try the Free Demo

AI Content Factory -- Free to Start

One prompt generates blog posts, social media, and emails. Free tier, BYOK, zero markup.

No spam. Unsubscribe anytime.