Connections
OAuth and API-key integrations with external services — Gmail, Slack, GitHub, Microsoft 365, and more.
A connection is a configured link between Sophon and an external service. Once you connect Gmail, the agent can read and send email. Once you connect Google Calendar, it can create events. Connections abstract away OAuth flows, token refresh, credential storage, and the difference between API-key and OAuth-based services.
Under the hood, all credentials live in the credential vault — encrypted at rest, never exposed to the LLM.
Adding a connection
From the Dashboard
Settings → Connections → Add Connection. Pick a service; the Dashboard walks you through the OAuth flow (or asks for an API key if that's what the service uses). Click Test when it's done to send a real call to the service and verify.
From the CLI
sophon connect list # available + configured services
sophon connect add gmail # starts OAuth flow in your browser
sophon connect add github
sophon connect test gmail # smoke-test an active connection
sophon connect status gmail # shows state, last use, expiry
sophon connect remove gmail # revoke and delete credentialsFrom the mobile app
More → Connections → Add. The OAuth flow opens in the device's system browser and returns to the app via deep link.
Authentication methods
Sophon supports several auth patterns, chosen per service:
| Method | Used by | How it works |
|---|---|---|
| OAuth 2.1 + PKCE | Google, Microsoft, GitHub, Slack, Dropbox, Notion, … | Browser-based consent flow, short-lived access token + refresh token. Refresh is automatic. |
| API key | Twilio, Jira, Confluence (with token), OpenRouter, … | Static key. Rotate from the service's portal; paste new key into the Dashboard. |
| Bearer token | Generic HTTP services, custom integrations | Static token treated like an API key. |
| SMTP / IMAP | Email (non-Gmail/M365) | Hostname + port + username + password (often app-specific password). |
| CLI credential reader | Claude CLI, OpenAI CLI, GitHub CLI | Reads credentials from ~/.claude/.credentials.json, ~/.openai/credentials, gh auth status — so you don't have to re-enter anything if you're already logged in at the CLI level. |
The CLI credential reader is worth calling out: if you've already authenticated Claude, OpenAI, or GitHub at your terminal, Sophon can pick those credentials up automatically instead of asking for a fresh OAuth.
Credential vault
All credentials — regardless of method — are stored in the credential vault. The vault has pluggable backends:
| Backend | Where it stores | Tier |
|---|---|---|
Local (default) | One encrypted .vault file per credential under ~/.sophon/vault/ — DPAPI-bound to your account on Windows, AES-256-CBC under ~/.sophon/security/vault.key elsewhere | All |
HashiCorp Vault | Your Vault server | Enterprise |
AWS Secrets Manager | AWS | Enterprise |
Azure Key Vault | Azure | Enterprise |
Pick the backend in appsettings.json:
{
"Sophon": {
"Credentials": {
"Vault": "AzureKeyVault",
"AzureKeyVault": { "VaultUri": "https://my-vault.vault.azure.net/" }
}
}
}The rest of Sophon doesn't know or care which backend is in use — tools, skills, and the Dashboard see the same vault interface everywhere.
How a skill gets a credential
- The skill manifest declares which credentials it needs, and how:
{ "service": "gmail", "access": "injected" }. - At execution time, Sophon delivers the stored credential into that skill's sandbox for the duration of one run. The container is destroyed afterwards.
- The model never sees it. The credential goes to the sandbox, not into the prompt, and tool results come back redacted.
"access": "proxy" is a deprecated spelling of "injected" and behaves identically — it is not an isolation boundary, and what arrives is the stored credential, not a short-lived scoped token. "access": "none" declares a connection for status purposes and delivers nothing.
So the skill code itself does hold the credential while it runs. Install skills you trust, keep OAuth scopes minimal at connect time, and lean on the sandbox's default-deny egress — a skill that declares no network allowlist has nowhere to send anything. A brokered proxy, where the sandbox hands back an API-call instruction and Sophon makes the call outside it, is on the roadmap.
Multi-account
You can connect the same service multiple times. Example: your personal Gmail and your work Gmail. Each connection gets its own ID; tools like gmail.send_email take a connectionId parameter (or the agent asks you to pick if ambiguous).
Naming connections — give each connection a human-readable label. Agents will use the label ("work Gmail" vs "personal Gmail") in prompts.
Token refresh
OAuth tokens expire; Sophon refreshes them automatically before expiry. If a refresh token is revoked or expires (usually because you changed your password or removed the app consent on the service's side), the connection flips to Needs re-auth and the agent will pause any tool call needing it until you re-authenticate.
Service catalog
Services Sophon knows about out of the box — each has a pre-built definition with the right auth method, scopes, and endpoints:
- Google: Gmail, Calendar, Drive, Docs, Sheets
- Microsoft 365: Outlook, Calendar, OneDrive, Graph API
- GitHub and GitLab
- Slack, Discord, Microsoft Teams
- Jira, Confluence, Linear, Notion
- Trello, Asana, Todoist
- Zapier, Make, IFTTT (outbound webhooks)
- Twilio, Telnyx (SMS + voice)
- OpenRouter, Anthropic, OpenAI, Gemini, Ollama (LLM providers — connected in Settings → Models, which uses the same vault)
- Dropbox, Box, Google Drive (file sync)
New services can be added via a connector SDK — see Plugins.
Testing a connection
Every connection has a Test button. Tests send a minimal real call:
- Gmail → read inbox metadata (no messages fetched)
- Calendar → list upcoming events (no events modified)
- GitHub →
GET /userto confirm auth
A passing test means the credentials work, scopes are correct, and the service is reachable.
Security
- Encrypted at rest — vault backends all encrypt by default.
- No raw tokens in context — the LLM never sees your credentials.
- Declared access — a skill only receives credentials for the services its manifest declares. It receives the stored credential, not a short-lived one, so scope minimization at connect time is what bounds it.
- Audit trail — every credential access is logged (user, skill, tool, connection, timestamp). Enterprise audit log filters down to the credential level.
- Scope minimization — OAuth flows request only the scopes listed in the service definition. Upgrading scopes requires re-authenticating, so you always see what you're granting.
- Per-user isolation — in multi-tenant deployments, connections are strictly user-scoped. Admins can see connection presence but not credentials.
Where to go next
- Service Connections catalog — every supported service and its scopes
- Skills — which skills need which connections
- Approval Gates — connection changes trigger approval on sensitive scopes