Frameworks
Vercel AI SDK
Frameworks
Vercel AI SDK
Use Humanlayer with Vercel AI SDK
Overview
The Vercel AI SDK enables streaming AI responses in Next.js applications. HumanLayer adds human oversight to your AI features.
Installation
npm install humanlayer ai
Basic Example
Here’s a simple example showing how to use HumanLayer with the Vercel AI SDK:
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)
import { humanlayer } from "humanlayer";
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)
"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
-
Streaming Responses
- Real-time AI output
- Responsive UI
- Error handling
-
Human Oversight
- Approval workflows
- Support team consultation
- Structured responses
-
Type Safety
- Full TypeScript support
- Validated parameters
- Error boundaries
Configuration
# .env.local
OPENAI_API_KEY=your-openai-key
HUMANLAYER_API_KEY=your-humanlayer-key