Example Agents
Complete agent implementations to learn from and build upon.
1. Meeting Scheduler Agent
Finds available time slots and schedules meetings with team members.
manifest.json
{
"id": "com.example.meeting-scheduler",
"name": "Meeting Scheduler",
"version": "1.0.0",
"description": "Schedule meetings with automatic availability detection",
"capabilities": [
"calendar.read",
"calendar.write",
"contacts.read",
"messages.send"
]
}agent.js
export async function handleIntent({ intent, context, tools }) {
if (intent.action === "schedule_meeting") {
const { title, attendees, duration } = intent.parameters;
// Step 1: Search for contacts
const contacts = await Promise.all(
attendees.map(name => tools.contacts.search({ query: name }))
);
const emails = contacts.map(c => c[0]?.emails[0]).filter(Boolean);
// Step 2: Find available time
const now = new Date();
const weekFromNow = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000);
const events = await tools.calendar.listEvents({
start: now.toISOString(),
end: weekFromNow.toISOString()
});
// Find first available 1-hour slot
let availableSlot = findAvailableSlot(events, duration || 60);
// Step 3: Request approval
const approval = await tools.approval.request({
action: "create_calendar_event",
title: `Schedule "${title}"`,
description: `Create meeting for ${formatDate(availableSlot.start)}`,
details: {
title: title,
start: availableSlot.start,
end: availableSlot.end,
attendees: emails
}
});
if (!approval.approved) {
return {
type: "error",
title: "Meeting not scheduled",
description: "You declined the approval."
};
}
// Step 4: Create event
const event = await tools.calendar.createEvent({
title: title,
start: availableSlot.start,
end: availableSlot.end,
attendees: emails
});
// Step 5: Send notification
await tools.messages.send({
to: emails,
subject: `Meeting Scheduled: ${title}`,
body: `You've been invited to "${title}" on ${formatDate(availableSlot.start)}`
});
return {
type: "result",
title: "✅ Meeting scheduled",
description: `Created "${title}" for ${formatDate(availableSlot.start)}`,
action: {
label: "View Event",
url: `metaos://calendar/event/${event.id}`
}
};
}
}
function findAvailableSlot(events, durationMinutes) {
// Simple algorithm: find first gap >= duration
const now = new Date();
now.setHours(9, 0, 0, 0); // Start at 9 AM
for (let day = 0; day < 7; day++) {
for (let hour = 9; hour < 17; hour++) {
const start = new Date(now);
start.setDate(start.getDate() + day);
start.setHours(hour, 0, 0, 0);
const end = new Date(start);
end.setMinutes(end.getMinutes() + durationMinutes);
const hasConflict = events.some(event =>
(new Date(event.start) < end && new Date(event.end) > start)
);
if (!hasConflict) {
return {
start: start.toISOString(),
end: end.toISOString()
};
}
}
}
throw new Error("No available slots found");
}
function formatDate(isoString) {
const date = new Date(isoString);
return date.toLocaleDateString('en-US', {
weekday: 'long',
month: 'long',
day: 'numeric',
hour: 'numeric',
minute: '2-digit'
});
}2. Travel Planner Agent
Saves trip details, itineraries, and packing lists.
manifest.json
{
"id": "com.example.travel-planner",
"name": "Travel Planner",
"version": "1.0.0",
"description": "Organize trips, itineraries, and packing lists",
"capabilities": [
"storage.read",
"storage.write",
"calendar.read",
"calendar.write"
],
"scopes": {
"storage.read": ["metaos://notes/travel/*"],
"storage.write": ["metaos://notes/travel/*"]
}
}agent.js
export async function handleIntent({ intent, context, tools }) {
// Create a trip
if (intent.action === "create_trip") {
const { destination, startDate, endDate } = intent.parameters;
const tripData = {
destination,
startDate,
endDate,
createdAt: new Date().toISOString(),
itinerary: [],
packing: []
};
await tools.storage.write({
path: `metaos://notes/travel/${destination}.json`,
content: JSON.stringify(tripData, null, 2),
contentType: "application/json"
});
// Add to calendar
await tools.calendar.createEvent({
title: `Trip to ${destination}`,
start: startDate,
end: endDate,
description: "Travel dates"
});
return {
type: "result",
title: `✅ Trip to ${destination} created`,
description: `Saved trip plan and added to calendar`
};
}
// List all trips
if (intent.action === "list_trips") {
const files = await tools.storage.list({
path: "metaos://notes/travel/"
});
const trips = await Promise.all(
files.map(async (file) => {
const content = await tools.storage.read({ path: file.path });
return JSON.parse(content.content);
})
);
return {
type: "summary",
title: "Your Trips",
items: trips.map(trip => ({
title: trip.destination,
subtitle: `${formatDate(trip.startDate)} - ${formatDate(trip.endDate)}`,
icon: "✈️"
}))
};
}
// Add to packing list
if (intent.action === "add_to_packing_list") {
const { destination, items } = intent.parameters;
const file = await tools.storage.read({
path: `metaos://notes/travel/${destination}.json`
});
const tripData = JSON.parse(file.content);
tripData.packing.push(...items);
await tools.storage.write({
path: `metaos://notes/travel/${destination}.json`,
content: JSON.stringify(tripData, null, 2),
contentType: "application/json"
});
return {
type: "result",
title: "✅ Packing list updated",
description: `Added ${items.length} items for ${destination}`
};
}
}
function formatDate(isoString) {
return new Date(isoString).toLocaleDateString('en-US', {
month: 'short',
day: 'numeric',
year: 'numeric'
});
}3. Note Taker Agent
Simple note-taking with search and organization.
manifest.json
{
"id": "com.example.note-taker",
"name": "Note Taker",
"version": "1.0.0",
"description": "Simple markdown note-taking agent",
"capabilities": [
"storage.read",
"storage.write"
],
"scopes": {
"storage.read": ["metaos://notes/*"],
"storage.write": ["metaos://notes/*"]
}
}agent.js
export async function handleIntent({ intent, context, tools }) {
// Save a note
if (intent.action === "save_note") {
const { title, content } = intent.parameters;
await tools.storage.write({
path: `metaos://notes/${title}.md`,
content: content,
contentType: "text/markdown"
});
return {
type: "result",
title: "✅ Note saved",
description: `Saved "${title}"`,
action: {
label: "View Note",
url: `metaos://storage/notes/${title}.md`
}
};
}
// List all notes
if (intent.action === "list_notes") {
const files = await tools.storage.list({
path: "metaos://notes/"
});
return {
type: "summary",
title: "Your Notes",
items: files.map(file => ({
title: file.name.replace('.md', ''),
subtitle: formatDate(file.lastModified),
icon: "📝",
action: {
label: "Open",
url: `metaos://storage/${file.path}`
}
})),
footer: `${files.length} notes`
};
}
// Search notes
if (intent.action === "search_notes") {
const { query } = intent.parameters;
const files = await tools.storage.list({
path: "metaos://notes/"
});
const results = [];
for (const file of files) {
const content = await tools.storage.read({ path: file.path });
if (content.content.toLowerCase().includes(query.toLowerCase())) {
results.push({
title: file.name.replace('.md', ''),
subtitle: extractSnippet(content.content, query),
icon: "🔍"
});
}
}
return {
type: "summary",
title: `Search results for "${query}"`,
items: results,
footer: `${results.length} matches`
};
}
}
function formatDate(isoString) {
const date = new Date(isoString);
const now = new Date();
const diffMs = now - date;
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
if (diffDays === 0) return "Today";
if (diffDays === 1) return "Yesterday";
if (diffDays < 7) return `${diffDays} days ago`;
return date.toLocaleDateString();
}
function extractSnippet(content, query) {
const lines = content.split('\n');
for (const line of lines) {
if (line.toLowerCase().includes(query.toLowerCase())) {
return line.slice(0, 100) + (line.length > 100 ? '...' : '');
}
}
return content.slice(0, 100) + '...';
}