Custom Tools

Email Triggers

Email triggers let any code tool receive and process inbound email. Forward a receipt, send a report, or pipe alerts — the tool processes the email body and attachments automatically.


Enable Email for a Tool

tool(action="email_enable", tool_id="tool_abc123")

This gives the tool a unique email address like [email protected]. Any email sent to this address will trigger the tool.


How It Works

  1. Email arrives at the tool's address
  2. Kyew parses the email (sender, subject, body, attachments)
  3. Your code tool's fetch handler receives the parsed email as JSON input
  4. The tool processes it and returns a result

Input Format

Your code tool receives:

{
  "from": "[email protected]",
  "to": "[email protected]",
  "subject": "March expense report",
  "text": "Plain text body",
  "html": "<p>HTML body</p>",
  "attachments": [
    {
      "filename": "report.csv",
      "content_type": "text/csv",
      "size": 1234,
      "content_base64": "..."
    }
  ]
}

Sender Allowlists

By default, only the tool owner's email is allowed. Add trusted senders:

tool(action="email_allowlist_add", tool_id="tool_abc123", email="[email protected]")

Manage the Allowlist

tool(action="email_allowlist_list", tool_id="tool_abc123")
tool(action="email_allowlist_remove", tool_id="tool_abc123", email="[email protected]")

Allow All Org Members

For team tools, allow anyone in your organization:

tool(action="email_allow_org", tool_id="tool_abc123", allow_org_members=true)

View Email History

See recent emails processed by a tool:

tool(action="email_history", tool_id="tool_abc123")

Check Email Config

See a tool's email address and current settings:

tool(action="email_config", tool_id="tool_abc123")

Disable Email

tool(action="email_disable", tool_id="tool_abc123")

Example: Expense Tracker

A tool that processes forwarded receipts:

tool(action="create",
  name="receipt_processor",
  description="Process forwarded receipt emails and log expenses",
  tool_type="code",
  input_schema={
    type: "object",
    properties: {
      from: { type: "string" },
      subject: { type: "string" },
      text: { type: "string" }
    }
  },
  code_config={
    code: `
import { exec, query } from "./db.mjs";

export default {
  async fetch(request) {
    const { from, subject, text } = await request.json();

    await exec(\`
      CREATE TABLE IF NOT EXISTS expenses (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        sender TEXT, subject TEXT, body TEXT,
        created_at TEXT DEFAULT (datetime('now'))
      )
    \`);

    await exec(
      "INSERT INTO expenses (sender, subject, body) VALUES (?, ?, ?)",
      from, subject, text
    );

    const count = await query("SELECT COUNT(*) as total FROM expenses");
    return Response.json({
      logged: true,
      total_expenses: count.rows[0].total
    });
  }
}`,
    runtime: "javascript",
    allowed_domains: []
  })

Then enable email:

tool(action="email_enable", tool_id="tool_abc123")
tool(action="email_allowlist_add", tool_id="tool_abc123", email="[email protected]")

Combining with Scheduling

Email triggers and scheduling work together. A tool can receive emails throughout the day and send a daily digest on a schedule. See Scheduling.

Previous
Scheduling