> ## Documentation Index
> Fetch the complete documentation index at: https://vibes-sdk.a7ul.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Hello World

> Build your first AI agent in 5 minutes. Start simple, add tools, structured output, and tests.

In this tutorial you will build a weather agent from scratch. You will start with a bare agent, add a tool, add structured output, and write a test - all in one progressive flow. By the end, you will have a fully tested, type-safe agent.

## Prerequisites

* Vibes installed ([Installation guide](/getting-started/install))
* An Anthropic API key set in your environment: `export ANTHROPIC_API_KEY="sk-ant-..."`

<Steps>
  <Step title="Create a bare agent">
    Start with the simplest possible agent: a model and a system prompt.

    ```ts theme={null}
    import { Agent } from "@vibesjs/sdk";
    import { anthropic } from "@ai-sdk/anthropic";

    const agent = new Agent({
      model: anthropic("claude-haiku-4-5-20251001"),
      systemPrompt: "You are a helpful weather assistant.",
    });

    const result = await agent.run("What's the weather like?");
    console.log(result.output);
    // The agent responds with text (no tools yet, so it can only guess)
    ```

    `Agent` takes a model and system prompt. `agent.run()` sends a message and returns a result. `result.output` is the text response.

    <Note>
      Without tools, the agent can only respond from its training data. Let's fix that.
    </Note>
  </Step>

  <Step title="Add a tool">
    Give the agent real capabilities by defining a type-safe tool with Zod parameter validation.

    ```ts theme={null}
    import { Agent, tool } from "@vibesjs/sdk";
    import { anthropic } from "@ai-sdk/anthropic";
    import { z } from "zod";

    const getWeather = tool({
      name: "get_weather",
      description: "Get the current weather for a city",
      parameters: z.object({
        city: z.string().describe("City name"),
      }),
      execute: async (_ctx, { city }) => {
        // In production, call a real weather API
        return `${city}: 22°C, sunny`;
      },
    });

    const agent = new Agent({
      model: anthropic("claude-haiku-4-5-20251001"),
      systemPrompt: "You are a helpful weather assistant.",
      tools: [getWeather],
    });

    const result = await agent.run("What's the weather in Tokyo?");
    console.log(result.output);
    // "The weather in Tokyo is currently 22°C and sunny."
    ```

    `tool()` creates a type-safe tool with Zod parameter validation. The agent automatically calls tools when relevant. The `_ctx` parameter is the `RunContext` - we will use it later for dependency injection.

    <Tip>
      The tool's `description` helps the model decide when to call it. Be specific!
    </Tip>
  </Step>

  <Step title="Add structured output">
    Force the agent to return typed data by providing an `outputSchema`.

    ```ts theme={null}
    import { Agent, tool } from "@vibesjs/sdk";
    import { anthropic } from "@ai-sdk/anthropic";
    import { z } from "zod";

    const getWeather = tool({
      name: "get_weather",
      description: "Get the current weather for a city",
      parameters: z.object({
        city: z.string().describe("City name"),
      }),
      execute: async (_ctx, { city }) => {
        return `${city}: 22°C, sunny`;
      },
    });

    const WeatherReport = z.object({
      city: z.string(),
      temperature: z.number().describe("Temperature in Celsius"),
      condition: z.string().describe("e.g. sunny, cloudy, rainy"),
      summary: z.string().describe("A brief human-readable summary"),
    });

    const agent = new Agent({
      model: anthropic("claude-haiku-4-5-20251001"),
      systemPrompt: "You are a helpful weather assistant.",
      tools: [getWeather],
      outputSchema: WeatherReport,
    });

    const result = await agent.run("What's the weather in Tokyo?");
    // result.output is typed as { city: string; temperature: number; condition: string; summary: string }
    console.log(result.output.city);        // "Tokyo"
    console.log(result.output.temperature); // 22
    console.log(result.output.condition);   // "sunny"
    ```

    `outputSchema` forces the agent to return data matching your Zod schema. `result.output` is now typed as `{ city: string; temperature: number; condition: string; summary: string }` instead of `string`. The agent will retry if validation fails.

    <Note>
      Structured output uses tool-based extraction by default. The agent calls a special output tool internally.
    </Note>
  </Step>

  <Step title="Test your agent">
    Test the agent without making real API calls using `TestModel`.

    ```ts theme={null}
    import { assertEquals } from "@std/assert";
    import { Agent, tool, TestModel, setAllowModelRequests } from "@vibesjs/sdk";
    import { z } from "zod";
    import { anthropic } from "@ai-sdk/anthropic";

    // Block accidental real API calls in your test suite
    setAllowModelRequests(false);

    const getWeather = tool({
      name: "get_weather",
      description: "Get the current weather for a city",
      parameters: z.object({
        city: z.string().describe("City name"),
      }),
      execute: async (_ctx, { city }) => {
        return `${city}: 22°C, sunny`;
      },
    });

    const WeatherReport = z.object({
      city: z.string(),
      temperature: z.number().describe("Temperature in Celsius"),
      condition: z.string().describe("e.g. sunny, cloudy, rainy"),
      summary: z.string().describe("A brief human-readable summary"),
    });

    const agent = new Agent({
      model: anthropic("claude-haiku-4-5-20251001"),
      systemPrompt: "You are a helpful weather assistant.",
      tools: [getWeather],
      outputSchema: WeatherReport,
    });

    Deno.test("weather agent returns structured output", async () => {
      const result = await agent
        .override({ model: new TestModel() })
        .run("What's the weather in Tokyo?");

      // TestModel auto-calls tools and produces schema-valid output
      assertEquals(typeof result.output.city, "string");
      assertEquals(typeof result.output.temperature, "number");
    });
    ```

    Run the test:

    ```bash theme={null}
    deno test agent_test.ts
    ```

    `TestModel` simulates model responses without API calls. `agent.override()` creates a copy of the agent with the test model - the original agent is unchanged (immutable). `setAllowModelRequests(false)` blocks any accidental real API calls in your test suite.
  </Step>
</Steps>

## What's next?

<Note>
  These concept deep-dives are coming soon.
</Note>

<CardGroup cols={2}>
  <Card title="Agents" icon="robot" href="/concepts/agents">
    Deep dive into the agent loop, system prompts, and run context.
  </Card>

  <Card title="Tools" icon="wrench" href="/concepts/tools">
    Build type-safe tools with Zod schemas and dependency injection.
  </Card>

  <Card title="Dependencies" icon="link" href="/concepts/dependencies">
    Inject services, databases, and other dependencies into your agents.
  </Card>
</CardGroup>
