Deploy

Environment variables

Settings and secrets your app reads at run time. You set them yourself in a browser at /secrets-manager, so a secret never passes through your agent — which can only ever see their names.

An environment variable is how a setting or a secret reaches your app without living in your code — a Stripe key, a webhook URL, an admin password. agenthost stores them apart from your source and injects them into your app's environment when it runs.

You set them, not your agent. There is no tool that writes a value and no parameter for one on create_app — the omission is the feature.

A live API key should not be typed into a chat window. It would sit in the conversation, in the model's context, and in whatever your MCP client keeps — none of which is agenthost, and none of which you can clear. An interface that accepts one invites exactly that, so agenthost doesn't have one: it takes the value from you directly instead.

How to set one

Ask your agent to manage environment variables and it calls manage_env, which hands back a link:

https://agenthost.eu/secrets-manager

Open it, sign in with a code emailed to you, pick the app, and type the value into the page. It goes to agenthost over HTTPS from your browser and never touches the conversation.

The link is safe to receive

It grants nothing on its own — you still sign in. So it doesn't matter that your agent saw it, or that it's sitting in a transcript.

This is the route for ordinary settings too — a feature flag, an admin address — not just secrets. There is only the one way in, which means there is no judgement call to get wrong.

A new app starts with none

So an app that needs a key to boot will crash on its first deploy. That is expected: set the variables, and saving restarts it. Your agent can watch it come up with get_app.

What you can do there

  • Read what is set. Every value is hidden behind its own eye, one row at a time, so checking a log level doesn't put an API key on screen beside it.
  • Add one or several through the Add variable panel: a key, a value, and an optional note to yourself about where to rotate it or who to ask.
  • Change values by revealing them and editing the .env box, or paste a whole file in.
  • Remove the ones you tick.
  • Share individual ones with your agents — see below.

Saving restarts your app so the new values take effect — a few seconds of downtime. It does not rebuild it and does not touch your deployed code.

Your sign-in there is deliberately short-lived, and separate from the one that authorizes your MCP clients: reading a live key asks for a proof from minutes ago, not from some point in the last month. Expect to enter a code most times you visit.

Adding one

Add variable opens a panel with a Sensitive switch, on by default. Leave it on for anything secret; turn it off for a setting that isn't, and your agents can read that one back. The switch applies to everything you add in that panel, and you can change your mind per variable afterwards.

The note is yours — "rotate in the SendGrid dashboard", "ask ops". agenthost never reads it and never shows it to an agent; it sits under the name in the list so the next person to touch that key knows what to do with it. It survives the value being rotated.

Pasting a whole file

One NAME=value per line.

STRIPE_SECRET_KEY=sk_live_51Nx…
ADMIN_EMAIL=you@company.com
WELCOME_MESSAGE="  keeps leading spaces  "
  • Everything after the first = is the value, exactly as typed. A # is part of it, not the start of a comment — generated passwords contain them, and truncating one silently would be worse than not supporting trailing comments.
  • Wrap a value in double quotes to keep leading or trailing spaces, or to span several lines (a PEM key pastes in as-is).
  • A line starting with # is a comment, and blank lines are ignored.
  • Anything you don't mention is left alone. Removing is done with the tick boxes, not by deleting a line.

If any line can't be read, nothing is applied and the page says which line — a half-applied paste is the one outcome nobody can reason about.

Reading them in your app

The normal way for your language:

Node
const key = process.env.STRIPE_SECRET_KEY;
Python
import os
key = os.environ["STRIPE_SECRET_KEY"]
PHP
$key = getenv('STRIPE_SECRET_KEY');

Redeploying does not disturb them: they survive every deploy of the app they were set on.

What your agent can and can't see

Every variable starts secret. Your agent sees its name — as envKeys on get_app — and nothing else, however it was set and however long ago.

Not every variable deserves that, though. A log level or a feature flag is not a secret, and an agent that can read it can actually help you with it. So each row in the secrets manager has an agent can read box. Tick it, and get_env returns that variable's value; leave it, and the same call returns only its name.

You, at the secrets managerYour agent
Name of any variable
Value, marked agent can read
Value, not marked
Setting or changing a value

The default is the safe direction to be wrong in: forgetting to tick a box keeps something private, where the reverse would hand a live key to every agent you ever connect. You can change your mind either way at any time, and it doesn't disturb the value.

A variable added by pasting is secret to begin with; tick it afterwards to share it.

Not a password manager

You can read your values back here, but keep your own copy wherever you keep your other secrets. agenthost is where they run, not where they live.

What belongs in one

Belongs in an environment variableBelongs in your code
API keys, tokens, passwordsAnything a visitor can see anyway
Connection stringsLayout, copy, styling
Per-deployment settings (a webhook URL, a feature flag)Logic

Naming

Use UPPER_SNAKE_CASE. Letters, digits and underscores, starting with a letter or underscore.

A few names belong to the container and are refused: PATH, PORT, LD_PRELOAD and LD_LIBRARY_PATH. Traffic is routed to a fixed port per runtime, so PORT would not do what it looks like it does.

Databases set one for you

Attaching a database writes its connection string into your app as DATABASE_URL (or whatever name you asked for). Those show as managed and can't be edited, removed or shared there — agenthost keeps them in step with the database, and a connection string carries a password, so it stays secret. Detach the database to remove one.

.env files don't ship

.env and .env.* are excluded from the build, deliberately: a secret that reaches the build context ends up in the image. Set values as variables, not as a file.

That also means a local .env your app currently reads with dotenv will simply be absent in production. Read process.env / os.environ directly and let dotenv be a local-development convenience.