Triggers

Trigger config is persisted per function/kind and controls how runtime invocation is initiated.

Step-by-Step Guide

1.Trigger schema

Each function keeps at most one row per trigger kind (fnId + kind).

  • http: { requireAuth: boolean } (defaults to false for new functions)
  • cron: { schedule: string, timezone?: string }
  • email: { address: string, allowlist?: string[] }address is platform-generated as {fn}-{workspace}-{random}@… and can be regenerated at any time
  • mcp: { toolName: string, description: string }

2.HTTP trigger

HTTP entrypoint is runtime route /run/:orgSlug/:fnSlug. HTTP requests invoke your exported main handler.

  • HTTP is created automatically for new functions.
  • main(payload, request)payload is the parsed JSON body (POST/PUT) or the query params (GET). Return a plain value (JSON-serialized) or a web Response.
  • When requireAuth is true, send Authorization: Bearer <workspace API token> (see Settings → Tokens).
  • Nested calls from executeFunction send x-hostfunc-parent-exec and skip the API token when the parent execution is valid.
typescript
export async function main(payload, request) {  // payload = JSON body (POST/PUT) or query params (GET)  return { hello: payload.name ?? "world" };  // …or return a Response directly:  // return new Response("hi", { status: 200 });}

3.Cron trigger

Cron worker fetches due jobs from control plane and invokes runtime with cron trigger metadata. Cron runs invoke your exported main — there is no separate cron handler.

  • Due/ack flow is handled by internal cron endpoints.
  • Runtime invokes main(payload) with payload.hostfuncTriggerKind === "cron" — branch on it to tell a scheduled run apart from an HTTP request.
typescript
export async function main(payload) {  if (payload.hostfuncTriggerKind === "cron") {    // scheduled run — do the periodic work    return { ranAt: new Date().toISOString() };  }  // normal HTTP request  return { ok: true };}

4.Email trigger

Every function can have one generated inbound address. Mail sent to it invokes your exported email(data) handler with the payload shape below.

  • Address format: {function-slug}-{workspace-slug}-{random}@hostfunc.io (slugs truncated to 20 chars, 8-char random suffix).
  • If the function has an active custom domain with verified inbound email, new addresses are generated on that domain instead — see Custom Domains → Receive email on your domain.
  • Regenerating replaces the address in place: the old address stops matching immediately.
  • Optional sender allowlist — empty accepts mail from anyone; otherwise only listed senders trigger the function (case-insensitive).
  • Your function **must export** email — it's a separate handler from main. An email trigger that hits a function without it fails with function must export 'email' for email triggers.
  • email(data, request); data.email includes to, from, rawSize, timestamp (ISO 8601), and optional subject / body. A function can export both main (HTTP/cron) and email.
  • Local development is fully mocked: the dispatch payload is logged to the dev server console, and a dev-only "Send test email" button on the triggers page exercises the whole path without DNS or a mail provider.
typescript
export async function email(data: {  email: {    from: string;    to: string;    rawSize: number;    timestamp: string;    subject?: string;    body?: string;  };}) {  return { received: data.email.subject ?? "(no subject)" };}

5.MCP-related triggering

MCP tool calls execute through /api/mcp handlers and are audited.

  • MCP tools include function execution operations.
  • MCP trigger config exists in trigger model for function-level metadata.

Related Documentation