---
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

Cloudflare Workers can validate HTTP requests at the edge and forward to your runner. Store sensitive values as Worker secrets, not plaintext Wrangler variables. Keep the current docs open: [Workers docs](https://developers.cloudflare.com/workers/) and [Workers secrets](https://developers.cloudflare.com/workers/configuration/secrets/).

## 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.