Overview
The Vercel AI SDK provides a TypeScript toolkit for building AI applications. ACN integrates as custom tools that your AI can call during conversations.Define ACN Tools
Copy
Ask AI
import { tool } from "ai";
import { z } from "zod";
const ACN_BASE_URL = "https://api.acn.exchange";
const acnDiscover = tool({
description: "Search ACN marketplace for services matching a natural language query",
parameters: z.object({
query: z.string().describe("What capability do you need?"),
}),
execute: async ({ query }) => {
const res = await fetch(`${ACN_BASE_URL}/v1/discover`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ query }),
});
return res.json();
},
});
const acnExecute = tool({
description: "Execute a service discovered on ACN. Use provider_id and endpoint_slug from discovery results.",
parameters: z.object({
provider_id: z.string().describe("Provider ID"),
endpoint_slug: z.string().describe("Endpoint slug"),
payload: z.record(z.any()).describe("Request payload matching the endpoint schema"),
}),
execute: async ({ provider_id, endpoint_slug, payload }) => {
const res = await fetch(
`${ACN_BASE_URL}/v1/execute/${provider_id}/${endpoint_slug}`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.ACN_API_KEY}`,
},
body: JSON.stringify(payload),
}
);
return res.json();
},
});
const acnBalance = tool({
description: "Check your current ACN balance in USDC",
parameters: z.object({}),
execute: async () => {
const res = await fetch(`${ACN_BASE_URL}/v1/wallet/balance`, {
headers: { Authorization: `Bearer ${process.env.ACN_API_KEY}` },
});
return res.json();
},
});
Use in a Route Handler
Copy
Ask AI
import { streamText } from "ai";
import { anthropic } from "@ai-sdk/anthropic";
export async function POST(req: Request) {
const { messages } = await req.json();
const result = streamText({
model: anthropic("claude-sonnet-4-20250514"),
messages,
tools: {
acn_discover: acnDiscover,
acn_execute: acnExecute,
acn_balance: acnBalance,
},
system: "You are an assistant with access to ACN services. "
+ "Use acn_discover to find services, then acn_execute to call them. "
+ "Always show the user the cost before executing.",
});
return result.toDataStreamResponse();
}
Use with generateText
For non-streaming, server-side use:
Copy
Ask AI
import { generateText } from "ai";
import { anthropic } from "@ai-sdk/anthropic";
const { text } = await generateText({
model: anthropic("claude-sonnet-4-20250514"),
tools: {
acn_discover: acnDiscover,
acn_execute: acnExecute,
},
maxSteps: 5,
prompt: "Find the current Bitcoin price using ACN",
});
console.log(text);
With Next.js
Copy
Ask AI
// app/api/chat/route.ts
import { streamText } from "ai";
import { anthropic } from "@ai-sdk/anthropic";
export const maxDuration = 30;
export async function POST(req: Request) {
const { messages } = await req.json();
const result = streamText({
model: anthropic("claude-sonnet-4-20250514"),
messages,
tools: {
acn_discover: acnDiscover,
acn_execute: acnExecute,
acn_balance: acnBalance,
},
});
return result.toDataStreamResponse();
}
useChat hook on the frontend handles the streaming response automatically:
Copy
Ask AI
"use client";
import { useChat } from "@ai-sdk/react";
export default function Chat() {
const { messages, input, handleInputChange, handleSubmit } = useChat();
return (
<div>
{messages.map((m) => (
<div key={m.id}>{m.role}: {m.content}</div>
))}
<form onSubmit={handleSubmit}>
<input value={input} onChange={handleInputChange} />
</form>
</div>
);
}