Skip to content

Credentials & logins

In short

  • Each agent CLI signs in on the server, as the account that runs the backend: a subscription login made once (codex login, claude then /login, gemini) or an API key in the backend's environment.
  • Settings → Agents and the Agent menu show where each agent's credential comes from, never the key itself.
  • Secrets for other connections live encrypted in the vault, config/vault.json; a connection refers to one as vault://<name>. Back the vault up with .secret_key.
  • Every step attempt gets a fresh ParleML token for the person who started the session, revoked when the attempt ends. Nothing to configure.

A cloud-backed session needs two kinds of credential: the CLI's login, which decides whose subscription or API account pays for the model, and the connections' credentials, which let the agent reach MCP servers. ParleML stores neither in a session.

Local inference without a cloud login

For Ollama and LM Studio, configure the provider, server URL and model in the profile editor. The workspace picker and preflight check the local server and installed model instead of the CLI's cloud login. The CLI must still be installed. See Local models with Ollama or LM Studio for setup, supported agents and guidance for CPU-only laptops. Connection credentials below still apply.

The CLI's login

Each CLI runs as the backend's operating-system user, with that user's own login or an API key from the backend's environment.

CLI Sign in on the server Or set (backend environment) How preflight checks
Claude Code run claude, then /login (subscription) ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN claude auth status
Codex codex login, with ChatGPT to use your plan OPENAI_API_KEY, CODEX_API_KEY, CODEX_ACCESS_TOKEN a key is set, else codex login status
Gemini CLI run gemini, choose Sign in with Google GEMINI_API_KEY, GOOGLE_API_KEY; or Vertex AI: GOOGLE_GENAI_USE_VERTEXAI=true with GOOGLE_CLOUD_PROJECT and Application Default Credentials a key is set; else, for Vertex AI, the project and a credentials file (GOOGLE_APPLICATION_CREDENTIALS or gcloud's default); else a saved sign-in in ~/.gemini/oauth_creds.json (or under GEMINI_CLI_HOME)
Cursor — CURSOR_API_KEY or PARLEML_AGENTS_CURSOR_API_KEY (Cursor Dashboard → Integrations) the key is set
  • A CLI process gets an allow-listed environment: system basics (PATH, HOME, locale, temp), its own credential variables above, and proxy settings. Nothing else from the backend's environment reaches it.
  • Codex ignores the user's own config.toml (--ignore-user-config) and Gemini CLI loads only the granted MCP servers, so a person's personal MCP servers on that machine do not leak into a session. Their login still applies. A profile may include the person's own settings instead, where the installation allows it (Host-native rules & hooks).
  • CLI keys are read from the process environment, not from the vault.

For a saved Codex login, run codex login and then codex login status as the account that starts the backend. If CODEX_HOME is set, use the same value for login and for the backend; the adapter forwards it to Codex. A successful CLI login establishes the credential, not a successful ParleML session: run the profile's preflight and verify an actual session separately.

Which sign-in a session uses

The same check preflight runs says, for each CLI, where its credential comes from: signed in (claude.ai), OPENAI_API_KEY is set, signed in with Google (…), or why it is not signed in. Never the key itself. It is shown

  • in the Agent menu and Home's Work with an agent, next to each agent the workspace's profile lets a person pick (GET /api/agent/agents?scope_id=…); an agent that is not signed in cannot be picked;
  • on Settings → Agents, in the Signed in with column (the admin agent catalog's login per adapter).

A CLI that does not answer within PARLEML_AGENTS_PREFLIGHT_TIMEOUT_SECONDS reads as not signed in.

Preflight runs these checks for every CLI a profile uses (its own and any skill_agents pin) before each session starts, and on Run preflight. A failed check refuses the start with 503 and names the check. A login that expires mid-session fails the attempt with login_required; the banner names the fix (for example "run codex login on this machine") and Retry continues once it is done.

Connection credentials

<data_root>/config/connections.yaml holds references, never values:

knowledge-hub:
  kind: mcp
  mcp_name: knowledge
  transport: http
  url: https://kb.example.com/mcp
  auth:
    type: bearer                       # or header, with header: X-Api-Key
    secret: vault://knowledge-hub

A vault://<name> reference names an entry in the vault, <data_root>/config/vault.json: every secret the installation stores, Fernet-encrypted with the data-root key (<data_root>/.secret_key). Settings → Connections writes the entry when someone types the secret (as vault://<connection id>); ParleML also stores installation secrets there, such as its identifier-pseudonymisation key. No API returns the secret values.

  • The value is read at the moment it is needed (a session start or resume, preflight, Test), fresh each time, so a new secret needs no restart and never blocks a resume.
  • It is never written to run.json, returned by the admin API, or put on a command line (how it reaches the CLI).
  • A reference with no value fails preflight ("has no value in the vault") instead of sending an empty header.
  • Back up vault.json together with .secret_key; one without the other cannot be read.

How a secret reaches the CLI

Details: environment variables, not arguments

CLIs get the secret in their environment under a generated PARLEML_MCP_* name, and their MCP configuration names the variable: Claude Code's per-attempt --mcp-config file (${PARLEML_MCP_…}, in the run's directory, never the work directory), Codex's env_http_headers, Gemini CLI's settings file. Codex's shell policy hides the variables from the agent. A Claude Code session granted Bash can read them.

ParleML's own MCP: minted tokens

The parleml connection uses auth: {type: minted, provider: parleml}. Instead of a stored secret, every attempt gets a fresh ParleML API token:

  • for the person who started the session, so an agent can never do more than they can;
  • scoped by the skill's parleml-scope: analyst (default), compute or builder, a builder token bound to the session's workspace;
  • named "agent session … · step … · attempt n", so the token list shows where it came from;
  • expiring at the attempt's wall-clock cap and revoked when the attempt ends;
  • recorded in provenance/<token_id>.json before the agent gets it.

A ParleML token is minted only for ParleML's own /mcp. The connection URL must have the same origin and path as <origin of PARLEML_AGENTS_SESSION_MCP_URL>/mcp. Pointed anywhere else, the provider refuses to mint; preflight reports "will not mint for connection …" and sessions do not start. The backend logs a warning at boot when the parleml connection does not point at this server. Fix the URL in Settings → Connections. The parleml connection is built in: it cannot be deleted, and the backend writes it again when it is missing.

Tokens for your own agent

Agents you run yourself (Claude Desktop, Cursor, Codex, …) connect with a token from Settings → Access (administrators mint them) or through OAuth; see Tokens & scopes. These tokens are separate from session tokens, and what they create reports kind: token in provenance. API tokens never drive sessions: the session routes accept signed-in people only.

Next