Reference
Configuration
The defaults are chosen so npm run dev works with nothing set. They are also chosen so that nothing survives a restart. That is the right trade on a laptop and the wrong one everywhere else, and the boot banner tells you which one you are in.
The four that decide whether this is real
| Var | Unset means |
|---|---|
MYCEL_DATABASE_URL | Everything in memory: tasks, events, tenants, vault, audit. No queue — queue=inline, tasks run in the API process |
MYCEL_SECRET_KEY | An ephemeral vault key. Every stored credential is unreadable after a restart |
MYCEL_SANDBOX | local unless DAYTONA_API_KEY is set. Local is a temp directory on your host, not isolation |
MYCEL_API_KEY | A new key printed on every boot, so your product breaks on every restart |
Nothing here fails loudly if you skip it. The boot line is the check: [sandbox=… store=… model=… queue=…].
Identity and access
| Var | Default | Purpose |
|---|---|---|
MYCEL_API_KEY | generated, msk_… | Default project key for your product |
MYCEL_OWNER_EMAIL | founder@mycel.local | Bootstrap owner account |
MYCEL_OWNER_PASSWORD | generated, own_… | Portal login |
MYCEL_GATE_TOKEN | random per process | Shared secret for the sandbox plugin gate. Fix it if sandboxes outlive the process |
MYCEL_RATE_MAX | 120 | Task creations per minute per credential |
Storage
| Var | Default | Purpose |
|---|---|---|
MYCEL_DATABASE_URL | — | Postgres for tasks, events, tenants, vault, audit, and the graphile-worker queue. Migrations run on boot |
MYCEL_SECRET_KEY | ephemeral | AES-256-GCM master key. Hex or base64, must decode to exactly 32 bytes |
MYCEL_ARTIFACTS | inline | inline | fs | s3 |
MYCEL_ARTIFACTS_DIR | .mycel/artifacts | For fs |
MYCEL_ARTIFACTS_BUCKET | — | For s3. Needs @aws-sdk/client-s3 installed |
MYCEL_LOG_DIR | .mycel/logs | Per-task JSONL event logs and llm.jsonl. Always on |
head -c 32 /dev/urandom | base64 # a valid MYCEL_SECRET_KEY
Execution
| Var | Default | Purpose |
|---|---|---|
MYCEL_RUNTIME | opencode | Exactly mock selects the mock runtime. Anything else is OpenCode |
MYCEL_SANDBOX | daytona if DAYTONA_API_KEY, else local | local | docker | daytona. Not validated — a typo silently gives you local |
MYCEL_SANDBOX_IMAGE | mycel/sandbox:latest | Image for docker and daytona |
OPENCODE_PORT | 4444 | OpenCode server inside the sandbox |
MYCEL_WEDGES_DIR | <cwd>/wedges | Where wedge folders are read from |
MYCEL_BLUEPRINTS_DIR | <cwd>/blueprints | Where blueprint JSON is read from |
MYCEL_WORKFLOW_TIMEOUT_MS | 5000 | Per-workflow timeout |
MYCEL_WORKER | on | 0 gives an API-only replica |
MYCEL_WORKER_CONCURRENCY | 10 | Concurrent runs per worker. Each run holds a sandbox, so memory is the limit |
PORT | 4000 | Kernel listen port |
Models, cost and the proxy
| Var | Default | Purpose |
|---|---|---|
MYCEL_MODEL | anthropic/claude-opus-4-8 | Fallback model. A wedge's model wins, and input.model on a task wins over that |
MYCEL_PROXY_MODE | off | 1 routes model calls through the harness so the provider key never enters the sandbox |
MYCEL_LLM_UPSTREAM | derived from the provider | Override the OpenAI-compatible upstream base URL |
MYCEL_PUBLIC_URL | http://127.0.0.1:4000 | How the sandbox reaches the harness. Docker needs host.docker.internal; Daytona needs a reachable URL |
MYCEL_MAX_COST_USD | 50 | Server ceiling per task; client constraints are clamped to it |
MYCEL_MAX_RUNTIME_S | 1800 | Server runtime ceiling |
MYCEL_MAX_TOKENS | 8192 | Cap on max_tokens the sandbox may request through the proxy |
MYCEL_READ_MAX_PER_TASK | 200 | Ungated reads per task |
Provider keys themselves — ANTHROPIC_API_KEYand friends — are read from the environment by name derived from the model's provider prefix.
Integrations and tracing
| Var | Default | Purpose |
|---|---|---|
COMPOSIO_API_KEY | — | Without it every Composio route returns 501 |
COMPOSIO_BASE_URL | https://backend.composio.dev | Composio REST base |
DAYTONA_API_KEY | — | Remote sandboxes. Its presence alone changes the default MYCEL_SANDBOX |
LANGFUSE_SECRET_KEY / LANGFUSE_PUBLIC_KEY | — | Both required, or the Langfuse sink stays off |
LANGFUSE_HOST | https://cloud.langfuse.com | Self-hosted Langfuse |
Tracing needs no configuration. The kernel writes a durable event row for everything a run does, and GET /v1/tasks/:id/trace folds that log into a span tree — steps, tool calls with redacted arguments, generations, approvals, timings and cost. It is always there, it is scoped exactly like the task, and no third party sees it.
The LANGFUSE_* keys above are separate and entirely optional: your account, for when you want an LLM-debugging UI over your own runs. Install it yourself (npm install langfuse) — if the keys are set but the package is not installed the kernel warns rather than pretending. Nothing provisions a Langfuse project per business: that needs Langfuse's Organization Management API, which is self-hosted Enterprise only and does not exist on Langfuse Cloud, so the code that tried was removed.
Your product
MYCEL_KERNEL_URL— where the kernel is, e.g.http://localhost:4000MYCEL_API_KEY— server-side only. Never a build argument: Next inlines build-time env into the client bundle
Failure modes
MYCEL_SECRET_KEY must be 32 bytes (got N)— the kernel refuses to start rather than sealing secrets with the wrong key.- Secrets unreadable after a deploy. The key changed. The log names the key fingerprint that sealed them.
- Sandbox cannot reach the harness.
MYCEL_PUBLIC_URLstill points at127.0.0.1from inside a container. - Runs are serialised and slow.
queue=inlinein the banner — noMYCEL_DATABASE_URL, so there is no queue. - Mock runtime not taking effect. Only the exact string
mockmatches.
What to read next
Deploying — which of these become non-negotiable once the kernel is not on your laptop.