Build/Routes

Handling Emails

Process incoming emails with router.email()

Handle incoming emails sent to a specific address. Email addresses are defined in code and automatically provisioned when deployed.

Routes Location

All routes live in src/api/. Import agents you need and call them directly.

Basic Example

import { createRouter } from '@agentuity/runtime';
import supportAgent from '@agent/support';
 
const router = createRouter();
 
router.email('support@example.com', async (email, c) => {
  c.var.logger.info('Email received', {
    from: email.fromEmail(),
    subject: email.subject(),
  });
 
  const response = await supportAgent.run({
    sender: email.fromEmail() || 'unknown',
    subject: email.subject() || 'No Subject',
    body: email.text() || '',
  });
 
  return c.text('Email processed');
});
 
export default router;

With Middleware

Email routes support middleware for authentication or preprocessing:

import { createRouter } from '@agentuity/runtime';
import { createMiddleware } from 'hono/factory';
 
const router = createRouter();
 
const logMiddleware = createMiddleware(async (c, next) => {
  c.var.logger.info('Email route accessed');
  await next();
});
 
router.email('support@example.com', logMiddleware, async (email, c) => {
  // Middleware runs before this handler
  return c.text('Processed');
});
 
export default router;

Email Object API

The email parameter provides methods to access email content:

// Sender information
email.fromEmail();    // "sender@example.com" or null
email.fromName();     // "John Doe" or null
 
// Recipients
email.to();           // All recipients (comma-separated)
email.toEmail();      // First recipient email
email.toName();       // First recipient name
 
// Content
email.subject();      // "Re: Your inquiry" or null
email.text();         // Plain text body or null
email.html();         // HTML body or null
 
// Attachments
email.attachments();  // Array of { filename, contentType }
 
// Metadata
email.date();         // Date object or null
email.messageId();    // Message-ID header or null
email.headers();      // Full Headers object

Accessing Attachments

router.email('uploads@example.com', async (email, c) => {
  const attachments = email.attachments();
 
  for (const attachment of attachments) {
    c.var.logger.info('Attachment received', {
      filename: attachment.filename,
      contentType: attachment.contentType,
    });
  }
 
  return c.text(`Received ${attachments.length} attachments`);
});

Full Example

A support inbox that categorizes and routes emails:

import { createRouter } from '@agentuity/runtime';
import supportRouter from '@agent/support-router';
 
const router = createRouter();
 
router.email('support@myapp.com', async (email, c) => {
  const from = email.fromEmail() || 'unknown';
  const subject = email.subject() || 'No Subject';
  const body = email.text() || email.html() || '';
  const attachmentCount = email.attachments().length;
 
  try {
    // Classify and process the email
    const result = await supportRouter.run({
      from,
      subject,
      body,
      hasAttachments: attachmentCount > 0,
    });
 
    // Store for audit trail
    await c.var.kv.set('emails', `${Date.now()}-${from}`, {
      from,
      subject,
      processedAt: new Date().toISOString(),
      category: result.category,
    });
 
    c.var.logger.info('Email processed', { from, category: result.category });
    return c.text('OK');
  } catch (error) {
    c.var.logger.error('Email processing failed', { error, from });
    return c.text('Error', 500);
  }
});
 
export default router;

Email Replies

The email.sendReply() method for sending replies is coming soon. Currently, you can process emails and trigger notifications through other channels (Slack, SMS, etc.) or store responses for manual follow-up.

Standalone Usage

Email handlers work without agents. This example archives incoming emails to storage:

import { createRouter } from '@agentuity/runtime';
 
const router = createRouter();
 
router.email('archive@example.com', async (email, c) => {
  const key = `${Date.now()}-${email.fromEmail()}`;
  await c.var.kv.set('archive', key, {
    from: email.fromEmail(),
    subject: email.subject(),
    body: email.text(),
    date: email.date()?.toISOString(),
  });
  c.var.logger.info('Email archived', { key });
  return c.text('OK');
});
 
export default router;

Next Steps

Need Help?

Join our DiscordCommunity for assistance or just to hang with other humans building agents.

Send us an email at hi@agentuity.com if you'd like to get in touch.

Please Follow us on

If you haven't already, please Signup for your free account now and start building your first agent!