Self-hosting and operations
Who can sign up: SIGNUP_MODE
| Mode | Who can get in | Who can create organizations |
|---|---|---|
invite (default) | Only people with a live invitation | Only addresses in TEST_ADMIN_EMAILS |
approval | Anyone can create an account, but signing in needs an existing membership, a live invitation, a TEST_ADMIN_EMAILS address, or a signup approval | Approved people, up to the number on their approval (default 1) |
open | Anyone | Anyone, up to MAX_ORGANIZATIONS_PER_USER (default 5) |
In approval mode, someone without access sees: "This account does not have
access to CreateOS Studio yet. You can sign in once it is approved." The check
applies to every sign-in method: email code, Google and SSO.
Background jobs
| Job | Does | How it runs |
|---|---|---|
POST /api/cron/workflow-schedule-tick | Starts due workflow schedules | Built in, every 60 s |
POST /api/cron/workflow-sweep | Repairs interrupted workflow runs | Built in, every 5 min |
POST /api/cron/rag-sweep | Finishes interrupted uploads and pending knowledge base processing | External scheduler, every few minutes |
POST /api/cron/agent-deployments | Resumes queued or failed Slack events | External scheduler, every minute |
Every cron call must send the header x-cron-secret: $CRON_SECRET. While
CRON_SECRET is unset, every cron endpoint refuses all requests. Paths are under
the app base path (default /studio).
Configuration by feature
| Feature | Needs |
|---|---|
| Core | DATABASE_URL, REDIS_URL, BETTER_AUTH_SECRET, BETTER_AUTH_URL, CORS_ORIGIN, TRUSTED_ORIGINS, SECRET_VAULT_KEY_ID, SECRET_VAULT_KEY |
| Agent runtime | EVE_RUNTIME_URL, EVE_INTERNAL_API_SECRET, CREATEOS_INTERNAL_URL |
| Model Gateway | OMNIROUTE_BASE_URL, OMNIROUTE_MANAGEMENT_API_KEY |
| Email (sign-in codes, invitations, approval emails) | SMTP_URL, EMAIL_FROM |
| Google sign-in | GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET (enabled only when both are set) |
| Tools | COMPOSIO_API_KEY |
| Knowledge bases | DATALAB_API_KEY, QDRANT_URL, QDRANT_API_KEY, object storage (OBJECT_STORAGE_PROVIDER = aws, azure or gcs, with its credentials) |
| Logos and avatars | A public S3-compatible bucket, PUBLIC_MEDIA_S3_* |
| Workflows | WORKFLOW_POSTGRES_URL (required outside development), CRON_SECRET; optional STUDIO_WORKFLOW_QUEUE_CONCURRENCY and STUDIO_WORKFLOW_POOL_SIZE (default 30 each) |
| Workflow assistant | WORKFLOW_ASSISTANT_MODEL_API_KEY (turns it on), WORKFLOW_ASSISTANT_MODEL_ID, WORKFLOW_ASSISTANT_MODEL_BASE_URL, WORKFLOW_ASSISTANT_NODE_MODEL_ID |
| Agent builder assistant | AGENT_BUILDER_MODEL_API_KEY (turns it on), AGENT_BUILDER_MODEL_ID, AGENT_BUILDER_MODEL_BASE_URL |
| Slack | A scheduled agent-deployments cron. For local or preview builds, NEXT_PUBLIC_SLACK_CALLBACK_BASE (public HTTPS origin including the base path). |
| Public API, MCP and Slack rate limit | STUDIO_API_KEY_REQUESTS_PER_MINUTE (default 60) |
| Base path | NEXT_PUBLIC_BASE_PATH (default /studio) |
Ingress
Besides the app under its base path, forward these root paths to Studio:
/mcp, the MCP server/api/v1/agents/*, the Public API (other/api/v1/*routes are not Studio's)/.well-known/*, OAuth discovery for MCP clients
Rate limits at a glance
| What | Limit |
|---|---|
| Starting runs via an API key, an MCP connection, or a Slack connection | STUDIO_API_KEY_REQUESTS_PER_MINUTE each (default 60/min) |
| Slack messages posted | 1 per second per channel |
| Sign-in, sign-up and code sending | Expected to be limited at the edge (e.g. Cloudflare) in front of Studio |
| Sign-in codes | Valid 5 minutes, 3 attempts |
| Sessions | 7 days, refreshed daily |
Health check
GET /studio/api/version returns {"status":"ok"} and is never cached. Use it
for liveness probes.