Skip to content

Ops View

Expose a read-only ops view over runtime projections without creating shadow state.

An HTTP ops mount that lists scopes and reads one Durable Object’s events, runs, quota, and resources through @agent-os/ops-api.

  1. Import the terminal ops adapter and the Cloudflare reader binder:

    import { mountOpsApi } from "@agent-os/ops-api";
    import { cloudflareAgentDoOpsStubFor } from "@agent-os/backend-cloudflare-do";
  2. Define a scope resolver. It owns routing from an ops scope string to a Cloudflare-resolved scope. The backend adapter owns Durable Object binding and truth identity selection:

    import type { CloudflareAgentDOResolvedScope } from "@agent-os/backend-cloudflare-do";
    const scopeResolver = {
    async list() {
    return [{ scope: "tutorial", label: "Tutorial", surface: "agent-do/v0.3" }];
    },
    async resolve(scope: string): Promise<CloudflareAgentDOResolvedScope | null> {
    if (scope !== "tutorial") return null;
    return {
    scope,
    label: "Tutorial",
    surface: "agent-do/v0.3",
    namespace: env.AGENT_DO,
    };
    },
    };
  3. Define auth at the edge:

    const auth = {
    async authenticate() {
    return { id: "local-dev", roles: ["operator"] };
    },
    async authorize(_principal, _scope, action) {
    return action === "read" || action === "stream";
    },
    };
  4. Mount under an explicit path:

    const opsApi = mountOpsApi({ scopeResolver, auth, stubFor: cloudflareAgentDoOpsStubFor });
    export default {
    fetch(request: Request) {
    if (new URL(request.url).pathname.startsWith("/__ops/api")) {
    return opsApi(request);
    }
    return appFetch(request);
    },
    };

The ops endpoint returns derived data only:

GET /__ops/api/scopes
GET /__ops/api/scopes/tutorial/events
GET /__ops/api/scopes/tutorial/runs

Ops code does not write ledger facts and does not maintain its own run table. If an ops view is wrong, fix the runtime projection or resolver boundary.

Deploy a Worker path with deploy minimal worker.