@mondaydotcomorg/atp-vercel-sdk
v0.19.10
Published
Vercel AI SDK integration for Agent Tool Protocol
Maintainers
Readme
@mondaydotcomorg/atp-vercel-ai-sdk
Vercel AI SDK integration for Agent Tool Protocol with production-ready features.
Overview
This package integrates ATP with Vercel AI SDK, enabling agents to generate and execute ATP code as tools. Includes support for human-in-the-loop approvals, LLM sampling, and embeddings.
Installation
npm install @mondaydotcomorg/atp-vercel-ai-sdk ai @ai-sdk/openaiArchitecture
graph TB
Agent[Vercel AI SDK Agent] --> Tools[ATP Tools]
Tools --> Client[VercelAIATPClient]
Client --> Server[ATP Server]
Server --> Runtime[Runtime APIs]
Runtime --> LLM[atp.llm.*]
Runtime --> Embed[atp.embedding.*]
Runtime --> Approval[atp.approval.*]
LLM --> Callback[Client LLM Callback]
Embed --> EmbedCallback[Client Embedding Callback]
Approval --> Handler[Approval Handler]Features
- 🤖 Vercel AI SDK Tools - Use ATP as tools with
generateTextandstreamText - 🔄 Multi-Step Execution - Full integration with Vercel AI SDK's
maxStepsparameter - 🧠 LLM Sampling -
atp.llm.call()routes to your Vercel AI SDK model - 🔍 Embedding Support -
atp.embedding.*routes to your embeddings model - ✅ Approval Workflows - Human-in-the-loop via async callbacks
- 📡 Streaming Support - Works with both
generateTextandstreamText - 📝 TypeScript - Full type safety
Quick Start
Basic Agent with Tools
import { createATPTools } from '@mondaydotcomorg/atp-vercel-ai-sdk';
import { openai } from '@ai-sdk/openai';
import { generateText } from 'ai';
const model = openai('gpt-4o');
const { tools } = await createATPTools({
serverUrl: 'http://localhost:3333',
headers: { Authorization: 'Bearer your-api-key' },
model,
approvalHandler: async (message, context) => {
console.log('Approval needed:', message);
return true;
},
});
const result = await generateText({
model,
system: 'You can execute TypeScript code using ATP tools',
prompt: 'Use ATP to call an LLM and get a creative product idea',
tools,
maxSteps: 5,
});With Streaming
import { createATPTools } from '@mondaydotcomorg/atp-vercel-ai-sdk';
import { openai } from '@ai-sdk/openai';
import { streamText } from 'ai';
const model = openai('gpt-4o');
const { tools } = await createATPTools({
serverUrl: 'http://localhost:3333',
headers: { Authorization: 'Bearer your-api-key' },
model,
approvalHandler: async () => true,
});
const result = await streamText({
model,
prompt: 'Use ATP to generate code',
tools,
maxSteps: 5,
});
for await (const chunk of result.textStream) {
process.stdout.write(chunk);
}With Embeddings
import { createATPTools } from '@mondaydotcomorg/atp-vercel-ai-sdk';
import { openai } from '@ai-sdk/openai';
import { embed } from 'ai';
const model = openai('gpt-4o');
const embeddings = {
embed: async (text: string) => {
const result = await embed({
model: openai.embedding('text-embedding-3-small'),
value: text,
});
return result.embedding;
},
};
const { tools } = await createATPTools({
serverUrl: 'http://localhost:3333',
headers: { Authorization: 'Bearer your-api-key' },
model,
embeddings,
});
// Agent can now use atp.embedding.embed() in codeHow It Works
ATP Runtime in Vercel AI SDK
When agents use ATP tools, they can generate TypeScript code using ATP's runtime APIs:
// Agent generates this code:
const idea = await atp.llm.call({
prompt: 'Generate a product idea',
});
// Store embedding for semantic search
const embeddingId = await atp.embedding.embed(idea);
// Request approval
const approval = await atp.approval.request(`Launch product: ${idea}?`, { idea });
if (approval.approved) {
return await atp.llm.call({
prompt: `Create marketing copy for: ${idea}`,
});
}LLM Sampling
atp.llm.call() routes to your Vercel AI SDK model:
- Uses the same model as your agent
- Fresh context for sub-reasoning
- Supports
call(),extract(),classify()
// In ATP code:
const analysis = await atp.llm.call({
prompt: 'Analyze this data: ' + JSON.stringify(data),
temperature: 0.7,
});
// Structured extraction
const structured = await atp.llm.extract({
prompt: 'Extract key information',
schema: z.object({
name: z.string(),
age: z.number(),
}),
});Approval Mechanism
When ATP code calls atp.approval.request(), your async handler is invoked:
const { tools } = await createATPTools({
serverUrl: 'http://localhost:3333',
headers: { Authorization: 'Bearer your-api-key' },
model,
approvalHandler: async (message, context) => {
// Option 1: CLI prompt
return confirm(message);
// Option 2: Webhook notification
await sendSlackNotification(message);
return await waitForWebhookResponse();
// Option 3: Database queue
await db.approvals.create({ message, context });
return await pollForApproval();
},
});API Reference
createATPTools()
async function createATPTools(options: CreateATPToolsOptions): Promise<ATPToolsResult>;Options:
interface CreateATPToolsOptions {
serverUrl: string;
headers?: Record<string, string>;
model: any;
embeddings?: EmbeddingProvider;
approvalHandler?: ApprovalHandler;
defaultExecutionConfig?: Partial<ExecutionConfig>;
hooks?: ClientHooks;
}Returns:
interface ATPToolsResult {
client: VercelAIATPClient;
tools: Record<string, any>;
}VercelAIATPClient
class VercelAIATPClient {
execute(code: string, config?: ExecutionConfig): Promise<ExecutionResult>;
getTypeDefinitions(): string;
getUnderlyingClient(): AgentToolProtocolClient;
}Production Patterns
Webhook-Based Approval
const pendingApprovals = new Map();
const approvalHandler = async (message: string, context?: any) => {
const approvalId = generateId();
await db.approvals.create({
id: approvalId,
message,
context,
status: 'pending',
});
await sendSlackNotification({
channel: '#approvals',
text: message,
actions: [
{ type: 'button', text: 'Approve', action_id: `approve_${approvalId}` },
{ type: 'button', text: 'Deny', action_id: `deny_${approvalId}` },
],
});
return new Promise((resolve) => {
pendingApprovals.set(approvalId, resolve);
setTimeout(() => {
pendingApprovals.delete(approvalId);
resolve(false);
}, 300000);
});
};
app.post('/slack/actions', async (req, res) => {
const { action_id } = req.body;
const approvalId = action_id.replace(/^(approve|deny)_/, '');
const approved = action_id.startsWith('approve');
const resolve = pendingApprovals.get(approvalId);
if (resolve) {
resolve(approved);
pendingApprovals.delete(approvalId);
}
res.json({ ok: true });
});Multiple Sequential Approvals
// Agent generates ATP code with multiple approvals:
const step1 = await atp.approval.request('Approve step 1?');
if (!step1.approved) return { cancelled: true };
const step2 = await atp.approval.request('Approve step 2?');
if (!step2.approved) return { cancelled: true };
return { success: true };Each atp.approval.request() triggers your approval handler.
Error Handling
const { tools } = await createATPTools({
serverUrl: 'http://localhost:3333',
headers: { Authorization: 'Bearer your-api-key' },
model,
approvalHandler: async (message) => {
try {
return await requestApproval(message);
} catch (error) {
console.error('Approval error:', error);
return false;
}
},
});Comparison with LangChain Integration
| Feature | Vercel AI SDK | LangChain |
| ------------------ | ----------------- | ------------------------ |
| Tool Format | tool() function | Tool classes |
| Agent Type | ToolLoopAgent | ReActAgent |
| Approval Mechanism | Async callbacks | Interrupts + Checkpoints |
| State Persistence | Custom | Built-in (LangGraph) |
| Streaming | Native support | Via LangChain |
| Model Integration | generateText | ChatModel.invoke |
Examples
See examples/vercel-ai-sdk-example/:
agent.ts- Basic ToolLoopAgent with CLI approvalsstreaming.ts- Streaming responses with ATP toolswebhook-approval.ts- Production webhook-based approvals
RAG with Embeddings
import { createATPTools } from '@mondaydotcomorg/atp-vercel-ai-sdk';
import { openai } from '@ai-sdk/openai';
import { embed } from 'ai';
const model = openai('gpt-4o');
const embeddings = {
embed: async (text: string) => {
const result = await embed({
model: openai.embedding('text-embedding-3-small'),
value: text,
});
return result.embedding;
},
};
const { tools } = await createATPTools({
serverUrl: 'http://localhost:3333',
headers: { Authorization: 'Bearer your-api-key' },
model,
embeddings,
});
const result = await generateText({
model,
tools,
maxSteps: 5,
prompt: `Use ATP to:
1. Embed these documents: ["AI is...", "ML is...", "DL is..."]
2. Search for content similar to "neural networks"
3. Use atp.llm.call() to answer based on results`,
});TypeScript Support
import type {
VercelAIATPClient,
VercelAIATPClientOptions,
ApprovalRequest,
ApprovalResponse,
ApprovalHandler,
CreateATPToolsOptions,
ATPToolsResult,
EmbeddingProvider,
} from '@mondaydotcomorg/atp-vercel-ai-sdk';Requirements
- Node.js 18+
- TypeScript 5.0+
ai^4.0.0- Vercel AI SDK provider (e.g.,
@ai-sdk/openai)
License
MIT
