-
Notifications
You must be signed in to change notification settings - Fork 1
Managing Operational Settings
Operational settings are stored in the system_settings database table, seeded from built-in registry defaults on first run, and fully manageable at runtime through the admin API. You do not need to restart the server to change them (with the exception of a small number of static settings — see Hot vs. Static Settings below).
This page covers the runtime workflow: reading and writing settings through the admin API, understanding what takes effect immediately, reconfiguring the Timmy AI subsystem and content sources without a restart, migrating YAML config into the database, and rotating encryption keys.
Out of scope: Bootstrap settings (database connection, JWT secret, server port, TLS, logging, etc.) are resolved from config files and environment variables at startup and require a restart to change. They are never stored in system_settings. See Configuration-Model for the full bootstrap/operational split, and Bootstrapping-Production for bootstrap setup.
All endpoints require the administrator role. Send a Bearer JWT in the Authorization header.
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/admin/settings |
List all settings with their effective values and source |
GET |
/admin/settings/{key} |
Get one setting and its effective source |
PUT |
/admin/settings/{key} |
Create or update a setting in the database |
DELETE |
/admin/settings/{key} |
Delete a setting from the database |
POST |
/admin/settings/reencrypt |
Re-encrypt all stored secrets under the current key |
Every GET response includes a source field that tells you where the effective value comes from:
| Source | Meaning |
|---|---|
database |
Value was written to system_settings via the API or dbtool |
config |
Value came from a config file at startup (unusual for operational settings) |
environment |
Value came from a TMI_* environment variable |
TMI applies a still-live environment > config > database precedence to operational settings, not just to bootstrap settings. For a fully operational setting, you should see database after initial seeding. If you see config or environment, a config-file or environment-variable value for that same operational key is overriding the database row — its read value comes from env/config rather than the DB.
When a key is config- or environment-controlled, it cannot be edited through the admin API. PUT /admin/settings/{key} returns 409 Conflict with a message like Setting '<key>' is controlled by <source> and cannot be modified via the API. To make the key editable again, remove the overriding environment variable or config-file entry for that key; once it falls back to the database, the DB value becomes editable via the API.
Settings that are marked as secrets (API keys, client secrets, etc.) are masked in all API responses. The response body will contain a redacted placeholder, not the live value. Use POST /admin/settings/reencrypt to rotate keys, not GET to retrieve them.
A PUT request with an empty string value for a string setting is rejected with a 400 error. An empty string would be stored as a NULL CLOB on Oracle, violating the column's NOT NULL constraint. If you need to effectively disable a setting, delete it (DELETE /admin/settings/{key}) to fall back to the registry default, or set it to a meaningful sentinel value.
List all settings:
curl -s http://localhost:8080/admin/settings \
-H "Authorization: Bearer $TOKEN" | jq .Read one setting:
curl -s http://localhost:8080/admin/settings/timmy.enabled \
-H "Authorization: Bearer $TOKEN" | jq .Update a setting:
curl -s -X PUT http://localhost:8080/admin/settings/timmy.enabled \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"value": "true"}'Delete a setting (reverts to registry default on next read):
curl -s -X DELETE http://localhost:8080/admin/settings/timmy.llm_provider \
-H "Authorization: Bearer $TOKEN"Operational settings have a mutability property:
| Mutability | Behavior after PUT /admin/settings/{key}
|
|---|---|
| hot | The new value is picked up at the next use. No restart required. |
| static | The database row is updated immediately, but the running server keeps the value it read at boot until you restart. |
When you update a static setting, TMI writes the new value to the database and returns success — but the change does not take effect in the running process. Restart the server after editing a static setting to activate it.
See Configuration-Reference for the mutability column of each setting.
Most operational settings are hot. This section covers the subsystems that benefit most from live reconfiguration.
The entire Timmy AI assistant is DB-backed and hot. Every aspect of Timmy's configuration — whether it is on or off, which model and provider it uses, its API keys, and its tuning knobs — can be changed through the admin API with no restart.
Toggling Timmy on or off:
# Disable
curl -s -X PUT http://localhost:8080/admin/settings/timmy.enabled \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"value": "false"}'
# Re-enable
curl -s -X PUT http://localhost:8080/admin/settings/timmy.enabled \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"value": "true"}'Switching model or provider:
curl -s -X PUT http://localhost:8080/admin/settings/timmy.llm_provider \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"value": "openai"}'
curl -s -X PUT http://localhost:8080/admin/settings/timmy.llm_model \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"value": "gpt-4o"}'When you change the provider, model, API key, or base URL, Timmy rebuilds its internal client on the next incoming request — no restart, no dropped connections.
Rotating a Timmy API key:
curl -s -X PUT http://localhost:8080/admin/settings/timmy.llm_api_key \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"value": "sk-new-key-value"}'The key is encrypted at rest. After writing, call POST /admin/settings/reencrypt if you are also rotating the encryption key (see Rotating the Encryption Key).
Adjusting tuning knobs (top-k, timeouts, rate limits, history depth, embedding dimension) works the same way — each knob is a separate key under timmy.*. Tuning changes are read live per request; there is no rebuild step.
The content-source registry and access poller are also DB-backed and runtime-tunable. You can enable or disable individual content sources and toggle the access poller without restarting the server. Use GET /admin/settings to identify the relevant content.* keys, then PUT /admin/settings/{key} to change them.
If you are upgrading from a pre-1.4.0 deployment whose operational settings were in a YAML config file, use tmi-dbtool to import those settings into the database. After migration, manage them at runtime via the admin API.
make build-dbtool # PostgreSQL
make build-dbtool-oci # Oracle ADBUse this when your existing YAML file contains operational settings mixed in with bootstrap settings (the pre-1.4.0 layout).
1. Preview what will happen:
tmi-dbtool --import-legacy \
--input-file config-production.yml \
--config config-production.yml \
--dry-runThe dry-run output shows which settings would be written to system_settings and which are bootstrap-only (and will stay in the file).
2. Run the import:
tmi-dbtool --import-legacy \
--input-file config-production.yml \
--config config-production.ymlBy default the tool:
- Writes a timestamped backup of the source file before modifying it.
- Rewrites the source file in place, leaving only bootstrap settings.
- Writes operational settings to the database; existing DB rows for those keys are skipped (not overwritten) to protect any runtime edits you have already made via the API.
Preserve the original file unchanged (write a sibling instead):
tmi-dbtool --import-legacy \
--input-file config-production.yml \
--config config-production.yml \
--no-rewriteThis writes config-production-migrated.yml alongside the original and leaves config-production.yml untouched. The two flags --no-rewrite and --output are mutually exclusive.
Skip the automatic backup:
tmi-dbtool --import-legacy \
--input-file config-production.yml \
--config config-production.yml \
--no-backupOnly use this if you are managing your own backup strategy.
Use this to bulk-load settings from any YAML file into the database — for example, to seed a new environment from a reference config or to restore settings from a snapshot.
# Dry run first
tmi-dbtool --import-config \
--input-file settings-snapshot.yml \
--config config-production.yml \
--dry-run
# Write to DB (skip existing rows by default)
tmi-dbtool --import-config \
--input-file settings-snapshot.yml \
--config config-production.yml \
--output settings-snapshot-migrated.ymlOverwrite behavior: by default, a key that already exists in system_settings is left unchanged. This protects any runtime edits made via the admin API. Pass --overwrite to replace existing values with the file values:
tmi-dbtool --import-config \
--input-file settings-snapshot.yml \
--config config-production.yml \
--overwriteUse --overwrite deliberately — it will discard any changes operators have made since the last config file snapshot.
If your bootstrap config has a secrets.* provider configured, tmi-dbtool initializes the encryptor automatically during import. Settings marked as secrets are encrypted at rest when written to system_settings. No extra flags are needed; the encryptor picks up its configuration from the file passed to --config.
| Flag | Purpose |
|---|---|
-c, --import-config |
Import a config file into the database |
-l, --import-legacy |
Import a pre-1.4.0 legacy config file |
-f, --input-file FILE |
Source YAML file |
--config FILE |
Bootstrap config file providing the DB connection (database.url) |
--output FILE |
Write the post-migration config to this path (with -c or -l) |
--dry-run |
Show what would happen without writing anything |
--overwrite |
Replace existing DB rows (with -c); default is to skip them |
--no-backup |
Skip the timestamped backup of the source file (with -l) |
--no-rewrite |
Write a sibling *-migrated.yml and leave the source unchanged (with -l) |
-v, --verbose |
Verbose output |
Secret operational settings (API keys, OAuth client secrets, etc.) are encrypted at rest in system_settings. When you rotate the encryption key in your secrets provider, re-encrypt the stored values with the new key:
curl -s -X POST http://localhost:8080/admin/settings/reencrypt \
-H "Authorization: Bearer $TOKEN"This re-reads every secret setting, decrypts it with the old key, and re-encrypts it under the current key (as configured in the running server's secrets.* bootstrap config). The operation is atomic per setting. If it fails partway through, repeat the call — settings that were already re-encrypted under the new key will be skipped or safely overwritten.
Update your secrets provider with the new key before calling reencrypt, not after.
- Configuration-Model — the bootstrap/operational split, hot vs. static, visibility, and the full resolution flow
- Configuration-Reference — per-key listing with category, mutability, visibility, and description
- Bootstrapping-Production — bootstrap config files, secret references, and initial server setup
-
Database-Tool-Reference — complete reference for all
tmi-dbtoolcommands and flags
- Using TMI for Threat Modeling
- Accessing TMI
- Authentication
- Identity Linking
- Creating Your First Threat Model
- Understanding the User Interface
- Working with Data Flow Diagrams
- Managing Threats
- Collaborative Threat Modeling
- Using Notes and Documentation
- Timmy AI Assistant
- Metadata and Extensions
- Planning Your Deployment
- Terraform Deployment (AWS, OCI, GCP, Azure)
- Deploying TMI Server
- OCI Container Deployment
- Certificate Automation
- Deploying TMI Web Application
- Setting Up Authentication
- Database Setup
- Bootstrapping Production
- Component Integration
- Post-Deployment
- Branding and Customization
- Monitoring and Health
- Cloud Logging
- Configuring Local Development
- Managing Operational Settings
- Content Extractors - Limits and Overrides
- Database Operations
- Database Security Strategies
- Transaction Isolation
- Oracle Content Feedback FK Cleanup
- Security Operations
- Performance and Scaling
- Maintenance Tasks
- Getting Started with Development
- Local Development Cluster
- Architecture and Design
- API Integration
- Testing
- Contributing
- Extending TMI
- Dependency Upgrade Plans
- DFD Graphing Library Reference
- Migration Instructions
- Issue Tracker Integration
- Webhook Integration
- Addon System
- MCP Integration
- Delegated Content Providers
- Setting Up Google Content Providers
- API Clients
- API Client Maintenance
- Database Tool Reference
- TMI Terraform Analyzer
- TMI Promtail Logger
- WebSocket Test Harness