Building Your First Loop
Theory is useful. A running agent is better. Let's build one end to end.
Goal
Build, run, and inspect a complete autonomous agent loop that accomplishes a real file organization task
What You'll Need
⏱ Time: 45 minutes | 📋 Tasks:
- Docker Desktop installed and running
- Python 3.10+ installed
- A terminal and a text editor
- An OpenRouter API key (free tier works for this — about $0.05 per run)
- All five patterns from Lesson 8 memorized
The Five Layers
Every autonomous agent loop has five layers. We'll build each one in order:
- Sandbox — Where does the agent run? A Docker container with restricted access.
- Harness — What runtime controls the loop? Hermes, in our case.
- Model — What drives the decisions? DeepSeek V4 Flash Max through OpenRouter.
- Tools — What can the agent do? Read, write, list, and organize files.
- Monitoring — How do we watch it? Console logging and a timestamped log file.
Each layer is a decision we make. The decisions build on each other — the sandbox determines what tools are safe, the harness determines what models we can use, the model determines the cost structure, and the monitoring determines whether we can debug failures. Let's work through them one at a time.
Step 1: Choose a Task
We need something real but contained. Something that exercises the loop without risking the things we care about. The classic first task: a file organizer.
Task: Organize a messy download folder. Take a directory of mixed files — PDFs, images, documents, spreadsheets, archives — and sort them into subdirectories by type. Create the subdirectories if they don't exist. Move (don't copy) each file into the matching folder.
Why this task? It's concrete — success is easy to verify (check that files moved). It's safe — we can test on a throwaway directory. It exercises the core loop actions: list files, classify each one, create directories, move files. And it produces an obvious log trail we can inspect afterward.
Create a test directory with a dozen mixed files for the agent to organize:
mkdir agent-test-files cd agent-test-files echo "report content" > q1-report.pdf echo "image data" > photo.jpg echo "image data" > screenshot.png echo "budget" > expenses.xlsx echo "meeting notes" > notes.docx echo "archive" > old-projects.zip echo "presentation" > slides.pptx echo "invoice" > invoice-q2.pdf echo "spreadsheet" > data.csv echo "image data" > banner.gif echo "backup" > backup.zip echo "document" > contract.docx
We now have 12 files of various types in a directory. This is what the agent will organize.
Step 2: Set Up the Sandbox
The agent will have file system access — it will create directories and move files. That's destructive. We sandbox it so it can't touch anything outside the test directory.
Create a Docker container with the test directory mounted read-write and everything else read-only:
docker run -d --name agent-sandbox `
-v ${PWD}/agent-test-files:/workspace/data:rw `
-v ${PWD}/agent-output:/workspace/output:rw `
-w /workspace/data `
python:3.11-slim sleep infinityThis container has no network access (add --network none for extra isolation), can only write to the data and output directories, and everything else in the file system is read-only. If the agent tries to delete system files or write to unexpected locations, it simply fails — no harm done.
We'll install the agent harness inside this container on the next step.
Step 3: Install and Configure Hermes
Hermes is our harness of choice for this build: it's lightweight, supports cost caps natively, and runs inside a container without fuss.
Install Hermes inside the container:
docker exec agent-sandbox pip install hermes-agent
Set up the config:
docker exec agent-sandbox mkdir -p /workspace/config
# Write the config file
docker exec -i agent-sandbox tee /workspace/config/hermes.yaml > $null
@"
model:
provider: openrouter
name: deepseek/deepseek-chat
temperature: 0.3
max_tokens: 4000
workspace:
path: /workspace
allowed_tools:
- bash
- read_file
- write_file
- list_directory
"@We chose DeepSeek V4 Flash Max through OpenRouter because it's cheap (~$0.002 per call), fast, and good enough for file organization. Temperature 0.3 keeps decisions deterministic — we want reliable classification, not creative file naming. The model runs inside the container, the container has no internet access beyond the OpenRouter API, and the workspace is constrained to /workspace.
Step 4: Define the Tools
Hermes comes with built-in tools for file operations. We don't need to write custom tool code for this task — the existing bash tool combined with shell commands is sufficient.
But we do need to control which tools are available. The task needs:
# Define allowed tools in the goal file
tools:
- name: list_directory
description: "List all files in a directory"
command: "ls -la {path}"
- name: read_file
description: "Read contents of a file"
command: "cat {path}"
- name: run_shell
description: "Execute a shell command"
command: "{command}"
- name: move_file
description: "Move a file from source to destination"
command: "mv {source} {destination}"
- name: create_directory
description: "Create a directory if it doesn't exist"
command: "mkdir -p {path}"Important constraint: we do not give the agent rm or delete access. If the agent tries to clean up by deleting files, it will fail — and that's intentional. The agent should move files, not delete them. If it needs to handle duplicates, it should move them to a duplicates/ subfolder instead.
Step 5: Write the Goal
The goal is the most important part. This is where all the patterns from Lesson 8 come together. A well-formed goal has: the task, concrete stopping criteria, constraints, and escalation rules.
# goal.yaml
goal:
description: >
Organize the files in /workspace/data into subdirectories
by file type. Create a directory for each type if it doesn't
exist. Move each file into the appropriate directory.
success_criteria:
- "Every file in /workspace/data has been moved to a subdirectory"
- "Subdirectories exist named: pdfs, images, documents,
spreadsheets, archives"
- "No files remain in /workspace/data root"
- "No files were deleted — only moved"
constraints:
- "Do not use rm, delete, or remove commands"
- "If a file extension doesn't match any category, move it to 'other/'"
- "Create the named subdirectories before moving files"
- "List the final directory structure when complete"
file_types:
pdf: [".pdf"]
images: [".jpg", ".jpeg", ".png", ".gif", ".bmp", ".svg"]
documents: [".doc", ".docx", ".txt", ".md", ".rtf"]
spreadsheets: [".xls", ".xlsx", ".csv"]
archives: [".zip", ".tar", ".gz", ".rar"]
escalation:
on_error: "Log the error, skip the file, continue"
on_ambiguous_extension: "Move to 'other/' and log the choice"We wrote the success criteria as concrete, testable statements — not "organize the files" but "no files remain in the root directory" and "subdirectories exist with these names." The agent can check its own work against these criteria and know when it's done.
Step 6: Set Budget and Limits
Before running, we apply the remaining reliability patterns: timeouts, cost budget, and logging.
limits:
max_iterations: 20
max_cost: 0.50
max_time_per_step: 60
max_total_time: 600
logging:
level: verbose
output: /workspace/output/agent-run-{timestamp}.logThe $0.50 cap is generous for this task — it should cost about $0.05. But the cap gives us confidence that even if the agent goes sideways, the damage is limited. If it hits the cap, we inspect the log, fix the goal, and re-run with a lesson learned.
Step 7: Run It
Copy the goal file into the container and start Hermes:
# Copy the goal file into the container docker cp goal.yaml agent-sandbox:/workspace/config/goal.yaml # Run Hermes with the goal docker exec -e OPENROUTER_API_KEY=$env:OPENROUTER_API_KEY ` agent-sandbox hermes run /workspace/config/goal.yaml ` --config /workspace/config/hermes.yaml ` --log-file /workspace/output/agent-run.log
Watch the output as it runs. Hermes prints each step as it executes:
[STEP 1/12] list_directory /workspace/data Found 12 files [STEP 2/12] create_directory /workspace/data/pdfs Directory created [STEP 3/12] create_directory /workspace/data/images Directory created [STEP 4/12] create_directory /workspace/data/documents Directory created ... (continues through all categories) [STEP 8/12] move_file /workspace/data/q1-report.pdf /workspace/data/pdfs/ File moved [STEP 9/12] move_file /workspace/data/invoice-q2.pdf /workspace/data/pdfs/ File moved ... [STEP 12/12] list_directory /workspace/data Subdirectories: pdfs/, images/, documents/, spreadsheets/, archives/ — root is empty. All files organized. [DONE] Goal achieved. Total cost: $0.034. Iterations: 12.
The agent finished in 12 iterations and spent 3.4 cents. All 12 files were sorted into the correct subdirectories. The log captured every action, every tool call, and the final directory listing as proof.
Step 8: Review the Log
Read the log file to verify everything happened as expected:
# Copy the log out of the container docker cp agent-sandbox:/workspace/output/agent-run.log . # View the log cat agent-run.log
What we're looking for in the log:
- Every tool call is recorded — with arguments, return values, and duration
- The decision process is visible — why the agent chose to create directories before moving files, why it classified each file into its category
- No unexpected tool calls — the agent didn't try to delete files or access anything outside
/workspace/data - The total cost is reported — and it matches the estimated ~$0.05 range
If the log reveals errors — files classified wrong, directories created in the wrong location, a step that timed out — that's not a failure. That's data. The log tells us exactly what went wrong, and we can fix the goal or constraints and re-run. This is the scientific method applied to agent building: hypothesize, run, inspect, adjust.
Compare: First Loop vs. the Ideal Pattern
Now compare what we built against the five-pattern reliability checklist from Lesson 8:
| Pattern | Our Loop | Production Ideal |
|---|---|---|
| Human-in-the-loop | Not implemented — the agent runs fully autonomously | Add a checkpoint before the first file move — "show me the classification plan and wait for approval" |
| Logging | Full verbose logging to file | Add structured JSON logging for automated analysis |
| Timeouts | Per-step and per-loop timeouts configured | Same — already production-ready |
| Cost budget | $0.50 hard cap configured | Same — already production-ready |
| Escalation path | Error logging + skip configured | Add retry logic and a dead-letter queue for consistently failing files |
We got four out of five patterns right on the first build. The missing one — human-in-the-loop — is the hardest to add in Hermes because the harness doesn't natively support pause-and-resume. For a file organizer, full autonomy is acceptable (files can be restored from backup). For higher-stakes tasks, we'd switch to Openclaw Fleet for its built-in approval gate support.
Deliverable: Proof of Completion
When the agent finishes, we have three artifacts to show it worked:
- The organized directory —
agent-test-files/now has subdirectories with files sorted by type. Runls -R agent-test-files/to see the structure. - The log file —
agent-run.logshows every step the agent took, every tool call, and every decision. This is the audit trail. - The cost receipt — the final output shows total cost ($0.034 in our case). This is the first data point for estimating future runs.
These three artifacts — organized files, log, and cost — are the minimum deliverable for any autonomous agent task. If you can produce these three things, you have a loop that works, verified by evidence, and priced so you know what to expect next time.
Try It
Run the build yourself. Follow steps 1 through 8. Use the exact goal file and config shown above. When it works, try these variations:
- Add a checkpoint. Modify the goal to: "List all files, present the classification plan, then wait for user input 'proceed' before moving anything." Simulate the checkpoint by running with
--interactive. - Introduce an ambiguous file. Add a file with no extension to the test directory. Does the agent handle it (move to
other/as instructed) or does it stumble? - Set the budget to $0.05 — intentionally too low. Watch what happens when the agent hits the cost cap mid-task. Inspect the partial work. Learn the failure mode in a safe environment.
The goal isn't just to get it working once. It's to understand every failure mode so that when you build a loop for something that matters, you already know what can go wrong and how to prevent it.
Next lesson: When NOT to Use an Autonomous Agent — the most important lesson is knowing when not to use one.