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) + '...';
}

📦 Download Examples

All example agents are available in our GitHub repository:

View on GitHub →