AI University/Docs

Quickstart: Your First Agent in 15 Minutes

A hands-on tutorial that walks you through building a working AI agent. You will create a research agent that can search the web, read pages, and produce a structured report.

Last updated: 2026-03-02

What you will build

A research agent that takes a company name, searches the web for information, reads their website, and produces a structured competitive brief. All in about 50 lines of code.

By the end of this tutorial, you will understand:

  • How to define an agent with a system prompt
  • How to give an agent tools
  • How to run the agent and get results
  • How the observe-think-act loop works in practice

Prerequisites

If you prefer Cursor or Windsurf, the concepts are the same — only the execution environment differs. See our tool comparison for setup instructions specific to each.

Step 1: Set up your project

Create a new directory and initialize:

mkdir my-first-agent && cd my-first-agent
npm init -y
npm install @anthropic-ai/sdk

Set your API key:

export ANTHROPIC_API_KEY="your-key-here"

Step 2: Define the agent prompt

Create a file called agent.ts:

const SYSTEM_PROMPT = `You are a company research agent.

Your job: Given a company name, research it and produce a structured brief.

STEPS:
1. Search the web for the company
2. Read their main website
3. Find their pricing (if public)
4. Check for recent news

OUTPUT FORMAT:
## Company: [Name]
**Website:** [URL]
**What they do:** [1-2 sentences]
**Pricing:** [Summary or "Not public"]
**Recent news:** [Key headlines]
**Strengths:** [Bullet points]
**Weaknesses:** [Bullet points]

RULES:
- Only include facts you can verify from sources
- If you cannot find something, say "Not found" — never fabricate
- Keep the brief under 500 words`;

This prompt is the agent's identity. It defines the goal, the steps, the output format, and the rules. A good prompt is specific, structured, and honest about limitations.

Step 3: Define tools

Tools are what give your agent hands. Without tools, it can only think — it cannot act.

const tools = [
  {
    name: "search_web",
    description: "Search the web for information. Returns top results with titles and snippets.",
    input_schema: {
      type: "object" as const,
      properties: {
        query: { type: "string", description: "The search query" },
      },
      required: ["query"],
    },
  },
  {
    name: "read_page",
    description: "Read the content of a web page. Returns the text content.",
    input_schema: {
      type: "object" as const,
      properties: {
        url: { type: "string", description: "The URL to read" },
      },
      required: ["url"],
    },
  },
];

Each tool has:

  • A name the LLM uses to call it
  • A description so the LLM knows when to use it
  • An input schema defining what parameters it accepts

The description matters more than you think. The LLM reads it to decide which tool to use. Write descriptions that explain when to use the tool, not just what it does.

Step 4: Implement tool execution

When the agent decides to use a tool, you need to actually execute it:

async function executeTool(name: string, input: Record<string, string>): Promise<string> {
  switch (name) {
    case "search_web":
      // In production, use a real search API (Tavily, SerpAPI, etc.)
      // For this demo, we will simulate it
      return `Search results for "${input.query}":\n1. ${input.query} - Official Website\n2. ${input.query} pricing and plans\n3. ${input.query} recent news and updates`;

    case "read_page":
      // In production, use fetch + cheerio or a headless browser
      return `Content from ${input.url}: [Page content would appear here]`;

    default:
      return `Unknown tool: ${name}`;
  }
}

In a real agent, search_web calls a search API and read_page fetches and parses HTML. The agent does not know or care about the implementation — it just sees the results.

Step 5: Run the agent loop

This is the core of every agent — the loop that keeps running until the task is done:

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

const client = new Anthropic();

async function runAgent(companyName: string) {
  console.log(`Researching: ${companyName}\n`);

  const messages: Anthropic.MessageParam[] = [
    { role: "user", content: `Research this company: ${companyName}` },
  ];

  // Agent loop — keeps running until the agent stops calling tools
  while (true) {
    const response = await client.messages.create({
      model: "claude-sonnet-4-6",
      max_tokens: 4096,
      system: SYSTEM_PROMPT,
      tools,
      messages,
    });

    // Collect all text and tool calls from the response
    const toolCalls = response.content.filter((b) => b.type === "tool_use");
    const textBlocks = response.content.filter((b) => b.type === "text");

    // Print any text the agent produces
    for (const block of textBlocks) {
      console.log(block.text);
    }

    // If no tool calls, the agent is done
    if (toolCalls.length === 0) break;

    // Add the assistant's response to the conversation
    messages.push({ role: "assistant", content: response.content });

    // Execute each tool call and add results
    const toolResults: Anthropic.ToolResultBlockParam[] = [];
    for (const call of toolCalls) {
      console.log(`  [Tool] ${call.name}(${JSON.stringify(call.input)})`);
      const result = await executeTool(call.name, call.input as Record<string, string>);
      toolResults.push({
        type: "tool_result",
        tool_use_id: call.id,
        content: result,
      });
    }

    messages.push({ role: "user", content: toolResults });
  }
}

// Run it
runAgent("Vercel").catch(console.error);

Step 6: Run your agent

npx tsx agent.ts

You will see the agent:

  1. Search the web for "Vercel"
  2. Read their website
  3. Look for pricing information
  4. Compile everything into a structured brief

That is the observe-think-act loop in action. The LLM decided which tools to call, in what order, and when to stop.

What just happened

You built an agent with:

  • A system prompt defining its role and rules
  • Two tools giving it the ability to search and read
  • An execution loop that runs until the task is complete

The LLM handled all the decision-making. You did not write any if/else logic for "search first, then read, then summarize." The model figured that out from the prompt.

Making it production-ready

This demo is simplified. A production agent adds:

ConcernSolution
Real searchUse Tavily, SerpAPI, or Brave Search API
Page readingUse fetch + cheerio for HTML parsing
Error handlingWrap tool calls in try/catch, return errors to the agent
Token limitsTrack token usage, implement context windowing
Rate limitingAdd delays between API calls
MemorySave results to a database for future reference
GuardrailsValidate tool inputs, restrict allowed domains
SchedulingRun agents on a cron schedule with an orchestrator

Each of these is covered in depth in the Production section.

Key takeaways

  • An agent is a loop: prompt the LLM, execute tool calls, feed results back, repeat
  • The system prompt defines what the agent does; tools define how it acts
  • Tool descriptions are critical — the LLM reads them to decide which tool to use
  • Start simple (2-3 tools), add complexity only when needed
  • The same pattern works regardless of which tool you use (Claude Code, Cursor, Windsurf)