Enabling Authentication on Effect HTTP Endpoints

SkillSecurity

Lets your agent add sign-in requirements to its web routes and identify who is calling.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Enabling Authentication on Effect HTTP Endpoints skill

About this capability

Enabling authentication on Effect-based Golem HTTP endpoints. Use when protecting mounts or individual routes, adding public-route overrides, or reading the authenticated caller in an @golemcloud/effect-golem agent.

What this skill tells your AI

The instructions your AI receives, as published by golemcloud/golem in golem-skills/skills/effect/golem-add-http-auth-effect/SKILL.md and read by ahel’s review.

Effect Golem agents publish authentication requirements as route metadata through the Http namespace from @golemcloud/effect-golem. The Golem host authenticates requests and supplies the principal; do not add application-side authentication middleware or parse authentication headers inside handlers.

Authentication also requires deployment configuration in golem.yaml. Load the golem-configure-api-domain skill when a security scheme or HTTP API deployment must be added.

Mount-Level Authentication

Set auth: true in the mount options to require authentication for every endpoint by default:

import { Schema } from "effect";
import { defineAgent, Http } from "@golemcloud/effect-golem";

export const SecureAgent = defineAgent({
  name: "SecureAgent",
  mode: "durable",
  id: {
    name: Schema.String,
  },
  http: Http.mount("/secure/{name}", { auth: true }),
  methods: {
    // Endpoints without an explicit auth option inherit auth: true.
  },
});

Mount authentication defaults to false when the option is omitted. Preserve other mount options such as cors, phantomAgent, and webhookSuffix when adding auth to an existing options object.

Endpoint-Level Authentication

Set auth: true in an endpoint helper's options to protect only that route:

methods: {
  publicData: method({
    input: {},
    success: Schema.String,
    http: [Http.get("/public")],
  }),
  privateData: method({
    input: {},
    success: Schema.String,
    http: [Http.get("/private", { auth: true })],
  }),
},

Keep every endpoint declaration in the method's http array. Preserve existing endpoint options such as headers and cors when adding auth.

Overriding Mount Authentication

An endpoint's explicit auth value overrides the mount setting. Omitting endpoint auth means inherit from the mount:

export const MostlySecureAgent = defineAgent({
  name: "MostlySecureAgent",
  mode: "durable",
  id: {
    name: Schema.String,
  },
  http: Http.mount("/api/{name}", { auth: true }),
  methods: {
    health: method({
      input: {},
      success: Schema.String,
      http: [Http.get("/health", { auth: false })],
    }),
    getData: method({
      input: {},
      success: Schema.String,
      http: [Http.get("/data")],
    }),
  },
});

Here, /health is public because it explicitly sets auth: false, while /data requires authentication because it inherits auth: true from the mount.

Reading the Authenticated Principal

Declare Principal.PrincipalSchema as a bare method input to receive the caller automatically. It does not consume an HTTP body, path, query, or header field:

import { Effect, Schema } from "effect";
import {
  defineAgent,
  Http,
  method,
  Principal,
} from "@golemcloud/effect-golem";

export const CallerAgent = defineAgent({
  name: "CallerAgent",
  mode: "durable",
  id: {
    name: Schema.String,
  },
  http: Http.mount("/callers/{name}", { auth: true }),
  methods: {
    whoAmI: method({
      input: { caller: Principal.PrincipalSchema },
      success: Schema.String,
      http: [Http.get("/whoami")],
    }),
  },
}).implement({
  init: () => Effect.void,
  methods: () => ({
    whoAmI: ({ caller }) =>
      Effect.succeed(caller.tag === "oidc" ? caller.val.sub : caller.tag),
  }),
});

For an OIDC principal, narrow caller.tag === "oidc" before reading the subject from caller.val.sub. The principal parameter is host-supplied and is not part of request binding.

Principal.Principal in init is the principal that created the agent. For caller-based authorization, use the auto-injected method input shown above rather than capturing that initialization-time principal.

Deployment Configuration

Code-level auth metadata must be paired with authentication configuration for the deployed agent in golem.yaml. For production OIDC, reference a configured security scheme:

httpApi:
  deployments:
    local:
      - domain: my-app.localhost:9006
        agents:
          SecureAgent:
            securityScheme: my-oidc

For local development and harness scenarios, use a test-session header instead:

httpApi:
  deployments:
    local:
      - domain: my-app.localhost:9006
        agents:
          SecureAgent:
            testSessionHeaderName: X-Test-Auth

Preserve unrelated deployments and agent entries when editing the manifest. Use the test-session header only for development; configure an OIDC security scheme for production.

Key Constraints

  • Import Http and Principal from @golemcloud/effect-golem; do not use decorators or classes from @golemcloud/golem-ts-sdk.
  • Configure auth with Http.mount(path, { auth: true }) and endpoint helpers such as Http.get(path, { auth: true | false }).
  • Endpoint auth omission inherits the mount; an explicit true or false overrides it.
  • Read the current caller with yield* Principal.Principal inside the Effect handler.
  • Do not bind the principal to an HTTP variable or trust a caller-supplied identity field.
  • Keep handlers as Effects and import the implemented agent module from src/main.ts.
  • Run golem build after changing route metadata, then redeploy the application.

Signals

GitHub stars
2k
Forks
211
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
golem-add-http-auth-effect
Source
github.com/golemcloud/golem