Skip to content

Functions and cron

Functions are Deno-compatible TypeScript declared in the app manifest.

Authenticated Function

yaml
functions:
  - name: summarize
    entrypoint: functions/summarize/index.ts
    verifyJwt: true
requiredSecrets:
  - AI_API_KEY
ts
import { defineFunction } from "@opencloud/server";

defineFunction(async ({ input, secrets, db, requestId, log }) => {
  const body = await input.json<{ itemId?: string }>();
  const secret = secrets.require("AI_API_KEY");
  const items = body.itemId
    ? await db.from("items").select("id,title", {
        filters: { id: body.itemId },
      })
    : [];
  log.info("summary requested", { itemId: body.itemId ?? null });
  return Response.json({
    ok: true,
    secretPresent: Boolean(secret),
    items,
    requestId,
  });
});

The platform creates the request ID before module loading and catches import errors, rejected promises, timeouts, invalid responses, and failed platform calls. The server library binds database, Auth, Storage, secrets, input, and structured logging to the current app environment. See development sessions for explicit dev invocation and diagnostics.

Table reads and writes use one consistent filter envelope:

ts
await db.from("items").select("*", { filters: { state: "open" } });
await db.from("items").update(
  { state: "closed" },
  { filters: { id: itemId } },
);
await db.from("items").delete({ filters: { id: itemId } });

Call PostgreSQL functions with db.rpc(name, args). For atomic multi-step work, put the steps in one PostgreSQL function and call db.transaction(name, args); one RPC is the transaction boundary. Use compareAndSet(value, { filters, expected }) for RLS-scoped optimistic concurrency. Application errors such as OUT_OF_STOCK retain their explicit code through the Function response and verification diagnostics.

js
await opencloud.functions.invoke("summarize", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({ itemId }),
});

Public Function

Declare verifyJwt: false and call invokePublic. Public means no user JWT verification; the SDK still sends the gateway’s anonymous project identity.

Cron

yaml
cron:
  - name: hourly-summary
    schedule: "0 * * * *"
    function: summarize
    enabled: true

Cron uses five-field UTC expressions. It invokes the Function with POST, a scheduling envelope, and x-opencloud-invocation: cron.

Verification triggers the declared active cron job deterministically and then reads the normal structured invocation history. The schedule cadence no longer needs to fit inside a verifier timeout.

Secrets

Declare names in the manifest and provision values separately. Generate values that do not need to be known:

bash
"$OPENCLOUD_CLI" secret generate "$APP_ID" INTERNAL_SIGNING_KEY

For a user-supplied provider key:

bash
"$OPENCLOUD_CLI" secret entry-link "$APP_ID" AI_API_KEY

The returned one-time browser page keeps the value out of the agent conversation. Return only a presence flag, version marker, or one-way digest. Never return or log plaintext secrets.

Self-hosted infrastructure for agent-built applications.