Credentials & Connectors
Applies to SDK 0.16+ · Last updated: 2026-06-12
AgentNode keeps your API keys on your own machine — in the OS keychain when one is available, otherwise a local file with owner-only permissions. Keys are never uploaded to AgentNode; they are sent only to the provider you configured. Environment variables always override stored credentials, and keys never enter sandboxed community code.
Where are credentials stored?
agentnode auth set stores a token through a two-tier vault:
- OS keychain (primary) — Windows Credential Manager, macOS Keychain, or Linux Secret Service via
keyring. The secret lives only in the keychain;~/.agentnode/credentials.jsonkeeps non-secret metadata. - Local file (fallback) — when no keychain is available (e.g. headless Linux or CI), the token is written to
~/.agentnode/credentials.jsonwith0600permissions. This is a plaintext file — never described as encrypted.
Honest scope: the keychain protects against other local users and accidental file exposure. Neither tier protects a secret from a program already running as you.
Environment variables vs the vault
An environment variable always wins over a stored credential, so explicit and CI intent takes precedence. AgentNode also loads ~/.agentnode/.env as part of the environment.
For LLM providers, the env var name comes from the provider registry (see the table below). For connector packages, the convention is AGENTNODE_CRED_<PROVIDER> (uppercase), and the resolution order is configurable via credentials.resolve_mode:
| resolve_mode | Sources checked, in order |
|---|---|
| auto (default) | Environment variable → local vault → server-side |
| env | Environment variable only |
| local | Local vault only |
| api | Server-side only |
LLM provider keys
These providers are built in. Set a key with agentnode auth set <provider>, or export its environment variable. Ollama is local and keyless.
| Provider | Environment variable | Needs key |
|---|---|---|
| openai | OPENAI_API_KEY | Yes |
| anthropic | ANTHROPIC_API_KEY | Yes |
| openrouter | OPENROUTER_API_KEY | Yes |
| deepseek | DEEPSEEK_API_KEY | Yes |
| mistral | MISTRAL_API_KEY | Yes |
| qwen | DASHSCOPE_API_KEY | Yes |
| gemini | GEMINI_API_KEY | Yes |
| ollama | OLLAMA_API_KEY | No — local, keyless |
Any other OpenAI-compatible endpoint can be added under llm.providers in your config — see LLM Providers.
Auth commands
Tokens are entered hidden (never via the command line) and only ever shown masked. No AgentNode account is required to store or use them.
$ agentnode auth set openai # prompts for the key (hidden input)
$ agentnode auth set github # also works for connector packages
$ agentnode auth list # configured credentials (no secrets shown)
$ agentnode auth status # providers + effective source (env vs stored)
$ agentnode auth test openai # validate a key via a free endpoint
$ agentnode auth remove github # delete a stored credentialagentnode auth test ollama is a keyless reachability check against your local Ollama — it does not validate a key.
Setup wizard
agentnode setup can store one provider key for you as part of its interactive flow. It offers this — it never requires it — and uses the same vault, hidden input, and honest storage labels as agentnode auth set. You can always skip it and configure keys later.
Sandboxes and secrets
- Untrusted community code runs in a sandbox with no host environment — your keys and tokens are never passed in. A community MCP that declares it needs credentials is refused, not handed a secret.
- Sandboxed agents reach an LLM through a host-side broker: the provider key stays on the host and never enters the container, audit records, manifests, or lockfiles.
- Trusted and curated packages run host-side. In the default subprocess mode they still receive only an allowlisted environment — API keys and tokens are stripped. The opt-in
mode="direct"shares your full process environment, so use it only for code you trust. These tiers are policy-checked, not OS-sandboxed.
More: Execution sandbox and the security model.
Connector packages
Some packages call external APIs (GitHub, Slack, etc.). They never receive a raw token — instead they get a CredentialHandle that attaches the secret only for allowed requests:
- Domain-locked — the handle checks the target host against the connector's allowed domains and refuses non-HTTPS targets before any secret is attached.
- Not serializable — a handle cannot be pickled or printed;
repr()shows only the provider name, never the secret. - Resolved per policy — from
AGENTNODE_CRED_<PROVIDER>, the local vault, or the server-side source, in the order set bycredentials.resolve_mode.
Store a connector token the same way as any provider: agentnode auth set <provider>.
Troubleshooting
| Symptom | Fix |
|---|---|
| Stored as plaintext file, not keychain | Expected when no OS keychain is available (headless Linux, CI). The file is 0600. agentnode auth list shows the storage backend. |
| Key not picked up | An environment variable overrides the vault. Run agentnode auth status to see the effective source for each provider. |
| Unknown provider | Check the spelling against the provider table, or add a custom endpoint under llm.providers (see LLM Providers). |
| Connector request rejected | The CredentialHandle blocks hosts outside the connector's allowed domains and any non-HTTPS target. |
Related
- Quick Start — install, set up, and run your first capability.
- LLM Providers — every supported provider, including custom endpoints and Ollama.
- Execution Sandbox — how untrusted code is isolated from your secrets.
- Security Model — what is enforced per trust tier.
- Getting Started — the guided overview.