Configuration¶
Copy .env.minimal for the Telegram golden path or .env.example for all
documented options. Keep .env private.
Required values¶
AGENT_NAME
: Required unique service identifier. Compose fails during interpolation when it is absent.
One model API key
: Set OPENROUTER_API_KEY or GOOGLE_API_KEY. Startup validation fails when
both are absent.
An explicit ROOT_AGENT_MODEL is strongly recommended so provider routing does
not depend on a default.
Docker Compose host settings¶
These values are consumed by Compose rather than ServerEnv.
| Variable | Default | Purpose |
|---|---|---|
HOST_PORT |
8080 |
Host-side port |
RESTART_POLICY |
unless-stopped |
Compose restart policy |
IMAGE |
blacki:local |
Image name or verified registry reference |
ENV_FILE |
.env |
File injected into the container |
HOST and PORT are different: they control the process inside the container.
Compose sets them to 0.0.0.0 and 8080; the supported overlays publish only
to host loopback and HOST_PORT selects that loopback port.
Server¶
| Variable | Default | Purpose |
|---|---|---|
AGENT_NAME |
None | Required identity for the service and telemetry |
LOG_LEVEL |
INFO |
DEBUG, INFO, WARNING, ERROR, or CRITICAL |
HOST |
127.0.0.1 |
Process bind address outside Compose |
PORT |
8080 |
Process port outside Compose |
AGENT_DIR |
src |
ADK agents and local-state base directory |
SERVE_WEB_INTERFACE |
false |
Enable the ADK development web interface |
RELOAD_AGENTS |
false |
Reload agent definitions; development only |
ALLOW_ORIGINS |
local origins JSON | JSON array of CORS origins |
AGENT_ENGINE |
unset | Optional Agent Engine identifier |
SQLITE_PATH |
{AGENT_DIR}/.adk/tools.db |
SQLite file for application tools |
For ALLOW_ORIGINS, use a JSON array string:
ALLOW_ORIGINS=["http://127.0.0.1","http://127.0.0.1:8080"]
Model providers¶
ROOT_AGENT_MODEL=openrouter/google/gemini-2.5-flash
OPENROUTER_API_KEY=replace-me
Blacki builds a LiteLLM model and normalizes common model identifiers to OpenRouter form when this key is present.
Set ROOT_AGENT_REASONING_EFFORT to configure the process-wide reasoning
fallback. Supported values are max, xhigh, high, medium, low,
minimal, and none; leave it unset to inherit the provider default.
A Telegram chat's explicit thinking selection overrides this fallback for
that chat. Only configure an effort advertised by the selected model.
ROOT_AGENT_MODEL=gemini-2.5-flash
GOOGLE_API_KEY=replace-me
Do not leave a fake OPENROUTER_API_KEY active in a Google-only configuration;
its presence changes model routing.
Telegram¶
| Variable | Default | Purpose |
|---|---|---|
TELEGRAM_ENABLED |
false |
Start Telegram long polling |
TELEGRAM_BOT_TOKEN |
unset | Token from BotFather |
TELEGRAM_TOOL_NOTIFICATIONS |
false |
Send short tool-use notices |
KOKORO_TTS_BASE_URL |
unset | Register private Kokoro speech delivery for Telegram |
KOKORO_TTS_VOICE |
af_heart |
Kokoro voice ID used for generated MP3 audio |
The token is required and format-validated when Telegram is enabled.
KOKORO_TTS_BASE_URL is an optional HTTP or HTTPS base URL without a path to
/v1/audio/speech; Blacki appends that fixed endpoint. The URL must be
reachable from inside the Blacki container. Do not use localhost for a
Kokoro process on another Tailscale host; configure that host's Tailscale IP or
MagicDNS name instead. Plain HTTP is suitable only across a trusted private
network such as the encrypted Tailscale connection.
Search and browser tools¶
| Variable | Default | Purpose |
|---|---|---|
EXA_API_KEY |
unset | Primary Exa search integration |
BRAVE_SEARCH_API_KEY |
unset | Brave search fallback |
BROWSER_USE_API_KEY |
unset | Browser Use Cloud automation |
These integrations are optional. Their absence should not replace the required model key.
Mem0 memory¶
Mem0 is optional. The current samples support:
MEM0_LLM_PROVIDER,MEM0_LLM_MODEL,MEM0_LLM_API_KEY,MEM0_LLM_TEMPERATURE, andMEM0_LLM_MAX_TOKENS;MEM0_EMBEDDER_PROVIDER,MEM0_EMBEDDER_MODEL,MEM0_EMBEDDER_DIMS, andMEM0_EMBEDDER_API_KEY;MEM0_USER_ID,MEM0_COLLECTION_NAME, andMEM0_SEARCH_LIMIT;- Qdrant Cloud through
MEM0_QDRANT_URLandMEM0_QDRANT_API_KEY; - local embedded Qdrant through
MEM0_QDRANT_PATH; or - a remote server through
MEM0_QDRANT_HOSTandMEM0_QDRANT_PORT.
Compose mounts ./data at /app/data. Use a path under /app/data for local
memory that must persist:
MEM0_QDRANT_PATH=/app/data/qdrant
If Qdrant Cloud values are present, the provider stores the vectors remotely.
Delegated task worker¶
| Variable | Default | Purpose |
|---|---|---|
TASK_WORKER_ENABLED |
true |
Register a same-privilege ADK task worker |
By default, the root agent can delegate one complex task at a time to a
registered ADK task-mode child. Set TASK_WORKER_ENABLED=false to opt out. The
worker receives an independently built copy of the root agent's user-facing
toolset and shares the same ADK session state, so sandbox tools reconnect to the
same sandbox ID.
This is not a security boundary or a background worker pool: the worker has the root agent's privileges, runs within the request, and cannot delegate recursively. Delegation can add another model and tool turn, increasing latency and model usage.
OpenSandbox¶
| Variable | Default | Purpose |
|---|---|---|
SANDBOX_ENABLED |
false |
Register code-execution tools |
SANDBOX_DOMAIN |
localhost:9090 |
OpenSandbox server address |
SANDBOX_API_KEY |
unset | Optional server credential |
SANDBOX_TIMEOUT_MINUTES |
30 |
Sandbox lifetime |
SANDBOX_MEMORY_LIMIT |
512Mi |
Per-sandbox memory setting |
SANDBOX_CPU_LIMIT |
0.5 |
Per-sandbox CPU setting |
SANDBOX_IMAGE |
project default | Code-interpreter image |
Running a local OpenSandbox server adds Docker and resource requirements beyond the Blacki golden path.
Zepto MCP¶
| Variable | Default | Purpose |
|---|---|---|
ZEPTO_MCP_ENABLED |
false |
Enable the root-only Zepto skill after OAuth |
ZEPTO_MCP_ALLOWED_TELEGRAM_CHAT_IDS |
unset | Comma-separated positive private chat IDs allowed to use the shared account |
ZEPTO_MCP_CONFIG_DIR |
data/credentials/zepto-mcp-remote |
Permission-protected bridge credential directory shared by host and container |
The allowlist deliberately rejects Telegram groups, topics, and arbitrary HTTP user IDs. All allowed chats share one Zepto account and cart. Complete the one-time OAuth flow before enabling the integration; see Zepto MCP.
Observability¶
| Variable | Default | Purpose |
|---|---|---|
TELEMETRY_NAMESPACE |
local |
OpenTelemetry service namespace |
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT |
false |
Allow instrumentors to capture message content |
ADK_CAPTURE_MESSAGE_CONTENT_IN_SPANS |
false |
Allow legacy ADK spans to capture prompts and tool data |
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT |
unset | Preferred complete trace collector URL |
OTEL_EXPORTER_OTLP_ENDPOINT |
unset | Global collector URL fallback; HTTP adds /v1/traces |
OTEL_EXPORTER_OTLP_TRACES_PROTOCOL |
grpc |
Preferred trace protocol: grpc or http/protobuf |
OTEL_EXPORTER_OTLP_PROTOCOL |
grpc |
Global protocol fallback |
OTEL_EXPORTER_OTLP_TRACES_HEADERS |
unset | Preferred trace authentication headers |
OTEL_EXPORTER_OTLP_HEADERS |
unset | Global authentication-header fallback |
Blacki always exports spans to local JSON. A validated trace-specific or global endpoint adds gRPC or HTTP/protobuf OTLP export; trace-specific values take precedence. See Observability.
When Zepto is enabled, Blacki forces both content-capture variables to false
and disables the OpenInference Google ADK instrumentor because it otherwise
records raw tool parameters.
Precedence¶
For Docker Compose:
- shell values and
--env-filedrive Compose interpolation; - the service's
environmentmapping overrides matchingenv_filevalues; - remaining values come from
ENV_FILE, which defaults to.env.
For local Python, initialize_environment loads the nearest .env with
override=True, so values in that file can replace existing process values.
Secret handling¶
- Keep
.envout of Git; it is already ignored. - Run
chmod 600 .envon a multi-user VPS. - Never include secrets in
docker compose configoutput shared with others. - Rotate a token immediately if it appears in Git, logs, an issue, or chat.
- Prefer provider-scoped, least-privilege credentials.