Skip to main content

Overview

MeepaGateway manages credentials for your agents using a flat credential model. All credential types — email addresses, phone numbers, virtual credit cards, GitHub tokens, and custom logins — are stored as uniform AgentCredential entries grouped by category. Credentials are provisioned per-agent. Built-in categories (email, phone, credit card) support automatic provisioning through external services. Other categories (login, api_key) are stored directly with no provisioning step required. Credentials are stored in a SOPS-encrypted file in each agent’s workspace. Credential provisioning is disabled by default. Enable it under credentials in config.yaml.

Credential Categories

CategoryProvisioned?Example Services
emailYes (automatic)AgentMail, Google Workspace
phoneNo (manual)Tello, carrier SIMs
credit_cardYes (automatic)Privacy.com, manual entry
loginNo (stored directly)GitHub, npm, Stripe
api_keyNo (stored directly)OpenAI, Anthropic, custom
tokenNo (stored directly)OAuth tokens, JWTs

Credential Origins

Every credential has an origin that tracks how it was obtained:
  • operator_provided — An operator or admin pre-created and registered the credential.
  • agent_created — The agent autonomously created this credential (e.g., signed up for a service using its email address).

Configuration

Global Setup

credentials:
  enabled: true

  credential_store:
    provider: sops   # "sops" (default) or "none"
    sops:
      # Public key for age encryption (auto-generated if absent)
      # public_key: "age1..."
      # Path to private key file (default: ~/.meepagateway/agents/{id}/private-key.key)
      # key_file: /path/to/key.key

  email:
    enabled: true
    provider: agentmail   # "agentmail", "google_workspace", or "existing"
    agentmail:
      api_key_env: AGENTMAIL_API_KEY
      # domain: yourdomain.com   # optional custom domain

  phone:
    enabled: false   # Enable to allow per-agent phone number overrides

  credit_card:
    enabled: true
    provider: privacy_com   # "privacy_com" or "manual"
    privacy_com:
      api_key_env: PRIVACY_API_KEY
      default_spend_limit: 5000       # cents ($50.00)
      default_spend_limit_duration: MONTHLY
      card_type: MERCHANT_LOCKED

Per-Agent Override

Disable or customise credentials for a specific agent:
agents:
  - id: meepa
    identity:
      enabled: false   # Disable provisioning for this agent
      email_prefix: custom-prefix   # Override email prefix
      credit_card_spend_limit: 2000 # Override spend limit (cents)

Credential File Format

Provisioned credentials are written to:
~/.meepagateway/agents/{agent_id}/credentials.json
The file uses a flat list format:
{
  "credential_store": {
    "provider": "sops",
    "item_id": "meepa-credentials",
    "vault": "agents",
    "status": "provisioned"
  },
  "credentials": [
    {
      "category": "email",
      "service": "agentmail",
      "name": "Email",
      "origin": "operator_provided",
      "items": [
        { "key": "address", "value": "agent-meepa@mg.example.com", "item_type": "email" },
        { "key": "inbox_id", "value": "abc123", "item_type": "other" }
      ],
      "status": "provisioned"
    },
    {
      "category": "credit_card",
      "service": "privacy_com",
      "name": "Credit Card",
      "origin": "operator_provided",
      "items": [
        { "key": "last_four", "value": "1234", "item_type": "other" }
      ],
      "metadata": { "spend_limit": 5000 },
      "status": "provisioned"
    },
    {
      "category": "login",
      "service": "github",
      "name": "GitHub",
      "origin": "operator_provided",
      "items": [
        { "key": "token", "value": "ghp_xxx", "item_type": "api_token" }
      ],
      "status": "existing"
    }
  ],
  "provisioned_at": "2025-07-01T09:00:00Z"
}
Old identity.json files are automatically migrated to this format on first read.

Adding Login / API Key Credentials

Login and API key credentials do not require provisioning — they are stored directly in the agent’s encrypted credential store.

Via the Captain Dashboard

  1. Open the agent in the Captain dashboard.
  2. Scroll to Agent Credentials and click + Add Credential.
  3. Select a category (Login, API Key, Token), enter the service name and value, and save.

Via the API

POST /api/captain/agents/{id}/credentials
Content-Type: application/json

{
  "category": "login",
  "service": "github",
  "name": "GitHub",
  "origin": "operator_provided",
  "items": [
    { "key": "token", "value": "ghp_xxx", "item_type": "api_token" }
  ]
}

Via the CLI

meepagateway agent credentials meepa
Launches an interactive credential management TUI for the agent.

Removing Credentials

DELETE /api/captain/agents/{id}/credentials/{category}/{service}
Example — remove a GitHub login:
DELETE /api/captain/agents/meepa/credentials/login/github

Credential Store

The credential store uses SOPS with age encryption. An age keypair is generated automatically on first provisioning:
~/.meepagateway/agents/{agent_id}/private-key.key   # private key (back this up)
All credential values are encrypted at rest. Plaintext credentials never touch disk outside of the credential store.

Sandbox Injection

When inject_credentials_env = true, the agent’s credentials are injected as environment variables into the Docker sandbox container:
agent_defaults:
  image_config:
    inject_credentials_env: true
Available environment variables inside the container:
VariableSource
AGENT_EMAILProvisioned email address
AGENT_PHONEProvisioned phone number
AGENTMAIL_API_KEYAgentMail API key
PRIVACY_API_KEYPrivacy.com API key

Credential Status Values

Each AgentCredential entry has a status field:
StatusMeaning
provisionedResource was newly created by this run
existingResource already existed and was reused
pending_manualWaiting for manual action (e.g. SIM card activation)
pending_signupAgent is in the process of signing up autonomously
skippedCredential type not configured or disabled
{ "failed": "reason" }Provisioning failed with the given reason
Partial success is valid — the credentials file is written even if some entries fail.

Security Notes

  • Back up private-key.key — without it, credentials cannot be decrypted
  • Credential values are encrypted at rest via SOPS/age
  • inject_credentials_env = true passes credentials into container env — only enable when the agent’s tools require them
  • Deprovisioning deletes the local credentials file but does not revoke credentials in third-party services (Privacy.com cards, AgentMail inboxes, etc.) — revoke those manually