Reference
Environment variables
Every variable PicoFlow and the demo application actually read, what each one does, the units that are easy to get wrong, and where the sample env file disagrees with the code.
Configuration is read once, when FlowEngine constructs a ConfigManager and calls
CoreConfig.setup(...). Values resolve in this precedence:
explicit `values` option > process.env > the dotenv file (.env by default)
A missing dotenv file is not an error. Flow model policy and session-idle policy are deliberately not read from the environment.
License
| Variable | Default | Read by | Purpose |
|---|---|---|---|
PICOFLOW_KEY |
— | CoreConfig |
The signed license token. Verified on every model run |
verifyLicense() runs at the start of each model invocation and again when the response is
processed. A missing token throws License token missing; a malformed or unsigned one throws
an invalid-license error. The result is cached after the first successful verification.
Provider credentials
| Variable | Read by | Purpose |
|---|---|---|
OPENAI_API_KEY |
CoreConfig, demo AppModule |
OpenAI adapter credentials, and OpenAI file uploads |
GEMINI_API_KEY |
CoreConfig, demo AppModule |
Google adapter credentials, and Gemini file uploads |
ANTHROPIC_API_KEY |
CoreConfig, demo AppModule |
Anthropic adapter credentials, and Claude file uploads |
OPENROUTER_API_KEY |
CoreConfig |
Loaded into CoreConfig.OpenRouterApiKey; nothing in pf/src consumes it today |
NVIDIA_API_KEY |
demo AppModule |
The demo’s application-owned NVIDIA adapter |
Provider adapters take credentials as explicit constructor options. The application passes them in — for example openai: { apiKey: config.get("OPENAI_API_KEY") }. The three keys CoreConfig reads for itself are used by LLMFileManager for provider-side file uploads, which has no adapter of its own.
MOONSHOT_API_KEY, ZAI_API_KEY, and OLLAMA_BASE_URL appear in .env-example and in
commented-out lines of the demo’s provider wiring. Nothing in pf/src or the active demo code
reads them. They become live only when you uncomment or add the corresponding
createBuiltinAdapters option.
Session store selection
| Variable | Default | Purpose |
|---|---|---|
SESSION_STORE |
MEMORY |
Selects the store. Uppercased before comparison |
Accepted values are MEMORY, SQLITE, MONGO, and COSMO or COSMOS. Anything else throws
No valid session store '<value>'. Use MEMORY, MONGO, COSMO, or SQLITE.
pico-demo/.env-example sets DOCUMENT_DB=COSMO. No code in pf/src or pico-demo/src reads DOCUMENT_DB. The variable CoreConfig actually reads is SESSION_STORE, and it does not appear in the sample file at all — so an application copied from .env-example silently runs on the in-memory store.
Store-specific settings
| Variable | Required for | Default | Purpose |
|---|---|---|---|
SQLITE_PATH |
SQLITE |
ignore/session/session.sqlite |
Database file. Relative paths resolve from the working directory; the parent directory is created if missing |
MONGODB_URL |
MONGO |
— | Connection string |
MONGODB_NAME |
MONGO |
— | Database name |
MONGODB_COLLECTION |
MONGO |
— | Collection name |
COSMODB_URL |
COSMO |
— | Account endpoint |
COSMODB_KEY |
COSMO |
— | Account key |
COSMODB_ID |
COSMO |
— | Database ID |
COSMODB_SESSION_ID |
COSMO |
— | Container ID |
The Mongo and Cosmos values are required at the moment the store is constructed or first used,
and a missing one throws Configuration value '<KEY>' is required. The Memory store needs no
configuration.
Flow-owned policies
Session stores load raw documents; a Flow decides whether a restored document is
acceptable. Use onRestoreSessionDoc() and sessionIdleMs(doc) with a code
constant when a Flow has an idle-time rule. The framework does not define a
global expiry environment variable or persist an expireAfter field.
Batch mode
| Variable | Default | Purpose |
|---|---|---|
SELF_URL |
— | Base URL used by SelfClient for concurrent worker requests |
Flow.concurrentSteps(...) posts one request per work item back to this application. Point it
at the run endpoint, for example http://localhost:8000/ai/run. Only batch coordinators need
it. Like SESSION_STORE, it is read by CoreConfig but absent from .env-example.
Test determinism
| Variable | Read by | Purpose |
|---|---|---|
HOTEL_FLOW_CURRENT_DATE |
demo ExploreStep |
Pins “today” so date-dependent hotel scenarios replay deterministically |
ExploreStep uses process.env.HOTEL_FLOW_CURRENT_DATE ?? moment().utc().format(). Any flow
whose prompts embed the current date needs an equivalent override before its scenarios can be
asserted. It is not part of .env-example.
Flow-test persistence
| Variable | Read by | Purpose |
|---|---|---|
USE_ENV=1 |
PicoDemo flow-test harness | Retains the session-store settings loaded from .env instead of forcing that test’s isolated SQLite store |
Flow tests load .env in either mode. Without USE_ENV=1, they intentionally use an isolated
SQLite database under test/.tmp; with it, they use the configured SESSION_STORE and related
settings. This is a test-harness control, not a PicoFlow runtime setting, and it does not
provide model credentials.
Sample file versus the code
| Variable | In .env-example |
Read by code | Note |
|---|---|---|---|
SESSION_STORE |
no | yes | The real store selector |
SELF_URL |
no | yes | Required for batch mode |
HOTEL_FLOW_CURRENT_DATE |
no | yes | Demo test determinism |
DOCUMENT_DB |
yes | no | Superseded by SESSION_STORE; has no effect |
MOONSHOT_API_KEY |
yes | no | Only referenced by commented-out demo wiring |
ZAI_API_KEY |
yes | no | Only referenced by commented-out demo wiring |
DEEPSEEK_API_KEY |
yes | no | nly referenced by commented-out demo wiring |
OLLAMA_BASE_URL |
yes | no | Only referenced by commented-out demo wiring |
OPENROUTER_API_KEY |
yes | partly | Loaded into CoreConfig but unused; the demo’s OpenRouter adapter is commented out |
Everything else in .env-example — the three live provider keys, NVIDIA_API_KEY,
SQLITE_PATH, the four COSMODB_* values, the three MONGODB_* values, and
PICOFLOW_KEY — matches what the code reads.
Not configurable by environment
Three things are explicit on purpose and are never read from the environment:
- Runner retry attempts.
retryAttemptsis a positive integer on aconfigModel()oruseModel(...)selection. A Step inherits its Flow value unless it sets its own; the selection is persisted with the session. - Model names and hyperparameters. These belong in
configModel()anduseModel(...), so the model plan persisted in the session document reflects what the Flow chose. See Providers. - Model-call deadlines.
timeoutMsbelongs in Flow or StepconfigLlmCallPolicy(). It is code-owned, provider-neutral, and is not persisted in the session document.