跳转到主内容
Logo

Building a Minimal Agent from Scratch: Seeing the Complete Skeleton of an Agent

Published on
...
Authors

Starting from an empty folder, I'll hand-write a minimal agent to reveal the core structure behind tool calling, identity prompts, and user profiles, then compare where OpenClaw, Hermes, Claude Code, and Codex derive their complexity.

Building a Minimal Agent from Scratch: Seeing the Complete Skeleton of an Agent

This note documents my process of hand-writing a minimal agent starting from an empty folder. The goal is not to dive into complex frameworks right away, but to first clearly see the core structure of an agent: how the model sees tools, how it decides to call them, how the program executes them, and how the results are fed back to the model to generate the final answer.

At the end, I'll also compare this small agent with more complex systems like OpenClaw, Hermes, Claude Code, and Codex to help understand where their complexity actually comes from.

1. Starting from an Empty Folder

My practice directory is:

/Users/huashan/Agent-development

At the start, I only need a few files:

Agent-development/
├── agent.py
├── requirements.txt
├── README.md
├── prompts/
│   └── identity.md
├── memory/
│   └── user_profile.md
└── docs/
    └── agent-learning-note.md

requirements.txt contains just one dependency:

anthropic

Because this time I've chosen to follow the Anthropic-style tool-use approach, while using MiniMax's Anthropic-compatible API to run the model.

Inline illustration 2B

8. .env: Putting the API Key Locally

Initially, every run required:

export MINIMAX_API_KEY="..."

Later I added a very small .env loader. Now I can put this at the project root:

MINIMAX_API_KEY=your_key_here

The .env file is added to .gitignore and won't be committed to Git. agent.py reads it at startup, but if a variable with the same name is already exported in the shell, the shell value takes precedence. The minimal implementation:

from pathlib import Path
import os

def load_dotenv(path: str = ".env") -> None:
    if not Path(path).exists():
        return
    for line in Path(path).read_text().splitlines():
        line = line.strip()
        if not line or line.startswith("#") or "=" not in line:
            continue
        k, v = line.split("=", 1)
        os.environ.setdefault(k.strip(), v.strip())  # setdefault: shell takes priority

load_dotenv()
api_key = os.environ["MINIMAX_API_KEY"]
Inline illustration 3B

The key is setdefault—existing environment variables won't be overwritten by .env, so any value temporarily exported in the shell always wins, and the local file only serves as a fallback.

9. The Relationship Between Small Agents and Complex Agents

This agent can now be summarized as:

identity + user_profile + tools + loop

This is already the minimal skeleton of an agent. OpenClaw, Hermes, Claude Code, and Codex may look far more complex, but at their core they still rely on this same structure.

The difference is mainly that complex systems stack more layers on top of this skeleton:

more entry points
more memory
more tools
more identities
more permission controls
stronger runtime engineering
more complex task scheduling

10. Where OpenClaw and Hermes Get Complex

OpenClaw / Hermes are more like long-running personal AI systems, rather than one-off command-line agents.

Their complexity lies in:

  • More entry points: Discord, Telegram, voice, cron, webhooks, scheduled tasks.
  • More memory: long-term memory, daily memory, conversation history, vector retrieval, shared memory across agents.
  • More tools: notifications, calendar, email, files, search, MCP, databases, transactions, voice.
  • More agents: main agent, life agent, English agent, trading agent, research agent.
  • Heavier runtime: persistent services, logging, monitoring, restarts, permissions, secrets, failure alerts.

If my small project is:

a one-off command-line agent

then OpenClaw / Hermes are more like:

a long-running personal AI operating system

But they still depend on the same loop:

model sees context and tool schema
-> decides to call a tool
-> program executes the tool
-> tool results go back to the model
-> model continues deciding or produces a final answer

11. Do Claude Code and Codex Count as Agents

Claude Code and Codex are certainly agents too—and coding agents at that.

They aren't life assistants, but software engineering agents that live specifically inside code repositories.

A typical life agent's loop is:

user question -> decide on tool -> call tool -> answer

A coding agent's loop is:

read code -> search files -> understand requirements -> modify code -> run tests -> check errors -> modify again -> summarize results

The essence is still:

the model handles decisions
tools handle execution
the loop handles closing the cycle

It's just that the tools are swapped for software engineering tools:

read_file / search_code / apply_patch / run_command / run_tests / git_diff / inspect_logs

Claude Code and Codex are complex because they need to understand real code repositories, respect engineering constraints, handle Git state, run tests, avoid breaking users' uncommitted changes, and keep debugging when things fail.

12. A Comparison Table

SystemTypeCore CapabilitySource of Complexity
This article's small agentLearning command-line agenttool-use loop, weather tool, identity, user profileSimple, single-process, no long-running
OpenClaw / HermesPersonal AI runtime / multi-agent systemMultiple entry points, multi-agent, cron, memory, tool ecosystemSessions, permissions, plugins, runtime stability
Claude CodeCoding agentRead/write code, execute commands, fix bugs, run testsCode understanding, repository context, engineering safety
CodexCoding agentCode modification, debugging, review, test loopTool permissions, context management, collaboration protocol

13. How I Now Understand Agents

After this exercise, I think agents can be understood this way:

Agent = LLM + context + tools + loop + state

Where:

identity -> prompt
understanding of the user -> user_profile / memory
external capabilities -> tools
task-specific instructions -> skills
external tool ecosystem -> MCP
long-running capability -> runtime
collaboration among roles -> multi-agent

So learning agents doesn't necessarily mean jumping straight into complex frameworks. A better path is:

first write a minimal loop
then add a real tool
then add identity
then add a user profile
then add memory
then add skills
finally connect MCP and multi-agent

This way, each layer of complexity becomes visible, and you won't be overwhelmed by frameworks all at once.

References