# The instance's assistants (Halkyon Learn's ADR 0021, points 4 and 8, D37, D38, D63): # copy to deploy/assistants.env, restrict it (chmod 600), and fill in. It is git-ignored, # goes to Halkyon Learn's server alone (compose.learn.yaml, `env_file`), never into an image, # the database or its backups; keep it with deploy/.env's secrets (in Proton Pass). # Without the file, the instance offers no assistant, as before. A change takes a # restart: docker compose up -d server. Anything the server can't use stops it as it # starts, naming the variable. # # Nobody has an assistant until an operator grants it to them in the app, with a budget # per day and month for all their assistants together, in money and in tokens (D58, # D59); each person agrees once to what goes where. The instance keeps what each person # used (requests, tokens, cost) per day for 3 months, never what was asked. # The assistants' IDs, in the order people see them, by commas or spaces: a letter, # then letters, digits or _. Each names its variables below (claude: ASSISTANT_CLAUDE_…) # and its grants; renaming one leaves its grants unused. ASSISTANTS=claude # The key the providers' opaque IDs of people are made with (D30): each request carries # one, so a provider can act against one person's abuse without blocking the key, and # can't tell who it is. At least 32 characters; a new one gives everyone a new ID. # Generate: openssl rand -hex 32 ASSISTANT_ID_KEY= # The name people see; the ID if unset. ASSISTANT_CLAUDE_NAME=Claude Sonnet # anthropic (Anthropic's Messages API), openai (OpenAI's chat completions, and every # service compatible with them: Mistral, Gemini, OpenRouter, Ollama, vLLM, llama.cpp), # or openai-responses (OpenAI's Responses API, which OpenAI's newest models need for # tools; Ollama, vLLM and OpenRouter speak it too). ASSISTANT_CLAUDE_PROTOCOL=anthropic # The provider's address; unset: its own (https://api.anthropic.com, or # https://api.openai.com/v1 for both of OpenAI's). With /v1 for the OpenAI protocols # (https://api.mistral.ai/v1, https://openrouter.ai/api/v1, # https://generativelanguage.googleapis.com/v1beta/openai), without it for Anthropic's. # https only, but for a model on this machine or network (http://ollama:11434/v1). #ASSISTANT_CLAUDE_BASE_URL= ASSISTANT_CLAUDE_MODEL=claude-sonnet-5-5 # The operator's key at the provider; may be unset only with a BASE_URL of a server of # one's own that takes none. ASSISTANT_CLAUDE_KEY= # on: people may add images (a card's picture, a PDF page) for a model that reads them. #ASSISTANT_CLAUDE_IMAGES=on # What the model costs per million tokens, as the provider bills it, in # ASSISTANT_CURRENCY, with a point for decimals: both or none. With prices, it counts # against a budget's money and tokens; without, against its tokens alone. A change # counts from then on. #ASSISTANT_CLAUDE_PRICE_INPUT=2 #ASSISTANT_CLAUDE_PRICE_OUTPUT=10 # How much the model thinks before it answers: low, medium, high, xhigh or max # (Anthropic's names, sent in each provider's own field; Gemini takes low to high, # Mistral none). EFFORT is what a question takes unless the person picks one; # MAX_EFFORT the highest they may pick (unset: EFFORT). Both unset: the model's own, # and nothing to pick. More effort spends more tokens, at the same price per token, and # leaves more room for the answer (8,192 tokens at low to 65,536 at max). #ASSISTANT_CLAUDE_EFFORT=medium #ASSISTANT_CLAUDE_MAX_EFFORT=high # A second one, through OpenAI's Responses API: #ASSISTANTS=claude gpt #ASSISTANT_GPT_NAME=GPT #ASSISTANT_GPT_PROTOCOL=openai-responses #ASSISTANT_GPT_MODEL= #ASSISTANT_GPT_KEY= # The currency of the prices (ISO 4217); unset: USD, as the providers bill. #ASSISTANT_CURRENCY=USD # on: people may add their own keys in the app, which then calls their provider # directly; the instance sees neither key nor question and counts nothing (D5, D6). #ASSISTANT_OWN_KEYS=on