Skip to main content

DIAL Scheduler configuration

This reference covers Scheduler configuration for platform engineers deploying the API and worker beside DIAL Core. It assumes the service dependencies are available. Per-schedule triggers, target properties, and retries are described in API.

Configuration sources​

Defaults come from settings.py, the entrypoint, and the API scheduler factory. Settings classes read .env; process environment variables take precedence. Configuration is loaded at startup and cached.

The upstream README lists SCHEDULER_APP_ID=dial_scheduler, but code defaults to public/dial_scheduler__1.0.0. It describes sign-in checks as OBO probes; the implementation instead reads application auth status. The code also includes DB_SCHEMA, ENV, and CLIENT_CHANNEL_SIGNIN_TIMEOUT_SECONDS, which its environment tables omit.

PlaceWhat it controlsReference
Container environmentProcess mode, database, DIAL connection, HTTP clients, health, and telemetryTables below
DIAL application definitionRoutes, MCP endpoint, application identity, and external servicesRegister Scheduler in DIAL
DIAL Chat environmentScheduled-task feature and the application and external-service IDsConnect DIAL Chat
Schedule JSONTrigger, target, request payload, timing, retry policy, and metadataSchedule definition

Process and DIAL connection​

VariableDefaultDescription
SERVICE—Required container mode: migrations, api, or worker. Missing or unknown values stop startup.
RUN_MIGRATIONS_ON_STARTfalseRun alembic upgrade head before API or worker startup. Accepts case-insensitive true or 1; migration failure stops startup.
ENVproddev enables Uvicorn reload for the API.
APP_NAMEaidial-schedulerAPI title and logging application name.
DIAL_URL—Required Core base URL, such as http://dial-core:8080.
DIAL_API_KEY—Required Scheduler project key used for OBO credential lookup. Its SHA-256 hash must match the application's app_identity.
SCHEDULER_APP_IDpublic/dial_scheduler__1.0.0Application resource path used for sign-in status and OBO scope. Keep API, worker, and Chat aligned.
USER_ID_PATH_LIST["userId", "project"]Ordered JSON paths into Core's user-info response. Supply a JSON array; the first non-empty match identifies the caller.
PORT5000API HTTP port; binds to 0.0.0.0.
LOG_LEVELINFOLogging level.
ECHO_ENDPOINTSfalseRegisters diagnostic echo routes and an echo chat-completion deployment. It is not a switch for logging all HTTP traffic.
MCP_ENABLEDtrueMounts the generated MCP tools in the API process.
MCP_PATH/mcpMCP HTTP endpoint path. Match it in the DIAL application definition.
CLIENT_CHANNEL_SIGNIN_TIMEOUT_SECONDS120.0Maximum wait for interactive external-service sign-in through a forwarded client channel.

Sources: settings, API routing and startup, and identity extraction. The README's description of ECHO_ENDPOINTS differs from its implementation.

Database connection and pool​

The API and worker must share the same PostgreSQL database and schema. Supply database settings to the migration container as well. The online migration path initializes the shared database engine, which also loads the required DIAL settings.

VariableDefaultDescription
DB_AUTH_MODEpasswordpassword, connection-string, gcp_iam, azure_entra, or aws_iam.
DB_DRIVERpostgresql+asyncpgAsync SQLAlchemy driver. The job store uses postgresql+psycopg2 in URL-based, Azure, and AWS modes; GCP IAM uses pg8000.
DB_HOSTlocalhostPostgreSQL hostname. Use a service hostname in container deployments.
DB_PORT5432PostgreSQL port.
DB_NAMEappDatabase name.
DB_USERappUsername for password authentication. Cloud identity modes use their dedicated user settings.
DB_PASSWORD—Required in password mode.
DB_URL—Required in connection-string mode; otherwise not selected as the connection URL.
DB_SCHEMA—Optional PostgreSQL search_path for service database connections. Provision the schema before use.
DB_POOL_SIZE10Async database pool size.
DB_MAX_OVERFLOW20Additional connections above the pool size.
DB_POOL_RECYCLE_SECONDS1800Connection recycling age, in seconds.
DB_POOL_TIMEOUT_SECONDS30Wait for an available pool connection, in seconds.
DB_POOL_PRE_PINGtrueCheck connections before reuse.
DB_ECHOfalseEnable SQL statement logging.

In connection-string mode, the async engine uses DB_URL; the job store rewrites its driver to postgresql+psycopg2. Sources: database settings and validation, URL selection, async engine, job-store engine, and migrations.

Workload identity authentication​

VariableDefaultDescription
DB_GCP_INSTANCE_CONNECTION_NAME—Required Cloud SQL instance connection name in gcp_iam mode.
DB_GCP_IAM_USER—Required PostgreSQL IAM user in gcp_iam mode.
DB_GCP_PRIVATE_IPfalseSelect the Cloud SQL private IP connection.
DB_AZURE_ENTRA_USER—Required database principal in azure_entra mode.
DB_AZURE_MANAGED_IDENTITY_CLIENT_ID—Optional user-assigned managed identity client ID.
DB_AWS_IAM_USER—Required database user in aws_iam mode.
DB_AWS_REGION—Optional region override; otherwise resolves through AWS_REGION, then the AWS SDK configuration.

All three workload identity modes reject a configured DB_PASSWORD or DB_URL. The workload must have the cloud identity, network access, and database permissions required for the selected mode. Missing mode-specific settings fail validation at startup. See credential providers and mode validation.

Worker and job settings​

VariableDefaultDescription
NOOP_INTERVAL_SECONDS60Worker heartbeat interval, in seconds.
JOB_COALESCEfalseWorker fallback for combining multiple missed fires into one.
JOB_MAX_INSTANCES1Worker fallback for concurrent instances of the same timed job.
JOB_MISFIRE_GRACE_TIME60Worker fallback grace period after a scheduled fire, in seconds.

The worker reads these JOB_* settings, but the API registers jobs with fixed defaults: coalesce=false, max_instances=1, and misfire_grace_time=60. Those values are stored with the job. Changing worker variables alone does not override defaults already assigned by the API. Immediate runs use the API's background launcher and can overlap an existing run.

Sources: worker creation, API job defaults, and immediate runs.

Health settings​

VariableDefaultDescription
READINESS_DB_TIMEOUT_SECONDS2.0Database check timeout, in seconds, for API and worker readiness.
WORKER_HEALTH_DIR/tmpDirectory for started, heartbeat, and ready marker files. Must be writable.
WORKER_LIVENESS_STALENESS_SECONDS180.0Documented heartbeat staleness threshold, in seconds. The 0.3.1 worker does not read it: the external liveness probe enforces staleness, and the upstream probe hard-codes 180. Set the threshold in the probe.
WORKER_READINESS_CHECK_INTERVAL_SECONDS15.0Interval between worker database checks, in seconds.

NOOP_INTERVAL_SECONDS must stay below the liveness probe's staleness threshold. Kubernetes worker probes check marker existence and heartbeat age with exec; HTTP probes apply only to the API. See probe configuration.

HTTP client settings​

The two prefixes have identical defaults. API_HTTP_* controls the API client and immediate runs; WORKER_HTTP_* controls timed runs.

VariableDefaultDescription
API_HTTP_MAX_DURATION_SECONDS, WORKER_HTTP_MAX_DURATION_SECONDS600.0Absolute ceiling on one non-streaming target attempt, in seconds.
API_HTTP_STREAMING_MAX_DURATION_SECONDS, WORKER_HTTP_STREAMING_MAX_DURATION_SECONDS3600.0Absolute ceiling on one streaming target attempt, in seconds.
API_HTTP_IDLE_TIMEOUT_SECONDS, WORKER_HTTP_IDLE_TIMEOUT_SECONDS60.0Maximum gap between parsed stream events, in seconds; heartbeat pings do not reset it.
API_HTTP_CONNECT_TIMEOUT_SECONDS, WORKER_HTTP_CONNECT_TIMEOUT_SECONDS5.0Connection timeout, in seconds.
API_HTTP_READ_TIMEOUT_SECONDS, WORKER_HTTP_READ_TIMEOUT_SECONDS60.0Default socket read timeout, in seconds; target execution adjusts the read bound.
API_HTTP_WRITE_TIMEOUT_SECONDS, WORKER_HTTP_WRITE_TIMEOUT_SECONDS60.0Socket write timeout, in seconds.
API_HTTP_POOL_TIMEOUT_SECONDS, WORKER_HTTP_POOL_TIMEOUT_SECONDS5.0Wait for an HTTP connection, in seconds.
API_HTTP_MAX_CONNECTIONS, WORKER_HTTP_MAX_CONNECTIONS200Maximum HTTP connections per client.
API_HTTP_MAX_KEEPALIVE_CONNECTIONS, WORKER_HTTP_MAX_KEEPALIVE_CONNECTIONS20Maximum retained keep-alive connections per client.

A schedule's properties.timeout and properties.idle_timeout override the corresponding process defaults. The duration ceiling applies separately to each attempt. Scheduler's retry policy does not retry duration expiry, stream inactivity, or transport failures without an HTTP status. See HTTP defaults, retry execution, and executor timeouts.

Telemetry​

The API and worker initialize DIAL SDK telemetry. Standard OpenTelemetry environment variables configure export; without exporter variables, upstream documents export as inactive.

VariableDefaultDescription
OTEL_TRACES_EXPORTER—Select otlp to export traces.
OTEL_METRICS_EXPORTER—Select otlp for OTLP or prometheus for a scrape endpoint.
OTEL_LOGS_EXPORTER—Optional log exporter, such as otlp.
OTEL_EXPORTER_OTLP_ENDPOINT—Collector endpoint, such as http://otel-collector:4317.
OTEL_EXPORTER_OTLP_PROTOCOL—Export protocol; the upstream example uses grpc.
OTEL_SERVICE_NAME—Explicit telemetry service name; the upstream example uses aidial-scheduler.
OTEL_EXPORTER_PROMETHEUS_PORT9464Prometheus scrape port when that exporter is selected.
OTEL_LOG_LEVELERROROpenTelemetry internal logger level documented upstream.

These are SDK settings, not fields in Scheduler's settings classes. Sources: telemetry environment example, upstream observability reference, and worker initialization.

Register Scheduler in DIAL​

The upstream application definition registers an asset application with path public/dial_scheduler__1.0.0.

  1. Create a Scheduler project key in DIAL Admin under Governance > Keys, and assign it a role with access to the Scheduler application.
  2. Set DIAL_API_KEY in API and worker to that key. Set the application's app_identity to its SHA-256 hash.
  3. Import the application definition under AI Gateway > Applications; see Import. Replace both <SCHEDULER_URL> occurrences with the API service URL, such as http://scheduler-api:5000.
  4. Retain the main application route with rewritePath=true and its upstream pointing to the API. The MCP definition points to <SCHEDULER_URL>/mcp, with HTTP transport and forwardPerRequestKey=true.
  5. Retain external_services.dial-native.auth_settings.authentication_type=DIAL_NATIVE. In the application's External Services, open DIAL Native and click Grant consent.
  6. Set SCHEDULER_APP_ID=public/dial_scheduler__1.0.0 in API and worker, or use the actual resource path if the imported asset differs.
  7. Each user enables offline access through DIAL Chat's Extensions. Check sign-in status before creating a schedule.

Scheduler requires DIAL Core 0.47.0 or later, the first release with DIAL_NATIVE external services, the /v1/user/offline-credentials endpoint, and the /v1/ops/external-service/obo-credentials operation. For a DIAL_NATIVE service, that operation redeems the owner's offline credentials, which Core obtains through the identity provider's offline client. The upstream local Core sample provides integration context.

Administrator consent applies to the application across users who enabled offline access. User sign-out prevents that user's later runs; withdrawing administrator consent prevents the application's later delegated runs. The service key obtains credentials for the owner; it is not the target request's user identity. See credential resolution.

Warning

A schedule supplies its target URL, and execution sends delegated credentials to that target. Limit target network access to trusted services and protect the database containing payloads and results.

Deployment example​

The following Compose fragment assumes an existing PostgreSQL service named postgres and Core service named dial-core on the same network. The scheduler database and user must already exist, and PostgreSQL must be ready before migrations start. Docker Hub publishes only the development tag; there is no image for release 0.3.1. Supply a Docker Hub image tag as SCHEDULER_IMAGE_TAG, or replace image with one built from the 0.3.1 Dockerfile. Supply SCHEDULER_DB_PASSWORD and SCHEDULER_API_KEY through the deployment's environment.

x-scheduler: &scheduler
image: epam/ai-dial-scheduler:${SCHEDULER_IMAGE_TAG:?Set the Scheduler image tag}
platform: linux/amd64
environment: &scheduler-environment
DIAL_URL: http://dial-core:8080
DIAL_API_KEY: ${SCHEDULER_API_KEY:?Set the Scheduler project key}
SCHEDULER_APP_ID: public/dial_scheduler__1.0.0
DB_AUTH_MODE: password
DB_HOST: postgres
DB_NAME: scheduler
DB_USER: scheduler
DB_PASSWORD: ${SCHEDULER_DB_PASSWORD:?Set the database password}

services:
scheduler-migrations:
<<: *scheduler
environment:
<<: *scheduler-environment
SERVICE: migrations
restart: "no"

scheduler-api:
<<: *scheduler
environment:
<<: *scheduler-environment
SERVICE: api
depends_on:
scheduler-migrations:
condition: service_completed_successfully
expose: ["5000"]

scheduler-worker:
<<: *scheduler
environment:
<<: *scheduler-environment
SERVICE: worker
depends_on:
scheduler-migrations:
condition: service_completed_successfully

This fragment adds the three Scheduler processes to an existing deployment; it does not register the application or configure offline delegation. The upstream Compose file includes a PostgreSQL service and migration ordering.

Connect DIAL Chat​

The Chat feature settings control the user interface and BFF routes:

SCHEDULED_TASKS_ENABLED=true
SCHEDULER_APP_ID=public/dial_scheduler__1.0.0
SCHEDULER_SERVICE_ID=dial-native

Chat's SCHEDULER_APP_ID must match Scheduler's application resource path; SCHEDULER_SERVICE_ID names its registered external service. SCHEDULER_SERVICE_TIMEOUT_MS defaults to 10000; this Chat-to-Scheduler request timeout is separate from target execution timeouts. Restart Chat after changing its environment.

Check that Scheduled tasks appears, complete offline sign-in, and create a task targeting an available model. Start now should create a run whose status eventually becomes success and whose result appears as a conversation. A successful immediate run verifies the API execution path; allow the next timed fire to verify the worker as well.

Troubleshooting​

SymptomWhat to check
Startup rejects database settingsRequired values for DB_AUTH_MODE; remove DB_PASSWORD and DB_URL in workload identity modes.
Chat returns 503 for scheduled-task callsChat's application ID; create and update also need its service ID.
Create or replace returns 403The owner's offline sign-in for the requested service.
Create or replace returns 502 with state=unknownAdministrator consent, application path, external-service registration, Core reachability, and auth-status response fields.
Run fails with result.stage=credentialsApplication identity, Scheduler project key, administrator consent, and the owner's current offline credentials. The target was not dispatched.
Immediate runs work but timed runs do notWorker startup and readiness, shared database/schema, and job-store connectivity.
Duplicate timed executionsMore than one worker or overlapping workers during a rollout.
Worker restarts repeatedlyWritable health directory; heartbeat interval below the probe's staleness threshold.
Changing JOB_* has no effectThe API stores its own fixed defaults with each job.
Successful run has no conversationOnly chat completions with create_conversation=true qualify. Check conversation_create_failed logs; storage failure does not fail the run.

Further reading​