---
title: Quickstart
description: Build your first Reactive Agent in 5 minutes.
sidebar:
  order: 3
---

import { Steps, FileTree, Aside, Badge, CardGrid, LinkCard } from '@astrojs/starlight/components';

## Prerequisites

- [Bun](https://bun.sh) ≥1.0.0 (`curl -fsSL https://bun.sh/install | bash`)
- An API key from [Anthropic](https://console.anthropic.com), [Google Gemini](https://ai.google.dev/), [OpenAI](https://platform.openai.com), or [LiteLLM](https://www.litellm.ai) — *or* run a local model with [Ollama](https://ollama.com) (no key needed)

The fastest path through this guide is the `rax` workflow (`Rax` = Reactive Agents Executable).

<Aside type="tip" title="In a hurry?">
The minimum viable agent is **3 lines**. Skip to step 3 if you've already got Bun + an API key.
</Aside>

## 1. Create a Project

Using the CLI:

```bash
bunx rax init my-agent-app --template standard
cd my-agent-app
bun install
```

`rax init --template standard` scaffolds:

<FileTree>
- my-agent-app/
  - src/
    - **agent.ts** Your first agent — runnable with `bun run src/agent.ts`
    - tools/ Drop custom tools here; auto-discovered when wired into builder
  - .env Provider API keys (gitignored by default)
  - package.json `reactive-agents` dependency + `bun run agent` script
  - tsconfig.json strict mode + Bun-aware module resolution
  - README.md
</FileTree>

Or manually:

```bash
mkdir my-agent-app && cd my-agent-app
bun init -y
bun add reactive-agents
```

:::note[Effect dependency]
`effect` ships as a dependency of `reactive-agents` and is installed automatically. For hooks and custom tools, import helpers explicitly (`import { Effect } from "effect"`) and use **`Effect.succeed`**, **`Effect.fail`**, etc. — see the [Effect-TS primer](/concepts/effect-ts/). Add `effect` to your app only if you rely on it outside the framework’s re-exports.
:::

## 2. Set Up Environment

Set at least one provider key. Pick whichever you have access to:

```bash
# Pick at least one
echo 'ANTHROPIC_API_KEY=sk-ant-...' > .env  # Recommended for first agent
echo 'OPENAI_API_KEY=sk-...'        >> .env
echo 'GOOGLE_API_KEY=...'           >> .env

# Or run fully local — no key needed
ollama pull qwen3:4b
```

Optional keys for built-in tools (web search, etc.) — add them later when you call `.withTools()`:

```bash
echo 'TAVILY_API_KEY=tvly-...' >> .env   # Web search (Tavily backend)
echo 'SERPER_API_KEY=...'      >> .env   # Web search (Serper.dev backend)
```

## 3. Build an Agent

Create `src/agent.ts`:

```typescript title="src/agent.ts"
import { ReactiveAgents } from "reactive-agents";

const agent = await ReactiveAgents.create()
  .withProvider("anthropic")
  .build();

const result = await agent.run("What are the three laws of thermodynamics?");
console.log(result.output);
```

That's the minimum. `.withProvider()` picks the default model for the provider automatically (`claude-sonnet-4-20250514` for Anthropic). Set `ANTHROPIC_API_KEY` in your environment before running.

To pin a specific model or add a name:

```typescript title="src/agent.ts" {2-5}
const agent = await ReactiveAgents.create()
  .withName("my-first-agent")
  .withProvider("anthropic")
  .withModel("claude-sonnet-4-20250514")
  .build();

const result = await agent.run("What are the three laws of thermodynamics?");
console.log("Output:", result.output);
console.log("Duration:", result.metadata.duration, "ms");
console.log("Steps:", result.metadata.stepsCount);
```

:::tip[Resource cleanup]
Always dispose agents that use MCP servers or other subprocess-based tools — otherwise the process will hang on open pipes. Use `await using` for automatic cleanup, or [`runOnce()`](../../reference/builder-api/#runonceinput-string-promiseagentresult) for one-shot scripts. See [Resource Management](../../reference/builder-api/#resource-management) for all three patterns.
:::

## 4. Run It

```bash
bun run src/agent.ts
```

## 5. Add Capabilities

Enable memory, reasoning, and safety:

```typescript title="src/agent.ts" {5-8}
const agent = await ReactiveAgents.create()
  .withName("research-agent")
  .withProvider("anthropic")
  .withModel("claude-sonnet-4-20250514")
  .withMemory()         // Default tier "standard" (FTS5 keyword search)
  .withReasoning()      // ReAct loop: Think → Act → Observe
  .withGuardrails()     // Pre-LLM injection / PII / toxicity blocking
  .withCostTracking()   // Complexity routing + budget enforcement
  .build();
```

## What's Next?

<CardGrid>
  <LinkCard
    title="Scaffold a New Project"
    description="create-reactive-agent scaffolds a runnable agent in seconds — pick template, provider, and package manager."
    href="/features/create-reactive-agent/"
  />
  <LinkCard
    title="OpenTelemetry Tracing"
    description="Export spans from every agent run to Jaeger, Grafana Tempo, Langfuse, or any OTLP backend."
    href="/features/observe/"
  />
  <LinkCard
    title="Your First Agent"
    description="Deeper walkthrough — memory, reasoning, guardrails, and lifecycle hooks step by step."
    href="../your-first-agent/"
  />
  <LinkCard
    title="Common Builder Stacks"
    description="Copy-paste recipes for tools, streaming, multi-agent, gateway, and Agent-as-data."
    href="/cookbook/builder-stacks/"
  />
  <LinkCard
    title="API Cheatsheet"
    description="The 80% of the API on one page — every important method, runtime call, and event tag."
    href="/reference/cheatsheet/"
  />
  <LinkCard
    title="Choosing a Stack"
    description="Pick provider, model tier, memory, and reasoning strategy in 2 minutes."
    href="../choosing-a-stack/"
  />
  <LinkCard
    title="Browse 30+ Examples"
    description="Runnable across foundations, tools, multi-agent, gateway, streaming, and more."
    href="../examples/"
  />
  <LinkCard
    title="Troubleshooting"
    description="Symptom → cause → fix reference for the most common failures."
    href="../troubleshooting/"
  />
</CardGrid>
