Opengram

Configuration

Configure Opengram using the config file, the init wizard, the admin API, or the web UI.

Opengram is configured through a single JSON file, opengram.config.json. This file controls agents, models, push notifications, security, server behavior, and more.

Ways to edit configuration

There are four ways to update the configuration:

  1. Edit the file directly — open opengram.config.json in any text editor and restart Opengram to apply changes.
  2. Run the init wizardopengram init walks you through the most common settings interactively.
  3. Use the admin API — send a PATCH request to /api/v1/config/admin to update configuration at runtime without a restart.
  4. Use the web UI — open the Settings page in the Opengram web interface (/settings) to edit agents, models, security, push notifications, and auto-rename settings from your browser. Changes are applied immediately.

Changes made by editing the JSON file require a restart to take effect. The admin API and the web UI apply changes immediately.

Config file location

When using the CLI (opengram init / opengram start), the config file lives at:

~/.opengram/opengram.config.json

You can change the home directory by setting the OPENGRAM_HOME environment variable, in which case the config file will be at $OPENGRAM_HOME/opengram.config.json.

For other deployment methods, the location depends on your setup:

MethodDefault path
CLI (opengram start)~/.opengram/opengram.config.json
Docker/opt/opengram/config/opengram.config.json (mount a volume)

You can always override the path explicitly with the OPENGRAM_CONFIG_PATH environment variable:

export OPENGRAM_CONFIG_PATH=/path/to/opengram.config.json

Top-level structure

The configuration file has the following top-level fields:

FieldTypeDefaultPurpose
appNamestring"OpenGram"Display name for the instance
maxUploadBytesnumber50000000Maximum file upload size in bytes (default 50 MB)
allowedMimeTypesstring[]["*/*"]Allowed MIME types for uploads (supports wildcards)
titleMaxCharsnumber48Maximum characters for chat titles
defaultModelIdForNewChatsstringPreselected model when creating new chats (must match a models entry)
agentsAgentConfig[]Array of agent definitions
modelsModelConfig[]Array of model definitions
pushobjectdisabledPush notification settings
securityobjectdisabledInstance secret and access control
serverobjectPort, public base URL, CORS, dispatch, and streaming settings
hooksHookConfig[][]Webhook endpoint definitions
autoRenameobjectLLM-based chat renaming settings

Agents

The agents array defines the AI agents available in your Opengram instance:

{
  "agents": [
    {
      "id": "assistant",
      "name": "Assistant",
      "description": "General-purpose AI assistant",
      "avatarUrl": "/avatars/assistant.png",
      "defaultModelId": "gpt-5"
    }
  ]
}
FieldTypeRequiredDescription
idstringYesUnique identifier for the agent
namestringYesDisplay name shown in the UI
descriptionstringYesShort description of what the agent does
avatarUrlstringNoURL to the agent's avatar image
defaultModelIdstringNoID of the default model (must match an entry in models)

Models

The models array defines the language models your agents can use:

{
  "models": [
    {
      "id": "gpt-5",
      "name": "GPT-5",
      "description": "OpenAI GPT-5",
      "metadata": {}
    }
  ]
}
FieldTypeRequiredDescription
idstringYesUnique identifier for the model
namestringYesDisplay name shown in the UI
descriptionstringYesShort description of the model
metadataobjectNoArbitrary key-value pairs for your agent to consume

Security

The security object controls access to your Opengram instance:

{
  "security": {
    "instanceSecretEnabled": true,
    "instanceSecret": "og_your-secret-here",
    "readEndpointsRequireInstanceSecret": false
  }
}
FieldTypeDefaultDescription
instanceSecretEnabledbooleanfalseRequire a bearer token to access the instance
instanceSecretstring""The secret token value (required when enabled)
readEndpointsRequireInstanceSecretbooleanfalseAlso protect read-only (GET) endpoints with the secret

Server

The server object controls runtime behavior:

{
  "server": {
    "port": 3000,
    "publicBaseUrl": "https://chat.example.com",
    "corsOrigins": ["https://myapp.example.com"],
    "streamTimeoutSeconds": 60,
    "idempotencyTtlSeconds": 86400
  }
}
FieldTypeDefaultDescription
portnumber3000HTTP port (1–65535)
publicBaseUrlstring"http://localhost:3000"Public URL used for links and push notifications
corsOriginsstring[][]Allowed CORS origins (must be valid HTTP/HTTPS URLs)
streamTimeoutSecondsnumber60Timeout in seconds before auto-cancelling an idle stream
idempotencyTtlSecondsnumber86400How long idempotency keys are cached (default 24 hours)
dispatchobjectMessage dispatch and queue settings (see Dispatch below)

Push notifications

Push notification settings. See Push Notifications for setup details.

{
  "push": {
    "enabled": true,
    "vapidPublicKey": "BNb...",
    "vapidPrivateKey": "x2k...",
    "subject": "https://chat.example.com"
  }
}
FieldTypeDefaultDescription
push.enabledbooleanfalseEnable web push notifications
push.vapidPublicKeystring""VAPID public key for push subscriptions
push.vapidPrivateKeystring""VAPID private key for sending push messages
push.subjectstring""VAPID subject (must be an https:// URL or mailto: address when push is enabled)

When push.enabled is true, all three key/subject fields are required. The subject field cannot contain localhost -- Apple Web Push will reject it.

Auto-rename

The autoRename object enables automatic chat title generation using an LLM:

{
  "autoRename": {
    "enabled": true,
    "provider": "openrouter",
    "modelId": "google/gemini-2.5-flash-lite",
    "apiKey": "your-api-key-here"
  }
}
FieldTypeDefaultDescription
autoRename.enabledbooleanfalseEnable automatic chat renaming after the first exchange
autoRename.providerstring""LLM provider: "anthropic", "openai", "google", "xai", or "openrouter"
autoRename.modelIdstring""Model ID to use for generating titles
autoRename.apiKeystringAPI key for the provider. Optional if the corresponding environment variable is set

When enabled is true, both provider and modelId are required. API keys can also be provided through environment variables: ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY / GOOGLE_API_KEY, XAI_API_KEY, or OPENROUTER_API_KEY.

Hooks

Webhook configuration for event-driven integrations. See Webhooks for usage details.

{
  "hooks": [
    {
      "url": "https://api.example.com/webhook",
      "events": ["message.created", "request.resolved", "request.cancelled"],
      "signingSecret": "whsec_your_secret",
      "timeoutMs": 10000,
      "maxRetries": 5
    }
  ]
}
FieldTypeDefaultDescription
urlstring(required)The URL Opengram will POST to. Must be a valid URL
eventsstring[](required)Array of event names to subscribe to
headersRecord<string, string>{}Extra headers to include in every delivery request
signingSecretstringSecret used to compute the HMAC-SHA256 signature sent in X-OpenGram-Signature
timeoutMsnumber5000Request timeout in milliseconds
maxRetriesnumber3Maximum number of retry attempts on failure

server.dispatch

Controls how chat messages are batched, queued, and delivered to agent workers. See Dispatch System for a full walkthrough.

FieldTypeDefaultDescription
server.dispatch.modestring"batched_sequential"Dispatch mode: "immediate", "sequential", or "batched_sequential"
server.dispatch.batchDebounceMsnumber600Milliseconds to wait after the last message before sealing a batch
server.dispatch.typingGraceMsnumber2000Extra grace period (ms) if the user is still typing
server.dispatch.maxBatchWaitMsnumber30000Maximum milliseconds before forcing a batch to dispatch
server.dispatch.schedulerTickMsnumber500Interval (ms) for the batch scheduler's internal tick
server.dispatch.leaseMsnumber30000Lease duration (ms) for claimed dispatches. Workers must heartbeat before this expires
server.dispatch.heartbeatIntervalMsnumber5000Recommended heartbeat interval (ms) for workers
server.dispatch.claimWaitMsnumber10000How long a claim request long-polls when no work is available
server.dispatch.retryBaseMsnumber500Base delay (ms) for exponential backoff on failed dispatches
server.dispatch.retryMaxMsnumber30000Maximum delay (ms) for exponential backoff
server.dispatch.maxAttemptsnumber8Maximum number of attempts before a dispatch is permanently failed. Minimum: 1

server.dispatch.execution

Controls autoscaling behavior for concurrent workers.

FieldTypeDefaultDescription
server.dispatch.execution.autoscaleEnabledbooleantrueWhether autoscaling is active
server.dispatch.execution.minConcurrencynumber2Minimum number of concurrent workers. Minimum: 1
server.dispatch.execution.maxConcurrencynumber10Maximum number of concurrent workers. Must be >= minConcurrency
server.dispatch.execution.scaleCooldownMsnumber5000Cooldown period (ms) before scaling down

server.dispatch.claim

Controls the claim-many endpoint behavior.

FieldTypeDefaultDescription
server.dispatch.claim.claimManyLimitnumber10Default number of batches returned by claim-many. Hard-capped at 50

Environment variable overrides

Some configuration values can be overridden by environment variables:

VariableOverrides
OPENGRAM_HOMEHome directory used by the CLI (default: ~/.opengram)
OPENGRAM_CONFIG_PATHConfig file location (overrides OPENGRAM_HOME-based path)
OPENGRAM_SERVER_PORTserver.port
OPENGRAM_PUBLIC_BASE_URLserver.publicBaseUrl
OPENGRAM_INSTANCE_SECRETsecurity.instanceSecret
OPENGRAM_CORS_ORIGINSserver.corsOrigins (comma-separated)
OPENGRAM_TRUST_PROXY_HEADERSTrust forwarded IP headers (1, true, or yes)

See the Environment Variables reference for the full list including rate-limiting variables.

Example configuration

Here is a minimal configuration with one agent and two models:

opengram.config.json
{
  "appName": "My Opengram",
  "agents": [
    {
      "id": "assistant",
      "name": "Assistant",
      "description": "General-purpose AI assistant",
      "defaultModelId": "claude-sonnet"
    }
  ],
  "models": [
    {
      "id": "claude-sonnet",
      "name": "Claude Sonnet",
      "description": "Anthropic Claude Sonnet"
    },
    {
      "id": "gpt-5",
      "name": "GPT-5",
      "description": "OpenAI GPT-5"
    }
  ],
  "server": {
    "port": 3000,
    "publicBaseUrl": "https://opengram.example.com"
  },
  "security": {
    "instanceSecretEnabled": true,
    "instanceSecret": "og_your-secret-here"
  }
}

Validation rules

  • At least 1 agent and 1 model must be configured.
  • If defaultModelIdForNewChats is set, it must reference a model ID in the models array.
  • When push.enabled is true, all VAPID fields and subject are required.
  • When security.instanceSecretEnabled is true, instanceSecret must be a non-empty string.
  • When autoRename.enabled is true, both provider and modelId are required.

On this page