The Descope Engine is a lightweight, self-hosted agent that you run inside your own network so Descope connectors can reach resources that are not reachable from the public internet β for example an internal HTTP API behind your firewall, a private database, or an on-prem SMTP relay.
The Engine makes a single outbound connection to Descope and executes connector actions locally, so you never have to open inbound ports or expose internal systems to Descope's cloud.
Your network (private) Descope cloud
βββββββββββββββββββββββββββββββββ ββββββββββββββββββββββββββββ
β β gRPC β β
β Engine container βββββββββββΌβββββββββΊβ Descope Engine service β
β (ghcr.io/descope/engine) β (TLS, β routes connector β
β β β outboundβ commands β
β β executes locally β only) β β
β βΌ β β β
β Internal API / DB / SMTP β β β
βββββββββββββββββββββββββββββββββ ββββββββββββββββββββββββββββ
Hello message as the first message on the stream. The Hello carries your Engine ID and Engine Secret. Descope looks up the Engine by ID and verifies the secret. There is no separate token exchange β the Hello message is the authentication.Hello to re-authenticate.High availability: run multiple Engine containers with the same Engine ID. Descope automatically distributes commands across the connected replicas (competing consumers), and any replica can execute any connector type.
Create an Engine and copy its credentials from the Descope Console:
These map to the ENGINE_ID and ENGINE_SECRET environment variables.
The Engine is published as ghcr.io/descope/engine and mirrored to Docker Hub as docker.io/descope/engine.
Create an .env file:
# Required β from Descope Console (Connectors β Engines β Edit)
ENGINE_ID=your-engine-id-here
ENGINE_SECRET=your-engine-secret-here
# Descope Engine gRPC endpoint (use the endpoint provided by Descope)
SERVER_ADDRESS=engine.descope.com:443
USE_SSL=true
Run the container:
docker run --env-file .env ghcr.io/descope/engine
For high availability, run the same container on multiple hosts/replicas with the same ENGINE_ID.
The official image already sets
ENGINE_IMAGE_VERSIONandENGINE_CONTENT_VERSION(which identify the image and the bundled connector templates), so you do not need to provide them.
The production image is based on Descope's FIPS-validated Node runtime image and invokes the client with node dist/index.js.
All configuration is provided through environment variables.
| Variable | Description |
|---|---|
ENGINE_ID | Engine ID from the Descope Console. Identifies this Engine; replicas sharing it form one HA group. Your Descope project is derived from this ID. |
ENGINE_SECRET | Engine Secret from the Descope Console. Sent in the Hello message and verified by Descope on connect. |
ENGINE_IMAGE_VERSION | Engine image version identifier. Pre-set in the official image β only set this if you build your own image. |
ENGINE_CONTENT_VERSION | Connector content (templates) version identifier. Pre-set in the official image. |
| Variable | Default | Description |
|---|---|---|
SERVER_ADDRESS | localhost:50051 | Descope Engine gRPC endpoint (host:port). Set this to the endpoint provided by Descope. |
USE_SSL | true | Use TLS for the connection. Keep true in production; set false only for local development. |
VERIFY_SERVER_CERTIFICATE | true | Verify the server's TLS certificate. Set false only for self-signed certificates in development. |
| Variable | Default | Description |
|---|---|---|
HEARTBEAT_INTERVAL | 30000 | Application-level heartbeat interval (ms). |
GRPC_KEEPALIVE_TIME_MS | 30000 | HTTP/2 PING interval when idle (ms). Keeps the connection alive through proxies. |
GRPC_KEEPALIVE_TIMEOUT_MS | 20000 | How long to wait for a PING acknowledgement before dropping the connection (ms). |
GRPC_KEEPALIVE_PERMIT_WITHOUT_CALLS | true | Send PINGs even when there are no active calls. |
The keepalive settings send HTTP/2 PING frames to maintain the connection through proxies (e.g. Cloudflare) and prevent idle-timeout disconnects (such as HTTP 524 errors).
| Variable | Default | Description |
|---|---|---|
MAX_RECONNECT_ATTEMPTS | 10 | Maximum reconnection attempts before the process exits. |
BASE_RECONNECT_DELAY | 1000 | Initial reconnection delay (ms). |
MAX_RECONNECT_DELAY | 30000 | Maximum reconnection delay, with jitter (ms). |
| Variable | Default | Description |
|---|---|---|
LOG_LEVEL | info | Log verbosity (fatal, error, warn, info, debug, trace). In production (NODE_ENV=production) logs are JSON; otherwise pretty-printed. |
443) to the Descope Engine endpoint.USE_SSL=true and VERIFY_SERVER_CERTIFICATE=true are the production defaults. The false overrides are for local development only.ENGINE_SECRET is a credential. In production, inject it via your orchestrator's secret mechanism rather than a plaintext .env file.This image is intended for Federal deployments (e.g. FedRAMP Moderate). The notes below describe the technical posture; for formal SLA commitments and signed per-CVE impact statements, contact Descope security/compliance.
echo/node-fips). All cryptography the client performs β notably the TLS gRPC connection to Descope β goes through that base's FIPS-validated OpenSSL module.crypto.getFips() returns 1 with no flags. Verify directly:
docker run --rm --entrypoint node descope/engine:latest -p 'crypto.getFips()' # -> 1
echo/node-fips base; remediation is prioritized by severity, aligned to FedRAMP timelines (High 30 days / Moderate 90 days / Low 180 days). Contact Descope for the formal, signed SLA.| Symptom | Likely cause / fix |
|---|---|
Invalid engine secret / auth failure on connect | Wrong ENGINE_ID or ENGINE_SECRET, or the secret was rotated in the Console. Re-copy both from Connectors β Engines β Edit. |
Connection refused / cannot reach server | SERVER_ADDRESS is wrong, or an egress firewall is blocking outbound TLS to Descope. |
| Connection drops when idle / behind a proxy | Proxy idle timeout. The keepalive defaults usually fix this; if not, lower GRPC_KEEPALIVE_TIME_MS. |
| Commands are not being executed | Confirm at least one Engine with the correct ENGINE_ID is connected. Check the logs for gRPC stream established with server and Listening for commands. |
| Need a shell to inspect the container | The FIPS runtime image is minimal. Override the entrypoint only when the base image includes inspection tooling. |
To get more detail, check the container logs β the Engine logs connection state, heartbeats, and command execution.
The Engine is a TypeScript application. To run it from source against a local server:
pnpm install
# Configure credentials and a local server address
cp .env.example .env # then edit ENGINE_ID, ENGINE_SECRET, SERVER_ADDRESS
# Run directly with tsx (no build needed). NODE_TLS_REJECT_UNAUTHORIZED=0
# is only for local servers with self-signed certs.
NODE_TLS_REJECT_UNAUTHORIZED=0 pnpm dev
# Or build and run the bundle
pnpm build
pnpm start
# Type-check and test
pnpm typecheck
pnpm test
Connector behavior is implemented as templates. At startup the Engine discovers templates under src/templates/; each template directory contains a metadata.json (id, name, commands) and an index.mjs exporting async function handler(event). When the server sends an execute command, the Engine routes it to the matching template by templateId. The official image bundles the standard connector templates from ghcr.io/descope/connectors. See src/templates/mock/ for a complete example.
The gRPC types in src/generated/ are generated with ts-proto. After changing the proto definitions, regenerate them from the service root:
cd .. && make proto
Content type
Image
Digest
sha256:e0d2dddecβ¦
Size
126.5 MB
Last updated
about 14 hours ago
docker pull descope/engine