---
title: "Trigger Autohand Code from a Cloudflare Worker"
source: https://docs.autohand.ai/tutorials/trigger-autohand-from-cloudflare-worker
---

# Trigger Autohand Code from a Cloudflare Worker

Use a Worker as the public webhook and policy layer while Autohand Code runs on a VPS, Docker host, or Cloudflare Container.

Intermediate 25 min

## Provider docs used

This tutorial follows provider documentation for current Workers request handling and secrets management. Keep these external guides open while you work.

-   [Workers docs](https://developers.cloudflare.com/workers/) (developers.cloudflare.com) — Validate HTTP requests at the edge and forward them to your runner.
-   [Workers secrets](https://developers.cloudflare.com/workers/configuration/secrets/) (developers.cloudflare.com) — Store sensitive values as Worker secrets, not plaintext Wrangler variables.

## Architecture

The Worker does not run the Autohand Code CLI. It validates inbound requests, checks tokens or signatures, and forwards approved jobs to a runner endpoint. The runner can be exposed through Cloudflare Tunnel, a private origin, or Cloudflare Containers.

## Step 1: Create the Worker

``` bash
npm create cloudflare@latest autohand-trigger
cd autohand-trigger
```

## Step 2: Add the trigger code

``` js
export default {
  async fetch(request, env) {
    if (request.method !== "POST") {
      return new Response("method not allowed", { status: 405 });
    }

    const auth = request.headers.get("authorization");
    if (auth !== `Bearer ${env.PUBLIC_TRIGGER_TOKEN}`) {
      return new Response("unauthorized", { status: 401 });
    }

    const body = await request.text();
    const runnerResponse = await fetch(env.RUNNER_URL, {
      method: "POST",
      headers: {
        authorization: `Bearer ${env.RUNNER_BACKEND_TOKEN}`,
        "content-type": "application/json"
      },
      body
    });

    return new Response(await runnerResponse.text(), {
      status: runnerResponse.status
    });
  }
};
```

## Step 3: Store secrets

Cloudflare secrets are encrypted bindings attached to a Worker and available through `env` in the fetch handler. Use them for tokens and origin URLs that should not appear in source control.

``` bash
wrangler secret put PUBLIC_TRIGGER_TOKEN
wrangler secret put RUNNER_BACKEND_TOKEN
wrangler secret put RUNNER_URL
```

For local development, put development-only values in `.dev.vars` and keep that file out of git.

## Step 4: Deploy and trigger

``` bash
wrangler deploy

curl -X POST https://autohand-trigger.example.workers.dev \
  -H "Authorization: Bearer $PUBLIC_TRIGGER_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{"repo":"your-org/your-repo","task":"review latest changes"}'
```

## Step 5: Make the runner task-aware

Have the origin runner parse the JSON body and map allowed tasks to fixed Autohand Code prompts. Avoid letting arbitrary webhook payloads become raw shell commands.

``` js
const prompts = {
  review: "Review the latest changes and summarize action items",
  docs: "Update documentation for the latest CLI behavior"
};

const selected = prompts[payload.task] || prompts.review;
spawn("autohand", ["-p", selected, "--restricted", "--output-format", "stream-json"], {
  cwd: repoDir,
  env: process.env
});
```

## Operations checklist

-   Use Worker secrets for trigger and backend tokens.
-   Validate request method, content type, signature, and allowed task names.
-   Do not expose model provider keys to the Worker unless the Worker itself calls the model provider.
-   Forward only normalized, allowlisted jobs to the runner.
-   Use Cloudflare logs or a Tail Worker for debugging webhook traffic.