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[] }—addressis 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)—payloadis the parsed JSON body (POST/PUT) or the query params (GET). Return a plain value (JSON-serialized) or a webResponse.- When
requireAuthis true, sendAuthorization: Bearer <workspace API token>(see Settings → Tokens). - Nested calls from
executeFunctionsendx-hostfunc-parent-execand 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)withpayload.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 frommain. An email trigger that hits a function without it fails withfunction must export 'email' for email triggers. email(data, request);data.emailincludesto,from,rawSize,timestamp(ISO 8601), and optionalsubject/body. A function can export bothmain(HTTP/cron) andemail.- 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.