---
title: Quick Start
description: Get your first Octavus agent running in minutes.
---

# Quick Start

This guide will walk you through integrating Octavus into your application in under 10 minutes.

## Prerequisites

- Node.js 18+
- An Octavus account with API key
- A Next.js application (or any Node.js backend)

## Installation

Install the Octavus SDKs in your project:

```bash
# Server SDK for backend
npm install @octavus/server-sdk

# React bindings for frontend
npm install @octavus/react
```

## Backend Setup

### 1. Initialize the Client

Create an Octavus client instance in your backend:

```typescript
// lib/octavus.ts
import { OctavusClient } from '@octavus/server-sdk';

export const octavus = new OctavusClient({
  baseUrl: process.env.OCTAVUS_API_URL!,
  apiKey: process.env.OCTAVUS_API_KEY!,
});
```

### 2. Create a Session Endpoint

Create an API endpoint that creates sessions and returns the session ID:

```typescript
// app/api/chat/create/route.ts
import { NextResponse } from 'next/server';
import { octavus } from '@/lib/octavus';

export async function POST(request: Request) {
  const { agentSlug, input } = await request.json();

  // Look up agent by slug to get its ID
  const agent = await octavus.agents.getBySlug(agentSlug);
  if (!agent) {
    return NextResponse.json({ error: 'Agent not found' }, { status: 404 });
  }

  // Create a new session using the agent ID
  const sessionId = await octavus.agentSessions.create(agent.id, input);

  return NextResponse.json({ sessionId });
}
```

### 3. Create a Trigger Endpoint

Create an endpoint that handles triggers and streams responses:

```typescript
// app/api/trigger/route.ts
import { toSSEStream } from '@octavus/server-sdk';
import { octavus } from '@/lib/octavus';

export async function POST(request: Request) {
  const { sessionId, triggerName, input } = await request.json();

  // Attach to session with tool handlers
  const session = octavus.agentSessions.attach(sessionId, {
    tools: {
      // Define tool handlers that run on your server
      'get-user-account': async (args) => {
        const userId = args.userId as string;
        // Fetch from your database
        return {
          name: 'Demo User',
          email: 'demo@example.com',
          plan: 'pro',
        };
      },
      'create-support-ticket': async (args) => {
        // Create ticket in your system
        return {
          ticketId: 'TICKET-123',
          estimatedResponse: '24 hours',
        };
      },
    },
  });

  // Trigger the action and convert to SSE stream
  const events = session.trigger(triggerName, input);

  // Return as streaming response
  return new Response(toSSEStream(events), {
    headers: {
      'Content-Type': 'text/event-stream',
      'Cache-Control': 'no-cache',
      Connection: 'keep-alive',
    },
  });
}
```

## Frontend Setup

### 1. Create a Chat Component

Use the `useOctavusChat` hook with the HTTP transport:

```tsx
// components/chat.tsx
'use client';

import { useState, useMemo } from 'react';
import { useOctavusChat, createHttpTransport, type UIMessage } from '@octavus/react';

interface ChatProps {
  sessionId: string;
}

export function Chat({ sessionId }: ChatProps) {
  const [inputValue, setInputValue] = useState('');

  // Create a stable transport instance
  const transport = useMemo(
    () =>
      createHttpTransport({
        triggerRequest: (triggerName, input) =>
          fetch('/api/trigger', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ sessionId, triggerName, input }),
          }),
      }),
    [sessionId],
  );

  const { messages, status, error, send } = useOctavusChat({ transport });

  const isStreaming = status === 'streaming';

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!inputValue.trim() || isStreaming) return;

    const message = inputValue.trim();
    setInputValue('');

    // Add user message and trigger in one call
    await send(
      'user-message',
      { USER_MESSAGE: message },
      { userMessage: { content: message } },
    );
  };

  return (
    <div className="flex flex-col h-full">
      {/* Messages */}
      <div className="flex-1 overflow-y-auto p-4 space-y-4">
        {messages.map((msg) => (
          <MessageBubble key={msg.id} message={msg} />
        ))}
      </div>

      {/* Input */}
      <form onSubmit={handleSubmit} className="p-4 border-t">
        <div className="flex gap-2">
          <input
            type="text"
            value={inputValue}
            onChange={(e) => setInputValue(e.target.value)}
            placeholder="Type a message..."
            className="flex-1 px-4 py-2 border rounded-lg"
            disabled={isStreaming}
          />
          <button
            type="submit"
            disabled={isStreaming}
            className="px-4 py-2 bg-blue-500 text-white rounded-lg disabled:opacity-50"
          >
            Send
          </button>
        </div>
      </form>
    </div>
  );
}

function MessageBubble({ message }: { message: UIMessage }) {
  const isUser = message.role === 'user';

  return (
    <div className={`flex ${isUser ? 'justify-end' : 'justify-start'}`}>
      <div
        className={`p-3 rounded-lg max-w-md ${
          isUser ? 'bg-blue-500 text-white' : 'bg-gray-100'
        }`}
      >
        {message.parts.map((part, i) => {
          if (part.type === 'text') {
            return <p key={i}>{part.text}</p>;
          }
          return null;
        })}

        {/* Streaming indicator */}
        {message.status === 'streaming' && (
          <span className="inline-block w-2 h-4 bg-gray-400 animate-pulse ml-1" />
        )}
      </div>
    </div>
  );
}
```

### 2. Create Session and Render Chat

```tsx
// app/chat/page.tsx
'use client';

import { useEffect, useState } from 'react';
import { Chat } from '@/components/chat';

export default function ChatPage() {
  const [sessionId, setSessionId] = useState<string | null>(null);

  useEffect(() => {
    async function createSession() {
      const response = await fetch('/api/chat/create', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          agentSlug: 'support-chat',
          input: {
            COMPANY_NAME: 'Acme Corp',
            PRODUCT_NAME: 'Widget Pro',
          },
        }),
      });
      const { sessionId } = await response.json();
      setSessionId(sessionId);
    }

    createSession();
  }, []);

  if (!sessionId) {
    return <div>Loading...</div>;
  }

  return <Chat sessionId={sessionId} />;
}
```

## Environment Variables

Add these to your `.env.local`:

```bash
OCTAVUS_API_URL=https://octavus.ai
OCTAVUS_API_KEY=your-api-key-here
```

## What's Next?

Now that you have a basic integration working:

- [Learn about the protocol](/docs/protocol/overview) to define custom agent behavior
- [Explore the Server SDK](/docs/server-sdk/overview) for advanced backend features
- [Build rich UIs](/docs/client-sdk/overview) with the Client SDK
