AgentAcademy
Module 5
15 min read

Building Your Own Agents

Get hands-on with building AI agents using Claude Code and the Agent SDK.

Getting Started with Claude Code

Claude Code is Anthropic's official agentic coding tool. It's a complete implementation of an AI coding agent that you can use immediately. Let's explore how it works and how you can use it effectively.

Installation
# Install globally with npm
npm install -g @anthropic-ai/claude-code

# Or use directly with npx
npx @anthropic-ai/claude-code

# Start Claude Code in your project
cd your-project
claude

How Claude Code Works

When you run Claude Code, it:

  • Reads your project structure and CLAUDE.md file
  • Provides Claude with tools for file operations, code search, and command execution
  • Manages the conversation loop between you and the AI
  • Handles permissions and safety checks
$ claude
╭─────────────────────────────────────────────────────────────╮
│ Claude Code                                                  │
│ Your AI pair programmer                                      │
╰─────────────────────────────────────────────────────────────╯

> Create a React component for a todo list

I'll create a todo list component for you. Let me first check
your project structure to understand the patterns you're using...

[Reading src/components/...]

I see you're using TypeScript with functional components. I'll
create a TodoList component following your existing patterns.

[Writing src/components/TodoList.tsx...]
[Writing src/components/TodoItem.tsx...]

Done! I've created two components:
- TodoList.tsx - The main container with state management
- TodoItem.tsx - Individual todo item with edit/delete

Would you like me to add tests or connect it to your app?

Building Custom Agents

While Claude Code is ready-to-use, you might want to build custom agents for specific use cases. Here are the key components:

Simple agent that can have a conversation:

import Anthropic from '@anthropic-ai/sdk';

const anthropic = new Anthropic();

async function chat(userMessage: string) {
  const response = await anthropic.messages.create({
    model: "claude-sonnet-4-20250514",
    max_tokens: 1024,
    system: "You are a helpful coding assistant.",
    messages: [
      { role: "user", content: userMessage }
    ]
  });

  return response.content[0].text;
}

// Usage
const answer = await chat("How do I reverse a string in JavaScript?");
console.log(answer);

The Agent SDK

For more sophisticated agents, Anthropic provides the Agent SDK, which handles many complexities for you:

import { Agent, Tool } from '@anthropic-ai/agent-sdk';

// Define custom tools
const calculator: Tool = {
  name: "calculator",
  description: "Perform mathematical calculations",
  execute: async (input) => {
    return eval(input.expression).toString();
  },
  schema: {
    type: "object",
    properties: {
      expression: { type: "string" }
    }
  }
};

// Create an agent
const agent = new Agent({
  model: "claude-sonnet-4-20250514",
  systemPrompt: "You are a helpful math tutor.",
  tools: [calculator]
});

// Run the agent
const result = await agent.run("What's 15% of 340?");

Architecture Patterns

Single Agent

One agent handles everything. Simple but limited for complex tasks.

User → Agent → Tools → Result
Supervisor Pattern

A main agent delegates to specialized sub-agents.

User → Supervisor Agent
              ├→ Code Agent
              ├→ Test Agent
              └→ Deploy Agent
Pipeline Pattern

Agents work in sequence, each building on previous work.

User → Planner → Coder → Reviewer → Tester → Result

Best Practices

Start Simple

Begin with a single agent and basic tools. Add complexity only when needed.

Log Everything

Record all tool calls, responses, and decisions. Essential for debugging.

Handle Errors Gracefully

Tools will fail. Give agents the information to recover or ask for help.

Set Boundaries

Limit which files/commands are accessible. Use sandboxing where possible.

Test Incrementally

Test each tool independently before combining. Verify the agent loop with simple tasks first.

Human in the Loop

For important actions, require human confirmation. Don't let agents run wild.

Example: File Organizer Agent

Here's a complete example of a simple but useful agent that organizes files:

import Anthropic from '@anthropic-ai/sdk';
import * as fs from 'fs/promises';
import * as path from 'path';

const anthropic = new Anthropic();

const tools = [
  {
    name: "list_files",
    description: "List files in a directory",
    input_schema: {
      type: "object",
      properties: {
        directory: { type: "string" }
      },
      required: ["directory"]
    }
  },
  {
    name: "move_file",
    description: "Move a file to a new location",
    input_schema: {
      type: "object",
      properties: {
        source: { type: "string" },
        destination: { type: "string" }
      },
      required: ["source", "destination"]
    }
  },
  {
    name: "create_directory",
    description: "Create a new directory",
    input_schema: {
      type: "object",
      properties: {
        path: { type: "string" }
      },
      required: ["path"]
    }
  }
];

async function executeTool(name: string, input: any) {
  switch (name) {
    case "list_files":
      const files = await fs.readdir(input.directory);
      return files.join('\n');
    case "move_file":
      await fs.rename(input.source, input.destination);
      return `Moved ${input.source} to ${input.destination}`;
    case "create_directory":
      await fs.mkdir(input.path, { recursive: true });
      return `Created directory ${input.path}`;
  }
}

// Run with: organizeFiles("./downloads")
async function organizeFiles(directory: string) {
  return await runAgent(
    `Organize the files in ${directory} by type.
     Create folders for images, documents, and other.
     Move each file to the appropriate folder.`
  );
}

Key Takeaways

  • Claude Code is a ready-to-use agentic coding assistant
  • Custom agents need tools, an agent loop, and proper error handling
  • The Agent SDK simplifies building sophisticated agents
  • Choose architecture patterns based on task complexity
  • Always prioritize safety with logging, boundaries, and human oversight