---
title: Migrating from v1 to v2
description: Complete guide for upgrading from Octavus SDK v1.x to v2.0.
---

# Migrating from v1 to v2

This guide covers all breaking changes and new features in Octavus SDK v2.0.0.

## Overview

Version 2.0.0 introduces **client-side tool execution**, allowing tools to run in the browser with support for both automatic execution and interactive user input. This required changes to the transport layer and streaming protocol.

## Breaking Changes

### HTTP Transport Configuration

The `triggerRequest` option has been renamed to `request` and the function signature changed to support both trigger and continuation requests.

**Before (v1):**

```typescript
import { createHttpTransport } from '@octavus/client-sdk';

const transport = createHttpTransport({
  triggerRequest: (triggerName, input, options) =>
    fetch('/api/trigger', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ sessionId, triggerName, input }),
      signal: options?.signal,
    }),
});
```

**After (v2):**

```typescript
import { createHttpTransport } from '@octavus/client-sdk';

const transport = createHttpTransport({
  request: (payload, options) =>
    fetch('/api/trigger', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ sessionId, ...payload }),
      signal: options?.signal,
    }),
});
```

The `payload` parameter is a discriminated union with `type: 'trigger' | 'continue'`:

- **Trigger request:** `{ type: 'trigger', triggerName: string, input?: Record<string, unknown> }`
- **Continue request:** `{ type: 'continue', executionId: string, toolResults: ToolResult[] }`

### Server SDK Route Handler

Server-side route handlers should use the new `execute()` method which handles both triggers and continuations via the request type.

**Before (v1):**

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

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

  const session = new AgentSession({
    sessionId,
    agentId: 'your-agent-id',
    apiKey: process.env.OCTAVUS_API_KEY!,
  });

  const events = session.trigger(triggerName, input, { signal: request.signal });
  return new Response(toSSEStream(events), {
    headers: { 'Content-Type': 'text/event-stream' },
  });
}
```

**After (v2):**

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

export async function POST(request: Request) {
  const body = (await request.json()) as { sessionId: string } & SessionRequest;
  const { sessionId, ...sessionRequest } = body;

  const session = new AgentSession({
    sessionId,
    agentId: 'your-agent-id',
    apiKey: process.env.OCTAVUS_API_KEY!,
  });

  const events = session.execute(sessionRequest, { signal: request.signal });
  return new Response(toSSEStream(events), {
    headers: { 'Content-Type': 'text/event-stream' },
  });
}
```

The `SessionRequest` type is a discriminated union:

- **Trigger:** `{ type: 'trigger', triggerName: string, input?: Record<string, unknown> }`
- **Continue:** `{ type: 'continue', executionId: string, toolResults: ToolResult[] }`

### Export Changes

The SDKs no longer use star exports (`export * from '@octavus/core'`). Instead, they use explicit type exports and value exports. This improves tree-shaking but may require import adjustments.

**If you were importing schemas:**

Some Zod schemas are no longer re-exported from `@octavus/server-sdk`. If you need validation schemas, import them directly from `@octavus/core`:

```typescript
// Before (v1) - some schemas were re-exported
import { fileUploadRequestSchema } from '@octavus/server-sdk';

// After (v2) - import from core if needed
import { fileReferenceSchema } from '@octavus/core';
```

**Type imports remain the same:**

```typescript
// Types are still available
import type { StreamEvent, UIMessage, FileReference } from '@octavus/client-sdk';
```

### Custom Transport Interface

Custom transport implementations must now implement the `continueWithToolResults()` method:

```typescript
interface Transport {
  trigger(triggerName: string, input?: Record<string, unknown>): AsyncIterable<StreamEvent>;
  continueWithToolResults(executionId: string, results: ToolResult[]): AsyncIterable<StreamEvent>;
  stop(): void;
}
```

### New ChatStatus Value

The `ChatStatus` type now includes `'awaiting-input'`:

```typescript
// v1
type ChatStatus = 'idle' | 'streaming' | 'error';

// v2
type ChatStatus = 'idle' | 'streaming' | 'error' | 'awaiting-input';
```

Update any status checks that assume only three values.

### Stream Event Changes

Two stream events have been modified:

**StartEvent and FinishEvent now include executionId:**

```typescript
interface StartEvent {
  type: 'start';
  messageId?: string;
  executionId?: string; // New in v2
}

interface FinishEvent {
  type: 'finish';
  finishReason: FinishReason;
  executionId?: string; // New in v2
}
```

**New FinishReason:**

```typescript
// Added 'client-tool-calls' to FinishReason
type FinishReason =
  | 'stop'
  | 'tool-calls'
  | 'client-tool-calls' // New in v2
  | 'length'
  | 'content-filter'
  | 'error'
  | 'other';
```

**New ClientToolRequestEvent:**

```typescript
interface ClientToolRequestEvent {
  type: 'client-tool-request';
  executionId: string;
  toolCalls: PendingToolCall[];
  serverToolResults?: ToolResult[];
}
```

## New Features

### Client-Side Tools

v2 introduces client-side tool execution, allowing tools to run in the browser. This is useful for:

- Accessing browser APIs (geolocation, clipboard, etc.)
- Interactive tools requiring user input (confirmations, forms, selections)
- Tools that need access to client-side state

See the [Client Tools guide](/docs/client-sdk/client-tools) for full documentation.

#### Automatic Client Tools

Tools that execute automatically without user interaction:

```typescript
import { useOctavusChat, createHttpTransport } from '@octavus/react';

function Chat() {
  const { messages, send, status } = useOctavusChat({
    transport: createHttpTransport({
      request: (payload, options) =>
        fetch('/api/trigger', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ sessionId, ...payload }),
          signal: options?.signal,
        }),
    }),
    clientTools: {
      'get-browser-location': async (args, ctx) => {
        const pos = await new Promise((resolve, reject) => {
          navigator.geolocation.getCurrentPosition(resolve, reject);
        });
        return { lat: pos.coords.latitude, lng: pos.coords.longitude };
      },
      'get-clipboard': async () => {
        return await navigator.clipboard.readText();
      },
    },
  });

  // ... rest of component
}
```

#### Interactive Client Tools

Tools that require user interaction before completing:

```typescript
import { useOctavusChat, createHttpTransport } from '@octavus/react';

function Chat() {
  const { messages, send, status, pendingClientTools } = useOctavusChat({
    transport: createHttpTransport({
      request: (payload, options) =>
        fetch('/api/trigger', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ sessionId, ...payload }),
          signal: options?.signal,
        }),
    }),
    clientTools: {
      'request-confirmation': 'interactive',
      'select-option': 'interactive',
    },
  });

  // Render UI for pending interactive tools
  const confirmationTools = pendingClientTools['request-confirmation'] ?? [];

  return (
    <div>
      {/* Chat messages */}

      {/* Interactive tool UI */}
      {confirmationTools.map((tool) => (
        <ConfirmationModal
          key={tool.toolCallId}
          message={tool.args.message as string}
          onConfirm={() => tool.submit({ confirmed: true })}
          onCancel={() => tool.cancel('User declined')}
        />
      ))}
    </div>
  );
}
```

### New Types for Client Tools

```typescript
// Context provided to automatic tool handlers
interface ClientToolContext {
  toolCallId: string;
  toolName: string;
  signal: AbortSignal;
}

// Handler types
type ClientToolHandler =
  | ((args: Record<string, unknown>, ctx: ClientToolContext) => Promise<unknown>)
  | 'interactive';

// Interactive tool with bound submit/cancel methods
interface InteractiveTool {
  toolCallId: string;
  toolName: string;
  args: Record<string, unknown>;
  submit: (result: unknown) => void;
  cancel: (reason?: string) => void;
}
```

### pendingClientTools Property

Both `OctavusChat` and `useOctavusChat` now expose `pendingClientTools`:

```typescript
// Record keyed by tool name, with array of pending tools
const pendingClientTools: Record<string, InteractiveTool[]>;
```

This allows multiple simultaneous calls to the same tool (e.g., batch confirmations).

## Migration Checklist

Use this checklist to ensure you've addressed all breaking changes:

- [ ] Update all Octavus packages to v2.0.0
- [ ] Update HTTP transport from `triggerRequest` to `request` with new signature
- [ ] Update server route handlers to use `execute()` with `SessionRequest` type
- [ ] Update any status checks to handle `'awaiting-input'`
- [ ] Update custom transport implementations to include `continueWithToolResults()`
- [ ] Review any direct schema imports and update if needed
- [ ] (Optional) Add client-side tools for browser-based functionality

## Package Versions

All packages should be updated together to ensure compatibility:

```json
{
  "dependencies": {
    "@octavus/core": "^2.0.0",
    "@octavus/client-sdk": "^2.0.0",
    "@octavus/server-sdk": "^2.0.0",
    "@octavus/react": "^2.0.0"
  }
}
```

## Need Help?

If you encounter issues during migration:

- Check the [Client Tools documentation](/docs/client-sdk/client-tools) for the new features
- Review the [HTTP Transport](/docs/client-sdk/http-transport) and [Server SDK Sessions](/docs/server-sdk/sessions) docs for updated APIs
- [Open an issue](https://github.com/octavus-ai/agent-sdk/issues) on GitHub if you find a bug
