Custom Tools

Scheduling

Schedule code tools to run automatically at specific hours. Get results via email summaries with optional custom formatting.


Setup

Add a schedule to any active code tool:

tool(action="schedule",
  tool_id="tool_abc123",
  schedule={
    enabled: true,
    hours: [9],
    timezone: "America/New_York"
  })

This runs the tool every day at 9:00 AM Eastern.


Schedule Properties

PropertyTypeDefaultDescription
enabledbooleanTurn scheduling on/off without deleting the schedule
hoursnumber[][9]Hours to run (0-23), max 4 per day
timezonestring"UTC"IANA timezone string (e.g., "America/New_York", "Europe/London")
email_summarybooleanfalseSend results via email
email_addressstringOverride the default recipient email
email_recipientsstringComma-separated additional recipient emails
argsobjectFixed arguments passed to the tool on every run

Example: Multiple Hours with Args

tool(action="schedule",
  tool_id="tool_abc123",
  schedule={
    enabled: true,
    hours: [9, 17],
    timezone: "America/Chicago",
    email_summary: true,
    args: { portfolio: "main", include_news: true }
  })

Email Summaries

Enable email summaries to receive tool results in your inbox:

tool(action="schedule",
  tool_id="tool_abc123",
  schedule={
    enabled: true,
    hours: [8],
    email_summary: true
  })

By default, emails go to the email address on your Kyew account. Override with email_address or add additional recipients with email_recipients:

tool(action="schedule",
  tool_id="tool_abc123",
  schedule={
    enabled: true,
    hours: [8],
    email_summary: true,
    email_address: "[email protected]",
    email_recipients: "[email protected], [email protected]"
  })

Email Customization

By default, scheduled emails contain the raw JSON output from your tool. To customize the email content, return a _email property from your tool:

export default {
  async fetch(request) {
    const results = await getResults();

    return Response.json({
      data: results,
      _email: {
        html: "<h2>Daily Report</h2><table><tr><th>Metric</th><th>Value</th></tr>...</table>",
        subject: "Daily Report — Mar 14",
        text: "Plain text fallback for email clients that don't render HTML"
      }
    });
  }
};
FieldRequiredDescription
_email.htmlNoHTML content that replaces the raw JSON in the email body
_email.subjectNoCustom email subject line (overrides default)
_email.textNoPlain text fallback

The email header with status, execution time, and duration always renders regardless of customization.


Management

List All Schedules

tool(action="schedule", schedule_action="list")

View Execution History

tool(action="schedule", tool_id="tool_abc123", schedule_action="history")

Disable a Schedule

Disable without deleting — preserves the schedule config:

tool(action="schedule",
  tool_id="tool_abc123",
  schedule={ enabled: false })

Delete a Schedule

tool(action="schedule", tool_id="tool_abc123", schedule_action="delete")

Constraints

  • Tool type: Only code tools can be scheduled
  • Tool status: The tool must be active
  • Max frequency: Up to 4 hours per day
  • Timeout: 5-minute execution limit per scheduled run
  • Auto-pause: Schedules pause automatically after 3 consecutive failures. Fix the issue and re-enable to resume.

Example: Daily Portfolio Summary

A code tool that runs at market open and close, emails a formatted summary:

tool(action="create",
  name="portfolio_summary",
  description="Generate portfolio performance summary",
  tool_type="code",
  code_config={
    code: `
import { query, exec } from "./db.mjs";

export default {
  async fetch(request) {
    const { portfolio } = await request.json();

    const holdings = await query(
      "SELECT symbol, shares, cost_basis FROM holdings WHERE portfolio = ?",
      portfolio || "main"
    );

    // Build summary
    const rows = holdings.rows.map(h =>
      \`<tr><td>\${h.symbol}</td><td>\${h.shares}</td><td>$\${h.cost_basis.toFixed(2)}</td></tr>\`
    ).join("");

    return Response.json({
      holdings: holdings.rows,
      _email: {
        subject: \`Portfolio Summary — \${new Date().toLocaleDateString()}\`,
        html: \`
          <h2>Portfolio Summary</h2>
          <table border="1" cellpadding="8">
            <tr><th>Symbol</th><th>Shares</th><th>Cost Basis</th></tr>
            \${rows}
          </table>
          <p>\${holdings.rows.length} holdings total</p>\`
      }
    });
  }
}`,
    runtime: "javascript",
    allowed_domains: []
  })

Then schedule it:

tool(action="schedule",
  tool_id="tool_abc123",
  schedule={
    enabled: true,
    hours: [9, 16],
    timezone: "America/New_York",
    email_summary: true,
    args: { portfolio: "main" }
  })

API Reference

For the full technical reference including all parameters and options, see tool Tool Reference. For a step-by-step walkthrough, see Scheduled Report Guide.

Previous
Connections