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.
| Place | What it controls | Reference |
|---|---|---|
| Container environment | Process mode, database, DIAL connection, HTTP clients, health, and telemetry | Tables below |
| DIAL application definition | Routes, MCP endpoint, application identity, and external services | Register Scheduler in DIAL |
| DIAL Chat environment | Scheduled-task feature and the application and external-service IDs | Connect DIAL Chat |
| Schedule JSON | Trigger, target, request payload, timing, retry policy, and metadata | Schedule definition |
Process and DIAL connection
| Variable | Default | Description |
|---|---|---|
SERVICE | — | Required container mode: migrations, api, or worker. Missing or unknown values stop startup. |
RUN_MIGRATIONS_ON_START | false | Run alembic upgrade head before API or worker startup. Accepts case-insensitive true or 1; migration failure stops startup. |
ENV | prod | dev enables Uvicorn reload for the API. |
APP_NAME | aidial-scheduler | API 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_ID | public/dial_scheduler__1.0.0 | Application 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. |
PORT | 5000 | API HTTP port; binds to 0.0.0.0. |
LOG_LEVEL | INFO | Logging level. |
ECHO_ENDPOINTS | false | Registers diagnostic echo routes and an echo chat-completion deployment. It is not a switch for logging all HTTP traffic. |
MCP_ENABLED | true | Mounts the generated MCP tools in the API process. |
MCP_PATH | /mcp | MCP HTTP endpoint path. Match it in the DIAL application definition. |
CLIENT_CHANNEL_SIGNIN_TIMEOUT_SECONDS | 120.0 | Maximum 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.
| Variable | Default | Description |
|---|---|---|
DB_AUTH_MODE | password | password, connection-string, gcp_iam, azure_entra, or aws_iam. |
DB_DRIVER | postgresql+asyncpg | Async SQLAlchemy driver. The job store uses postgresql+psycopg2 in URL-based, Azure, and AWS modes; GCP IAM uses pg8000. |
DB_HOST | localhost | PostgreSQL hostname. Use a service hostname in container deployments. |
DB_PORT | 5432 | PostgreSQL port. |
DB_NAME | app | Database name. |
DB_USER | app | Username 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_SIZE | 10 | Async database pool size. |
DB_MAX_OVERFLOW | 20 | Additional connections above the pool size. |
DB_POOL_RECYCLE_SECONDS | 1800 | Connection recycling age, in seconds. |
DB_POOL_TIMEOUT_SECONDS | 30 | Wait for an available pool connection, in seconds. |
DB_POOL_PRE_PING | true | Check connections before reuse. |
DB_ECHO | false | Enable 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
| Variable | Default | Description |
|---|---|---|
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_IP | false | Select 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
| Variable | Default | Description |
|---|---|---|
NOOP_INTERVAL_SECONDS | 60 | Worker heartbeat interval, in seconds. |
JOB_COALESCE | false | Worker fallback for combining multiple missed fires into one. |
JOB_MAX_INSTANCES | 1 | Worker fallback for concurrent instances of the same timed job. |
JOB_MISFIRE_GRACE_TIME | 60 | Worker 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
| Variable | Default | Description |
|---|---|---|
READINESS_DB_TIMEOUT_SECONDS | 2.0 | Database check timeout, in seconds, for API and worker readiness. |
WORKER_HEALTH_DIR | /tmp | Directory for started, heartbeat, and ready marker files. Must be writable. |
WORKER_LIVENESS_STALENESS_SECONDS | 180.0 | Documented 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_SECONDS | 15.0 | Interval 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.
| Variable | Default | Description |
|---|---|---|
API_HTTP_MAX_DURATION_SECONDS, WORKER_HTTP_MAX_DURATION_SECONDS | 600.0 | Absolute ceiling on one non-streaming target attempt, in seconds. |
API_HTTP_STREAMING_MAX_DURATION_SECONDS, WORKER_HTTP_STREAMING_MAX_DURATION_SECONDS | 3600.0 | Absolute ceiling on one streaming target attempt, in seconds. |
API_HTTP_IDLE_TIMEOUT_SECONDS, WORKER_HTTP_IDLE_TIMEOUT_SECONDS | 60.0 | Maximum gap between parsed stream events, in seconds; heartbeat pings do not reset it. |
API_HTTP_CONNECT_TIMEOUT_SECONDS, WORKER_HTTP_CONNECT_TIMEOUT_SECONDS | 5.0 | Connection timeout, in seconds. |
API_HTTP_READ_TIMEOUT_SECONDS, WORKER_HTTP_READ_TIMEOUT_SECONDS | 60.0 | Default socket read timeout, in seconds; target execution adjusts the read bound. |
API_HTTP_WRITE_TIMEOUT_SECONDS, WORKER_HTTP_WRITE_TIMEOUT_SECONDS | 60.0 | Socket write timeout, in seconds. |
API_HTTP_POOL_TIMEOUT_SECONDS, WORKER_HTTP_POOL_TIMEOUT_SECONDS | 5.0 | Wait for an HTTP connection, in seconds. |
API_HTTP_MAX_CONNECTIONS, WORKER_HTTP_MAX_CONNECTIONS | 200 | Maximum HTTP connections per client. |
API_HTTP_MAX_KEEPALIVE_CONNECTIONS, WORKER_HTTP_MAX_KEEPALIVE_CONNECTIONS | 20 | Maximum 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.
| Variable | Default | Description |
|---|---|---|
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_PORT | 9464 | Prometheus scrape port when that exporter is selected. |
OTEL_LOG_LEVEL | ERROR | OpenTelemetry 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.
- Create a Scheduler project key in DIAL Admin under Governance > Keys, and assign it a role with access to the Scheduler application.
- Set
DIAL_API_KEYin API and worker to that key. Set the application'sapp_identityto its SHA-256 hash. - Import the application definition under AI Gateway > Applications; see Import. Replace both
<SCHEDULER_URL>occurrences with the API service URL, such ashttp://scheduler-api:5000. - Retain the
mainapplication route withrewritePath=trueand its upstream pointing to the API. The MCP definition points to<SCHEDULER_URL>/mcp, with HTTP transport andforwardPerRequestKey=true. - Retain
external_services.dial-native.auth_settings.authentication_type=DIAL_NATIVE. In the application's External Services, open DIAL Native and click Grant consent. - Set
SCHEDULER_APP_ID=public/dial_scheduler__1.0.0in API and worker, or use the actual resource path if the imported asset differs. - 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
| Symptom | What to check |
|---|---|
| Startup rejects database settings | Required values for DB_AUTH_MODE; remove DB_PASSWORD and DB_URL in workload identity modes. |
Chat returns 503 for scheduled-task calls | Chat's application ID; create and update also need its service ID. |
Create or replace returns 403 | The owner's offline sign-in for the requested service. |
Create or replace returns 502 with state=unknown | Administrator consent, application path, external-service registration, Core reachability, and auth-status response fields. |
Run fails with result.stage=credentials | Application 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 not | Worker startup and readiness, shared database/schema, and job-store connectivity. |
| Duplicate timed executions | More than one worker or overlapping workers during a rollout. |
| Worker restarts repeatedly | Writable health directory; heartbeat interval below the probe's staleness threshold. |
Changing JOB_* has no effect | The API stores its own fixed defaults with each job. |
| Successful run has no conversation | Only chat completions with create_conversation=true qualify. Check conversation_create_failed logs; storage failure does not fail the run. |
Further reading
- Scheduler API — triggers, target fields, verification requests, and run results
- DIAL Chat features — feature flags and Chat-side Scheduler settings
- Application routes — how Core forwards application API calls