Direct API connections to communication, social media, and file management services.
Send transactional and marketing emails with React-based templates.
// lib/tools/email.ts
import { Resend } from "resend"
import { z } from "zod"
import { tool } from "ai"
const resend = new Resend(process.env.RESEND_API_KEY)
export const sendEmailTool = tool({
description: "Send an email to one or more recipients",
parameters: z.object({
to: z.array(z.string().email()).describe("Recipient email addresses"),
subject: z.string().describe("Email subject line"),
template: z.enum([
"welcome",
"rent_reminder",
"maintenance_update",
"lease_renewal",
"payment_receipt"
]).describe("Email template to use"),
data: z.record(z.any()).describe("Template variables"),
}),
execute: async ({ to, subject, template, data }) => {
const result = await resend.emails.send({
from: process.env.RESEND_FROM_EMAIL!,
to,
subject,
react: getEmailTemplate(template, data),
})
return {
success: true,
messageId: result.data?.id,
recipients: to.length,
}
}
})
// Example usage in agent
await agent.useTool("sendEmail", {
to: ["tenant@example.com"],
subject: "Rent Reminder - Due in 3 Days",
template: "rent_reminder",
data: {
tenantName: "John Smith",
amount: 2500,
dueDate: "February 1, 2024",
propertyAddress: "123 Main St, Unit 4B"
}
})Send SMS messages for urgent notifications and two-factor authentication.
// lib/tools/sms.ts
import twilio from "twilio"
import { z } from "zod"
import { tool } from "ai"
const client = twilio(
process.env.TWILIO_ACCOUNT_SID,
process.env.TWILIO_AUTH_TOKEN
)
export const sendSmsTool = tool({
description: "Send an SMS message to a phone number",
parameters: z.object({
to: z.string().describe("Recipient phone number in E.164 format"),
message: z.string().max(1600).describe("SMS message content"),
priority: z.enum(["normal", "urgent"]).optional()
.describe("Message priority"),
}),
execute: async ({ to, message, priority }) => {
const result = await client.messages.create({
to,
from: process.env.TWILIO_PHONE_NUMBER,
body: message,
...(priority === "urgent" && {
statusCallback: `${process.env.NEXT_PUBLIC_APP_URL}/api/webhooks/twilio`
})
})
return {
success: true,
messageId: result.sid,
status: result.status,
}
}
})
// Example: Urgent maintenance alert
await agent.useTool("sendSms", {
to: "+64211234567",
message: "URGENT: Water leak detected at 123 Main St. Maintenance team dispatched. ETA: 30 mins.",
priority: "urgent"
})Post to multiple social media platforms simultaneously for property marketing.
// lib/tools/social.ts
import { z } from "zod"
import { tool } from "ai"
export const postToSocialTool = tool({
description: "Post content to social media platforms",
parameters: z.object({
content: z.string().describe("Post content/caption"),
platforms: z.array(z.enum([
"facebook", "instagram", "twitter", "linkedin", "tiktok"
])).describe("Platforms to post to"),
mediaUrls: z.array(z.string().url()).optional()
.describe("Image or video URLs"),
scheduledDate: z.string().datetime().optional()
.describe("ISO date to schedule post"),
}),
execute: async ({ content, platforms, mediaUrls, scheduledDate }) => {
const response = await fetch("https://api.ayrshare.com/api/post", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.AYRSHARE_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
post: content,
platforms,
mediaUrls,
scheduleDate: scheduledDate,
})
})
const result = await response.json()
return {
success: true,
postIds: result.postIds,
platforms: result.platforms,
}
}
})
// Example: Property listing marketing
await agent.useTool("postToSocial", {
content: `š NEW LISTING: Beautiful 3BR apartment in Auckland CBD!
ā
Modern kitchen with stainless appliances
ā
In-unit washer/dryer
ā
Stunning harbor views
ā
Walking distance to transport
$2,500/month | Available Feb 1
š Contact us for a viewing!
#AucklandRentals #PropertyForRent #NewZealandProperty`,
platforms: ["facebook", "instagram", "linkedin"],
mediaUrls: [
"https://storage.example.com/listings/123-main-st/hero.jpg",
"https://storage.example.com/listings/123-main-st/kitchen.jpg",
"https://storage.example.com/listings/123-main-st/view.jpg"
]
})Upload, transform, and optimize images for property listings and marketing.
// lib/tools/images.ts
import { v2 as cloudinary } from "cloudinary"
import { z } from "zod"
import { tool } from "ai"
cloudinary.config({
cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET,
})
export const uploadImageTool = tool({
description: "Upload and optimize an image",
parameters: z.object({
url: z.string().url().describe("Source image URL"),
folder: z.string().describe("Destination folder"),
transformations: z.object({
width: z.number().optional(),
height: z.number().optional(),
crop: z.enum(["fill", "fit", "scale", "thumb"]).optional(),
quality: z.enum(["auto", "auto:low", "auto:best"]).optional(),
}).optional().describe("Image transformations"),
}),
execute: async ({ url, folder, transformations }) => {
const result = await cloudinary.uploader.upload(url, {
folder,
transformation: transformations ? [{
width: transformations.width,
height: transformations.height,
crop: transformations.crop,
quality: transformations.quality,
}] : undefined,
})
return {
success: true,
publicId: result.public_id,
url: result.secure_url,
width: result.width,
height: result.height,
}
}
})
// Example: Process property photos
const photos = await Promise.all(
rawPhotos.map(url =>
agent.useTool("uploadImage", {
url,
folder: `properties/${propertyId}`,
transformations: {
width: 1920,
height: 1080,
crop: "fill",
quality: "auto:best"
}
})
)
)// lib/tools/custom-api.ts
import { z } from "zod"
import { tool } from "ai"
// Template for any REST API integration
export function createApiTool<T extends z.ZodType>({
name,
description,
baseUrl,
endpoint,
method = "POST",
parameters,
headers,
transformResponse,
}: {
name: string
description: string
baseUrl: string
endpoint: string
method?: "GET" | "POST" | "PUT" | "DELETE"
parameters: T
headers?: Record<string, string>
transformResponse?: (data: any) => any
}) {
return tool({
description,
parameters,
execute: async (params) => {
const response = await fetch(`${baseUrl}${endpoint}`, {
method,
headers: {
"Content-Type": "application/json",
...headers,
},
body: method !== "GET" ? JSON.stringify(params) : undefined,
})
if (!response.ok) {
throw new Error(`API error: ${response.status}`)
}
const data = await response.json()
return transformResponse ? transformResponse(data) : data
}
})
}
// Example: Custom property valuation API
export const getPropertyValuationTool = createApiTool({
name: "getPropertyValuation",
description: "Get estimated market value for a property",
baseUrl: "https://api.propertydata.nz",
endpoint: "/v1/valuation",
parameters: z.object({
address: z.string(),
propertyType: z.enum(["house", "apartment", "townhouse"]),
bedrooms: z.number(),
bathrooms: z.number(),
landArea: z.number().optional(),
}),
headers: {
"X-API-Key": process.env.PROPERTY_DATA_API_KEY!,
},
transformResponse: (data) => ({
estimatedValue: data.valuation.median,
confidenceRange: {
low: data.valuation.low,
high: data.valuation.high,
},
comparables: data.comparables.slice(0, 5),
})
})