---
title: "Vercel AI SDK"
description: "Use Humanlayer with Vercel AI SDK"
icon: "bolt"
---

## Overview

The [Vercel AI SDK](https://sdk.vercel.ai/docs) enables streaming AI responses in Next.js applications. HumanLayer adds human oversight to your AI features.

## Installation

```bash
npm install @humanlayer/sdk ai
```

## Basic Example

Here's a simple example showing how to use HumanLayer with the Vercel AI SDK:

```typescript
import { tool, generateText } from "ai";
import { createOpenAI } from "@ai-sdk/openai";
import { humanlayer } from "humanlayer-vercel-ai-sdk";
import { z } from "zod";

const hl = humanlayer({
  verbose: true,
});

// Simple math operations
const add = tool({
  parameters: z.object({
    a: z.number(),
    b: z.number(),
  }),
  execute: async (args) => {
    return args.a + args.b;
  },
});

// Multiply requires approval
const multiplyTool = tool({
  parameters: z.object({
    a: z.number(),
    b: z.number(),
  }),
  execute: async (args) => {
    return args.a * args.b;
  },
});

// Wrap multiply with approval requirement
const multiply = hl.requireApproval({ multiplyTool });

// Human consultation tool
const contactHuman = hl.humanAsTool();

const openai = createOpenAI({
  compatibility: "strict",
});

// Generate text with tool access
const { text, steps } = await generateText({
  model: openai("gpt-4"),
  tools: {
    add,
    multiply,
    contactHuman,
  },
  maxSteps: 5,
  prompt: "multiply 2 and 5, then add 32 to the result",
});
```

## Complete Next.js Example

### API Route (app/api/chat/route.ts)

```typescript
import { humanlayer } from "@humanlayer/sdk";
import { StreamingTextResponse, LangChainStream } from "ai";
import { ChatOpenAI } from "langchain/chat_models/openai";
import { AIMessage, HumanMessage, SystemMessage } from "langchain/schema";

// Initialize with contact channel
const hl = humanlayer({
  runId: "support-chat",
  contactChannel: {
    slack: {
      channelOrUserId: "C123456",
      contextAboutChannelOrUser: "the support team",
    },
  },
});

// Functions requiring approval
const updateSubscription = hl.requireApproval(
  async (userId: string, plan: string) => {
    // Subscription logic here
    return `Updated ${userId} to ${plan}`;
  },
);

const issueCredit = hl.requireApproval(
  async (userId: string, amount: number) => {
    // Credit logic here
    return `Issued $${amount} credit to ${userId}`;
  },
);

// Support team consultation
const askSupport = hl.humanAsTool({
  responseOptions: [
    {
      name: "approve",
      title: "Approve Request",
      description: "Grant the customer's request",
    },
    {
      name: "deny",
      title: "Deny Request",
      description: "Deny with explanation",
    },
    {
      name: "escalate",
      title: "Escalate",
      description: "Escalate to management",
    },
  ],
});

export async function POST(req: Request) {
  const { messages, userId } = await req.json();
  const { stream, handlers } = LangChainStream();

  const llm = new ChatOpenAI({
    streaming: true,
    callbacks: [handlers],
  });

  llm.call(
    [
      new SystemMessage("You are a helpful customer support assistant."),
      ...messages.map((m: any) =>
        m.role === "user"
          ? new HumanMessage(m.content)
          : new AIMessage(m.content),
      ),
    ],
    {
      tools: [
        {
          name: "updateSubscription",
          description: "Update a user's subscription plan",
          parameters: {
            type: "object",
            properties: {
              userId: { type: "string" },
              plan: { type: "string" },
            },
            required: ["userId", "plan"],
          },
        },
        {
          name: "issueCredit",
          description: "Issue account credit to user",
          parameters: {
            type: "object",
            properties: {
              userId: { type: "string" },
              amount: { type: "number" },
            },
            required: ["userId", "amount"],
          },
        },
        {
          name: "askSupport",
          description: "Ask support team for help",
          parameters: {
            type: "object",
            properties: {
              message: { type: "string" },
            },
            required: ["message"],
          },
        },
      ],
    },
  );

  return new StreamingTextResponse(stream);
}
```

### Client Component (app/page.tsx)

```typescript
"use client";

import { useChat } from "ai/react";

export default function Chat() {
  const { messages, input, handleInputChange, handleSubmit } = useChat();

  return (
    <div className="p-4 max-w-lg mx-auto">
      <div className="space-y-4">
        {messages.map(m => (
          <div key={m.id} className={`p-4 rounded-lg ${
            m.role === "user" ? "bg-blue-100" : "bg-gray-100"
          }`}>
            <p className="font-semibold">{m.role}</p>
            <p>{m.content}</p>
          </div>
        ))}
      </div>

      <form onSubmit={handleSubmit} className="mt-4">
        <input
          value={input}
          onChange={handleInputChange}
          placeholder="How can I help?"
          className="w-full p-2 border rounded"
        />
        <button
          type="submit"
          className="mt-2 px-4 py-2 bg-blue-500 text-white rounded"
        >
          Send
        </button>
      </form>
    </div>
  );
}
```

## Key Features

1. **Streaming Responses**

   - Real-time AI output
   - Responsive UI
   - Error handling

2. **Human Oversight**

   - Approval workflows
   - Support team consultation
   - Structured responses

3. **Type Safety**
   - Full TypeScript support
   - Validated parameters
   - Error boundaries

## Configuration

```bash
# .env.local
OPENAI_API_KEY=your-openai-key
HUMANLAYER_API_KEY=your-humanlayer-key
```

## Next Steps

- [Configure contact channels](/channels/introduction)
- [Customize response options](/core/customize-response-options)
- [See complete example](https://github.com/humanlayer/humanlayer/tree/main/examples/ts_vercel_ai_sdk)
