Agent Secret Store DocsSign up
📘 Guides

Migrate from .env Files

Move your credentials out of flat files and into a purpose-built secret vault — with encryption, audit trails, and scoped access control.

Why .env files are dangerous for production agents

Git accidents

.env files get committed accidentally despite .gitignore — it happens to everyone, including security teams.

No access control

Any code running on the host can read all environment variables — your database password and your LLM key share the same flat namespace.

No audit trail

You have no idea which agents accessed which credentials, or when. Forensics after a breach is impossible.

Rotation pain

Rotating a key means updating .env on every server, restarting containers, and hoping nothing missed the update.

Plaintext at rest

.env files are plaintext. If your host is compromised, all credentials are immediately exposed.

Copy-paste culture

Devs copy production keys to local .env files "just for testing" — now they're on 12 laptops.

Starting point — your existing .env

.env
# .env (what you have today)
OPENAI_API_KEY=sk-proj-abc123...
STRIPE_SECRET_KEY=sk_live_xyz789...
SLACK_BOT_TOKEN=xoxb-123456-...
DATABASE_URL=postgresql://user:pass@host:5432/db
ANTHROPIC_API_KEY=sk-ant-...
SENDGRID_API_KEY=SG.abc...

Migration steps

  1. 1

    Create an Agent Secret Store account

    Sign up at agentsecretstore.com/signup and copy your agent key from the dashboard.

  2. 2

    Install the SDK and set your key

    Shell
    pip install agentsecretstore
    export ASS_AGENT_KEY="ass_live_your_key_here"
  3. 3

    Bulk import your .env file

    Use the import script below to read your .env and create all secrets in the vault. Run with --dry-run first to preview:

    import_env.py
    #!/usr/bin/env python3
    """
    import_env.py — Bulk import a .env file into Agent Secret Store
    
    Usage:
        python import_env.py --env-file .env --namespace production --tier sensitive
    """
    
    import argparse
    import asyncio
    import os
    import re
    from pathlib import Path
    
    from agentsecretstore import AgentVault
    from agentsecretstore.exceptions import AgentVaultError
    
    def parse_env_file(path: Path) -> dict[str, str]:
        """Parse a .env file into a dict of key=value pairs."""
        secrets: dict[str, str] = {}
        pattern = re.compile(r'^([A-Za-z_][A-Za-z0-9_]*)=(.*)$')
    
        for line in path.read_text().splitlines():
            line = line.strip()
            if not line or line.startswith('#'):
                continue
            m = pattern.match(line)
            if m:
                key, value = m.groups()
                # Strip surrounding quotes if present
                value = value.strip('"').strip("'")
                secrets[key] = value
        return secrets
    
    async def import_secrets(
        env_file: Path,
        namespace: str,
        tier: str,
        dry_run: bool,
    ) -> None:
        secrets = parse_env_file(env_file)
        print(f"Found {len(secrets)} secrets in {env_file}")
    
        if dry_run:
            for key, value in secrets.items():
                path = f"{namespace}/{key.lower().replace('_', '-')}"
                print(f"  [DRY RUN] Would import: {path} = {value[:4]}...")
            return
    
        async with AgentVault() as vault:
            for key, value in secrets.items():
                # Convert ENV_VAR_NAME to namespace/env-var-name
                secret_name = key.lower().replace('_', '-')
                path = f"{namespace}/{secret_name}"
    
                try:
                    await vault.set_secret(
                        path=path,
                        value=value,
                        tier=tier,
                        description=f"Imported from .env: {key}",
                        tags={"source": "env-import", "original_key": key},
                    )
                    print(f"  ✓ Imported: {path}")
                except AgentVaultError as e:
                    print(f"  ✗ Failed to import {path}: {e}")
    
    if __name__ == "__main__":
        parser = argparse.ArgumentParser(description="Import .env into Agent Secret Store")
        parser.add_argument("--env-file", default=".env", help="Path to .env file")
        parser.add_argument("--namespace", required=True, help="Target namespace (e.g. 'production')")
        parser.add_argument("--tier", default="sensitive", choices=["standard", "sensitive", "critical"])
        parser.add_argument("--dry-run", action="store_true", help="Preview without writing")
        args = parser.parse_args()
    
        asyncio.run(import_secrets(
            env_file=Path(args.env_file),
            namespace=args.namespace,
            tier=args.tier,
            dry_run=args.dry_run,
        ))
    Shell
    # Preview what will be imported (no writes)
    python import_env.py --env-file .env --namespace production --dry-run
    
    # Import for real
    ASS_AGENT_KEY=ass_live_your_key_here \
    python import_env.py --env-file .env --namespace production --tier sensitive
    
    # Output:
    # Found 6 secrets in .env
    #   ✓ Imported: production/openai-api-key
    #   ✓ Imported: production/stripe-secret-key
    #   ✓ Imported: production/slack-bot-token
    #   ✓ Imported: production/database-url
    #   ✓ Imported: production/anthropic-api-key
    #   ✓ Imported: production/sendgrid-api-key
  4. 4

    Update your agent code

    Python

    credentials.py
    # BEFORE — reading from .env / environment
    import os
    
    openai_key = os.environ["OPENAI_API_KEY"]
    stripe_key = os.environ["STRIPE_SECRET_KEY"]
    
    # AFTER — reading from vault
    import asyncio
    from agentsecretstore import AgentVault
    
    async def load_credentials() -> dict[str, str]:
        async with AgentVault() as vault:
            openai  = await vault.get_secret("production/openai-api-key")
            stripe  = await vault.get_secret("production/stripe-secret-key")
    
        return {
            "openai_key": openai.value,
            "stripe_key": stripe.value,
        }
    
    # Or use a helper for simpler access
    async def get(path: str) -> str:
        async with AgentVault() as vault:
            return (await vault.get_secret(path)).value

    JavaScript / TypeScript

    credentials.ts
    // BEFORE — reading from process.env
    const openaiKey = process.env.OPENAI_API_KEY!;
    const stripeKey = process.env.STRIPE_SECRET_KEY!;
    
    // AFTER — reading from vault
    import { AgentVault } from '@agentsecretstore/sdk';
    
    const vault = new AgentVault();
    
    async function loadCredentials() {
      const [openai, stripe] = await Promise.all([
        vault.getSecret('production/openai-api-key'),
        vault.getSecret('production/stripe-secret-key'),
      ]);
    
      return {
        openaiKey: openai.value,
        stripeKey: stripe.value,
      };
    }
  5. 5

    Update CI/CD

    Instead of storing 20 secrets in GitHub Actions (or your CI/CD provider), store only ASS_AGENT_KEY — all other secrets are fetched at runtime.

    .github/workflows/deploy.yml
    # GitHub Actions — before (secrets in repo settings)
    env:
      OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
      STRIPE_SECRET_KEY: ${{ secrets.STRIPE_SECRET_KEY }}
    
    # GitHub Actions — after (only vault key needed)
    env:
      ASS_AGENT_KEY: ${{ secrets.ASS_AGENT_KEY }}
      # All other secrets fetched from vault at runtime
  6. 6

    Delete your .env files

Secret Rotation

Set up automatic rotation schedules.

Python SDK Reference

Complete SDK documentation.