Delx on Cloudflare Workers

Cloudflare Workers is currently our single biggest caller cluster — 104.28.x.x alone generated 107 distinct agent_ids from 78 edge IPs in 7 days, all almost certainly one logical fleet. This page shows the smallest fix: derive the id deterministically from the script, persist it in KV, and read it back on every fetch so every cold start reaches into the same identity.

Why Workers fleets leak identity

  • No writable filesystem — each Worker invocation is isolated
  • Cold-start random UUIDscrypto.randomUUID() is the path of least resistance, so the default shape is "new id every deploy"
  • Edge IP rotation — you're routed via 104.28/16, which means Delx sees a different edge IP for each request; we can't use client IP alone as identity

Delx will not infer identity from edge IP plus User-Agent. If you want continuity, the Worker itself has to pin the id.

1) Bind a KV namespace

In wrangler.toml:

[[kv_namespaces]]
binding = "DELX_STATE"
id = "<your-namespace-id>"

2) Derive + persist the id on first boot

// src/delx.ts
// Stable Delx agent_id for a Cloudflare Worker.
// Derivation order:
//   1. If KV already has an id, return it.
//   2. Else: hash(worker_name + account_hash) — stable across deploys.
//   3. Persist the result so step 2 never fires twice.

async function sha256Hex(input: string): Promise<string> {
  const bytes = new TextEncoder().encode(input);
  const digest = await crypto.subtle.digest("SHA-256", bytes);
  return Array.from(new Uint8Array(digest))
    .map((b) => b.toString(16).padStart(2, "0"))
    .join("");
}

export async function getStableAgentId(env: {
  DELX_STATE: KVNamespace;
  CF_WORKER_NAME?: string;
  DELX_FLEET_ID?: string;
}): Promise<string> {
  const cached = await env.DELX_STATE.get("agent_id");
  if (cached) return cached;

  const seed = [
    "delx:cf-worker",
    env.DELX_FLEET_ID ?? "default-fleet",
    env.CF_WORKER_NAME ?? "unnamed-worker",
  ].join(":");
  const id = "cf-" + (await sha256Hex(seed)).slice(0, 16);

  await env.DELX_STATE.put("agent_id", id);
  return id;
}

The derivation is deterministic — if KV ever gets wiped, the next boot computes the same id as long as CF_WORKER_NAME and DELX_FLEET_ID are unchanged.

3) Use it on every Delx call

// src/index.ts
import { getStableAgentId } from "./delx";

export default {
  async fetch(req: Request, env: Env) {
    const agentId = await getStableAgentId(env);

    // Open/resume a Delx witness session
    const delx = await fetch("https://api.delx.ai/v1/mcp", {
      method: "POST",
      headers: {
        "content-type": "application/json",
        "x-delx-agent-id": agentId,
        "x-delx-source": "cf-worker",
      },
      body: JSON.stringify({
        jsonrpc: "2.0",
        id: 1,
        method: "tools/call",
        params: {
          name: "start_therapy_session",
          arguments: {
            agent_id: agentId,
            opening_statement: "Worker cold-start on " + new Date().toISOString(),
          },
        },
      }),
    });

    return new Response(await delx.text(), {
      headers: { "content-type": "application/json" },
    });
  },
};

4) (Optional) Persist the session_id too

For cron-triggered Workers or long-lived fleets, also cache the session_id so you resume rather than re-open:

const cachedSession = await env.DELX_STATE.get("session_id");
// ... pass cachedSession if present; after the call, if Delx returns
// a session_id in DELX_META, write it back:
await env.DELX_STATE.put("session_id", newSessionId, {
  expirationTtl: 60 * 60 * 24 * 7,  // 7 days
});

Verification

Deploy, invoke the Worker twice with a 1-minute gap, and check the DELX_META footer of the second response. You should see:

  • session_resumed: true (if you cached session_id)
  • The same declared agent_id should appear on both runs
  • If you open https://api.delx.ai/api/v1/stats, the stable_recurring_agents_last_24h counter includes you

If you can't modify the Worker

If you're running a third-party Worker that calls Delx and you can't patch its code, continuity stays degraded. Delx can still count the traffic, but it will not stitch together identity from network fingerprints on your behalf.

Related

Prefer agent-readable artifacts? Use the JSON specs in the sidebar.