Cybersecurity

More Than a Chatbot

Python Docker LLMs MCP AI Agents Git Hashing
1,757 words Includes Code
🎯 Key Takeaway: AI coding agents are not just chatbots with file access. They operate through a continuous loop: LLM plans β†’ selects tool β†’ executes β†’ observes result β†’ decides next action. Understanding this loop is essential for using them effectively and safely.
AI Coding Agent architecture showing LLM planning, tool selection, execution, and observation loop
The core components of an AI coding agent: LLM, tools, context, and execution loop.

More Than a Chatbot

Most developers' first interaction with AI is a chatbotβ€”ask a question, get an answer. Then came coding assistantsβ€”inline suggestions, code completion, quick edits. Now we have coding agentsβ€”autonomous systems that can plan, execute, observe, and iterate.

The difference is not cosmetic. A chatbot responds to messages. A coding agent takes actions in the real world: reading files, running commands, executing tests, and making changes to your codebase.

Chatbot vs Coding Assistant vs Coding Agent

Comparison of Chatbot, Coding Assistant, and Coding Agent capabilities
Three levels of AI coding capability: from passive conversation to autonomous execution.
Feature πŸ’¬ Chatbot ✏️ Coding Assistant πŸ€– Coding Agent
Text generation βœ… βœ… βœ…
Code completion ❌ βœ… βœ…
File access ❌ ⚠️ Read-only βœ… Read/Write
Terminal execution ❌ ⚠️ Limited βœ… Full
Git operations ❌ ❌ βœ… Full
Autonomous loops ❌ ❌ βœ…
Multi-step plans ❌ ❌ βœ…
Test execution ❌ ❌ βœ…
Autonomy level Low Medium High

The Agent Loop: How It Actually Works

Every AI coding agent, regardless of platform, follows the same fundamental loop:

AI coding agent execution loop showing User Request, LLM Planning, Tool Selection, Execution, Observation, and Loop
The agent loop: plan, act, observe, repeat until complete.
User Request: "Fix the failing tests"
        ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              AGENT LOOP                 β”‚
β”‚                                         β”‚
β”‚  1. LLM Plans                           β”‚
β”‚     β”œβ”€β”€ Analyze request                 β”‚
β”‚     β”œβ”€β”€ Consider context                β”‚
β”‚     └── Decide first action             β”‚
β”‚                                         β”‚
β”‚  2. Select Tool                         β”‚
β”‚     β”œβ”€β”€ Read test file                  β”‚
β”‚     β”œβ”€β”€ Run pytest                      β”‚
β”‚     └── Search for error                β”‚
β”‚                                         β”‚
β”‚  3. Execute Tool                        β”‚
β”‚     └── Tool runs in environment        β”‚
β”‚                                         β”‚
β”‚  4. Observe Result                      β”‚
β”‚     β”œβ”€β”€ Tool output                     β”‚
β”‚     β”œβ”€β”€ Error messages                  β”‚
β”‚     └── File changes                    β”‚
β”‚                                         β”‚
β”‚  5. Decide Next Action                  β”‚
β”‚     β”œβ”€β”€ More work needed? β†’ Loop        β”‚
β”‚     └── Task complete? β†’ Done           β”‚
β”‚                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        ↓
   Final Output: Code changes + explanation

The Five Components

1. The LLM (Planner)

The Large Language Model is the brain of the agent. It receives the user's request, considers the available context, and decides what to do next. But unlike a chatbot, it doesn't just generate textβ€”it generates actions.

The LLM answers questions like:

  • What does the user want?
  • What information do I need?
  • Which tool should I use?
  • What parameters should I pass?
  • Did the action succeed?
  • What should I do next?

2. Tools (Capabilities)

Tools are the agent's hands. Without tools, an LLM can only talk. With tools, it can act:

Tool Capability Risk Level
File Read Read source code, configs, docs 🟒 Low
File Write Create or modify files 🟑 Medium
Terminal Run commands, install packages 🟠 High
Search Find code patterns, files 🟒 Low
Git Commit, branch, diff 🟑 Medium
Test Runner Execute test suites 🟒 Low
Web Search Look up documentation 🟒 Low
MCP Tools External tool integration 🟑 Medium

3. Context (Information)

Context is everything the agent knows before it starts working:

  • System instructions β€” Rules from AGENTS.md or CLAUDE.md
  • Project files β€” Source code, configs, documentation
  • Conversation history β€” Previous messages in the session
  • Tool outputs β€” Results from previous tool calls
  • State β€” Current Git status, test results

The quality of context directly affects the quality of the agent's decisions. This is why context engineering is so important.

4. State (Memory)

State tracks what has happened during the current session:

  • Which files have been read
  • Which tools have been called
  • What results were returned
  • What changes have been made
  • What errors occurred

Without state, the agent would repeat actions or lose track of progress.

5. Planning (Reasoning)

Planning is how the agent decides what to do next. The LLM considers:

  • The user's original request
  • What has been done so far
  • What information is still missing
  • Which tool is most appropriate
  • What the expected outcome should be

A Simple Python Agent Loop

Here's a minimal demonstration of how an agent loop works. This uses mock tools for safety:

"""Minimal AI Agent Loop Demo β€” Safe mock tools only."""

import json
from typing import Callable

# ── Mock Tools (safe, no real execution) ──────────────────

def read_file(path: str) -> str:
    """Mock: reads a file and returns contents."""
    mock_files = {
        "main.py": "def add(a, b):\n    return a + b",
        "test_main.py": "from main import add\n\ndef test_add():\n    assert add(1, 2) == 3",
    }
    return mock_files.get(path, f"Error: {path} not found")


def write_file(path: str, content: str) -> str:
    """Mock: writes content to a file."""
    return f"Written {len(content)} chars to {path}"


def run_command(cmd: str) -> str:
    """Mock: runs a terminal command."""
    if "pytest" in cmd:
        return "1 passed in 0.02s"
    return f"Executed: {cmd}"


# ── Tool Registry ─────────────────────────────────────────

TOOLS: dict[str, Callable] = {
    "read_file": read_file,
    "write_file": write_file,
    "run_command": run_command,
}


# ── Agent Loop ────────────────────────────────────────────

def agent_loop(user_request: str, max_steps: int = 10) -> list[dict]:
    """
    Simulate an AI agent loop:
    1. Plan (mock LLM)
    2. Select tool
    3. Execute
    4. Observe
    5. Repeat or finish
    """
    history: list[dict] = []
    context: list[str] = []

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

        # Step 1: Plan (mock LLM decision)
        plan = mock_llm_plan(user_request, context, history)
        print(f"Plan: {plan['thought']}")

        if plan.get("done"):
            print("Agent: Task complete!")
            break

        # Step 2: Select tool
        tool_name = plan["tool"]
        tool_args = plan["args"]
        print(f"Tool: {tool_name}({tool_args})")

        # Step 3: Execute tool
        tool_fn = TOOLS[tool_name]
        result = tool_fn(**tool_args)
        print(f"Result: {result}")

        # Step 4: Observe and record
        observation = {
            "step": step + 1,
            "thought": plan["thought"],
            "tool": tool_name,
            "args": tool_args,
            "result": result,
        }
        history.append(observation)
        context.append(f"{tool_name}({tool_args}) β†’ {result}")

    return history


def mock_llm_plan(request: str, context: list, history: list) -> dict:
    """Mock LLM that follows a fixed plan for demonstration."""
    steps_done = [h["tool"] for h in history]

    if "read_file" not in steps_done:
        return {
            "thought": "I need to read the test file to understand the failure",
            "tool": "read_file",
            "args": {"path": "test_main.py"},
        }
    elif "run_command" not in steps_done:
        return {
            "thought": "Let me run the tests to see current status",
            "tool": "run_command",
            "args": {"cmd": "pytest test_main.py -v"},
        }
    else:
        return {
            "thought": "Tests pass. Task is complete.",
            "done": True,
        }


# ── Run Demo ──────────────────────────────────────────────

if __name__ == "__main__":
    print("=" * 50)
    print("AI Agent Loop Demo")
    print("=" * 50)

    result = agent_loop("Fix the failing tests")

    print("\n" + "=" * 50)
    print("Execution History:")
    print("=" * 50)
    for obs in result:
        print(f"  Step {obs['step']}: {obs['thought']}")
        print(f"         Tool: {obs['tool']} β†’ {obs['result'][:50]}")
πŸ’‘ Key Insight: This demo shows the fundamental pattern. Real agents use actual LLMs for planning and real tools for execution, but the loop structure is identical.

What Makes a "Real" Agent Different

The mock demo above uses a hardcoded plan. Real agents differ in critical ways:

Aspect Mock Agent Real Agent
Planning Fixed script LLM reasons about context
Tool selection Predetermined LLM chooses based on task
Error handling None LLM adapts strategy
Context Hardcoded files Real project files
Termination Fixed steps LLM decides when done

How Agents Use Git

Git is one of the most powerful tools in an agent's arsenal. Agents can:

  • Read history β€” Understand past changes and decisions
  • View diffs β€” See what changed and why
  • Create branches β€” Work in isolation
  • Commit changes β€” Save progress with meaningful messages
  • Run bisect β€” Find when a bug was introduced
  • Blame β€” Understand who wrote what and when

This is why agents are so effective at tasks like "fix the bug introduced in the last commit" or "refactor the module that was changed yesterday."

Context Window and Token Limits

Every agent operates within a context windowβ€”the maximum number of tokens the LLM can process. This creates a fundamental constraint:

  • Too little context β€” Agent doesn't understand the codebase
  • Too much context β€” Agent gets confused, loses important signals
  • Just right β€” Agent has exactly what it needs

This is why agents use context selectionβ€”strategically choosing which files and information to include. Smart agents read only the files relevant to the current task.

State Management Across Steps

As the agent works, it builds up state:

Step 1: Read test_main.py
  State: [test file contents]

Step 2: Read main.py
  State: [test file, source file]

Step 3: Run pytest
  State: [test file, source file, test results]

Step 4: Edit main.py
  State: [test file, source file, test results, edit applied]

Step 5: Run pytest again
  State: [test file, source file, test results, edit applied, tests pass]

Step 6: Done β€” all tests pass

Without proper state management, the agent would re-read files it already read, re-run tests it already ran, or lose track of changes it already made.

Safety and Permissions

Because agents can execute real commands and modify files, safety is critical:

Control Purpose Example
File restrictions Limit which files agent can access Only project directory, not ~/.ssh
Command approval Require confirmation for dangerous commands Ask before rm, git push
Sandboxing Run agent in isolated environment Docker container with limited access
Network restrictions Prevent unauthorized external access Allowlist outbound connections
Human review Review changes before committing Show git diff before commit
⚠️ Important: Never give an agent unrestricted access to your system. Always use least privilege: let the agent access only what it needs for the current task.

Try It Yourself

Run the Python demo above to see the agent loop in action:

# Save the code as agent_demo.py
python agent_demo.py

Then experiment:

  1. Add new mock tools (search, git status)
  2. Change the mock LLM plan to handle different requests
  3. Add error handling when a tool fails
  4. Add a max-retry limit to prevent infinite loops

Key Takeaways

  • AI coding agents operate through a continuous loop: plan β†’ select β†’ execute β†’ observe β†’ repeat
  • Tools give the agent real-world capabilities: files, terminal, Git, tests
  • Context determines what the agent knows; quality matters more than quantity
  • State tracks progress across multiple steps
  • Agents are different from chatbots (no tools) and assistants (no autonomous loops)
  • Safety requires least privilege, sandboxing, and human review
  • The fundamental loop is the same across all agent platforms

Further Reading

Related BestWordz Tools

  • πŸ› οΈ JSON Formatter β€” Format agent tool call outputs
  • πŸ› οΈ Regex Tester β€” Test patterns for parsing agent logs
  • πŸ› οΈ Hash Generator β€” Generate checksums for file integrity

πŸ’¬ Discuss this topic on BestWordz Community β€” Share your agent experiences, tips, and workflows.

Try the JSON Formatter

Put what you've learned into practice with this free BestWordz tool.

Open Tool β†’

πŸ’¬ Discuss on BestWordz Community

Join the conversation about Python, Docker, LLMs on the BestWordz Community forum.

Visit Forum β†’