Beginner-Friendly Guide

How an AI Agent Actually Works

You don't need to be a programmer to understand this. We'll start with plain English, build up to pseudocode, and then look at only the ~20 lines of real code that matter. By the end, you'll understand how NanoClaw works — and you'll realize you could build one yourself.

No programming experience required. Seriously.
1
2
3
4

Think of It Like a Company

Forget code for a moment. An AI agent is structured exactly like a small company with three departments. NanoClaw has just 3 important files — and each one maps to a department.

👨‍💼

The CEO

index.ts

Receives requests, decides what to do, delegates work, and delivers the final answer. Runs the whole show.

☎️

The Phone System

ipc-mcp.ts

Connects the CEO to the outside world. Need to send a message? Schedule a meeting? Make the call through here.

🗄️

The Filing Cabinet

db.ts

Stores every conversation, every decision, every piece of context. So the CEO remembers what happened yesterday.

CEO (Brain) + Phone (Tools) + Filing Cabinet (Memory) = AI Agent
🔍 Quick Check

If a customer sends a WhatsApp message and the agent needs to look up their order history before replying — which "departments" are involved?

All three! The CEO (index.ts) receives the message and decides to look up the order. The Filing Cabinet (db.ts) retrieves the conversation history. The Phone System (ipc-mcp.ts) sends the reply back. Teamwork!
1
2
3
4

What Happens When You Send a Message

Every AI agent in the world — from NanoClaw to ChatGPT to enterprise systems — follows this same 4-step loop. Once you see it, you'll recognize it everywhere.

📨

1. A message arrives

Someone sends a WhatsApp message. NanoClaw checks: "Is this message for me?" (Does it match the trigger word?)

🧠

2. The AI thinks

The message + conversation history gets sent to Claude. Claude decides: "Do I need a tool, or can I just answer?"

🛠️

3. Use a tool (if needed)

If Claude needs to take action — send a message, check a schedule — it calls a tool. Then loops back to step 2 with the result.

💬

4. Respond

Once Claude has everything it needs, it crafts a clear answer and sends it back through WhatsApp.

That's it. That's the entire pattern. Now let's see it as pseudocode.

1
2
3
4

The Agent in Almost-English

Before we look at real code, here's the entire agent written in plain English that looks like code. This is called "pseudocode" — it's how programmers plan before they write.

nanoclaw-in-plain-english.txt
1 EVERY 2 seconds:
2 Check for new WhatsApp messages
3
4 FOR EACH new message:
5 IF message does NOT contain the trigger word:
6 Skip it // not for us
7
8 Show "typing..." on WhatsApp // so the user knows we're working
9 Load conversation history from the Filing Cabinet
10 Send message + history to the CEO (Claude AI)
11 Get back the AI's response
12 Send response back to the WhatsApp chat

Read that again. That's the entire NanoClaw agent. 12 lines of logic. Everything else is just the TypeScript syntax to express this same logic.

🔍 Detective Challenge #1

Look at lines 5-6 in the pseudocode. Why would NanoClaw skip messages that don't have a trigger word?

Because NanoClaw lives in group chats! If it responded to every message, it would jump into every conversation — even ones not meant for it. The trigger word (like "@claw") is like saying "Hey Siri" — it tells the agent "this one's for you." Without it, you'd have a very annoying chatbot.
1
2
3
4

Finding the Pseudocode in Real TypeScript

Now the fun part. Below is NanoClaw's actual code — but we've dimmed everything except the key lines. Your job: match each highlighted line back to the pseudocode you just read. The grey lines are just syntax details — ignore them.

👨‍💼 The CEO — index.ts

This is the main file. It runs the loop from the pseudocode — check for messages, think, respond. Only 6 lines matter. The rest is plumbing.

📝 Pseudocode

EVERY 2 seconds:
  Check for new messages
  IF no trigger word: Skip
  Load history from Filing Cabinet
  Send to the CEO (Claude)
  Send response to WhatsApp

🔍 What to look for

Line 30: The "every 2 seconds"
Line 33: "Check for new messages"
Line 38: "IF no trigger word"
Line 44: "Load history"
Line 47: "Send to Claude"
Line 51: "Send response"
src/index.ts THE CEO
1// src/index.ts — NanoClaw Orchestrator
2-11// ... import statements (loading dependencies) ...
12async function main() {
13-28// ... setup code (connecting to WhatsApp) ...
29
30 setInterval(async () => { // EVERY 2 seconds...
31-32 // ...
33 const messages = db.getNewMessages(lastTs) // Check for new messages
34-37 // ...
38 if (!TRIGGER.test(msg.text)) continue // No trigger word? Skip!
39-43 // ...
44 const history = db.getMessagesSince(jid) // Load from Filing Cabinet
45-46 // ...
47 const response = await runAgent(folder, prompt) // Ask the CEO (Claude)
48-50 // ...
51 sock.sendMessage(jid, { text }) // Send response to WhatsApp
52-54 }, 2000) // repeat every 2000 milliseconds
That's the whole agent loop. Six highlighted lines. Everything else (the grey lines) is just setup, error handling, and formatting. The logic is exactly the pseudocode you already read.
🔍 Detective Challenge #2

Look at line 33: db.getNewMessages(lastTs). The db part refers to which "department" of our company?

The Filing Cabinet (db.ts)! The db. prefix means "go to the database file and run this function." It's like the CEO walking over to the filing cabinet and saying "get me all the new messages since the last time I checked."

☎️ The Phone System — ipc-mcp.ts

This file defines the tools the AI agent can use. Remember the Colab notebook where you gave Claude a calculator? Same idea — but NanoClaw's tools send real WhatsApp messages and schedule real tasks.

📱 Your Colab Tools

calculator(expression)
get_stock_price(ticker)
get_company_info(name)
// Simple, educational

🌍 NanoClaw's Tools

send_message(chat, text)
schedule_task(time, task)
register_group(group)
// Real-world actions!
container/ipc-mcp.ts THE TOOLS
1-2// Tools the agent can use — like a menu of actions
3
4// Tool 1: Send a WhatsApp message
5server.tool('send_message', {
6 description: 'Send a message to a WhatsApp chat',
7 input: { chatJid: string, text: string }
8})
9
10// Tool 2: Schedule a task for later
11server.tool('schedule_task', {
12 description: 'Schedule a task to run at a specific time',
13 input: { name: string, schedule: string, prompt: string }
14})
15
16// Tool 3: Register a new WhatsApp group
17server.tool('register_group', {
18 description: 'Register a WhatsApp group for the agent',
19 input: { jid: string, name: string, folder: string }
20})
Notice the pattern? Every tool has a name, a description (so Claude knows when to use it), and inputs (what info it needs). This is EXACTLY the same structure as the tools you built in your Colab notebook — just with real-world actions instead of a calculator.
🔍 Detective Challenge #3

Look at line 6: the description says 'Send a message to a WhatsApp chat'. Who reads this description — a human or the AI?

The AI reads it! Claude uses these descriptions to decide which tool to use. If someone asks "tell the marketing group about the meeting," Claude reads the tool descriptions and thinks: "I need send_message — it sends messages to WhatsApp chats, which is what the user wants." This is why good descriptions matter. The AI is literally reasoning about which tool fits the task.

🗄️ The Filing Cabinet — db.ts

Without memory, every conversation starts from zero. The filing cabinet stores messages, groups, and sessions so the agent remembers what happened before. It uses SQLite — a simple database stored in a single file on disk.

src/db.ts THE MEMORY
1-3// Database setup — one file: messages.db
4
5// Save a new message to the filing cabinet
6function saveMessage(chatJid, sender, text, timestamp) {
7 db.run('INSERT INTO messages VALUES (?, ?, ?, ?)',
8 [chatJid, sender, text, timestamp])
9}
10
11// Retrieve conversation history
12function getMessagesSince(chatJid, since) {
13 return db.all('SELECT * FROM messages WHERE chat = ? AND ts > ?',
14 [chatJid, since])
15}
16
17// Get new messages since last check
18function getNewMessages(lastTimestamp) {
19 return db.all('SELECT * FROM messages WHERE ts > ?',
20 [lastTimestamp])
21}
Three functions. That's the entire memory system. saveMessage puts a message in the cabinet. getMessagesSince retrieves conversation history. getNewMessages checks for messages the agent hasn't seen yet. The SQL commands (INSERT, SELECT) are how you talk to databases — you'll learn more about these in future sessions.
🔍 Detective Challenge #4

Why does getMessagesSince need a chatJid parameter? Why not just get ALL messages?

Because NanoClaw handles multiple group chats at once! If you asked for ALL messages, the agent would see conversations from other groups that have nothing to do with the current question. The chatJid is like a folder label — it says "only get messages from THIS specific group chat." Good memory isn't just remembering everything — it's remembering the right things.

All Three Files Working Together

Let's trace a real scenario through all three files. Someone in a WhatsApp group types: "@claw remind me to submit the report at 5pm"

what-actually-happens.txt
// 1. The CEO checks for messages (index.ts)
index.ts calls db.getNewMessages() // "Any new mail?"
db.ts returns: "@claw remind me to submit the report at 5pm"
// 2. The CEO sees "@claw" and springs into action
index.ts calls db.getMessagesSince() // "What's the context?"
index.ts calls runAgent() // "Claude, figure this out"
// 3. Claude thinks and decides to use a tool
Claude reads the tool descriptions and picks: schedule_task
ipc-mcp.ts runs schedule_task("5pm", "submit report reminder")
// 4. Claude crafts a response
index.ts sends back: "Got it! I'll remind you at 5pm to submit the report."

Three files. One loop. Real-world action.
That's the entire architecture of a production AI agent.

What You Just Learned

You can read production AI code. NanoClaw has 10,500+ GitHub stars — and you just understood how it works. Not by memorizing syntax, but by understanding the architecture: a CEO that runs the loop, a phone system that provides tools, and a filing cabinet that stores memory.

The gap is smaller than you think. Your Colab notebook was ~50 lines. NanoClaw is ~700. The only difference is that NanoClaw connects to WhatsApp instead of a Python prompt, and uses real tools instead of a calculator. The pattern is identical.

Simplicity wins. NanoClaw beat a 400,000-line competitor with 700 lines. In business and in code, the simplest solution that works is usually the best one.

3
files that matter
~20
key lines of code
1
loop pattern
10,500+
GitHub stars

Want to go deeper? Check out the full code walkthrough with every file and all 700 lines annotated.