Skip to content

Credential Management

Anvil includes a credential management system that helps handle missing API keys gracefully, with optional interactive prompting.

Tools often fail because of missing credentials:

tool.run(query="test")
# Error: NOTION_API_KEY environment variable not set

Anvil can detect these errors and help resolve them.

anvil = Anvil(
interactive_credentials=True, # Enable prompting
env_file=".env", # Where to save credentials
)

When a tool fails due to a missing credential, Anvil will:

  1. Detect the missing key from the error message
  2. Prompt you to enter it
  3. Optionally save it to your .env file
  4. Retry the tool execution

Anvil looks for common patterns in error messages:

# These patterns are detected:
"NOTION_API_KEY not set"
"Missing environment variable: GITHUB_TOKEN"
"API key not found"
"Authentication failed: no key provided"

The credential name is extracted and you’re prompted to provide it.

Anvil has built-in knowledge of common API keys:

Key NameServiceGet Key URL
ANTHROPIC_API_KEYClaudeconsole.anthropic.com
OPENAI_API_KEYOpenAIplatform.openai.com
FIRECRAWL_API_KEYFireCrawlfirecrawl.dev
NOTION_API_KEYNotionnotion.so/my-integrations
GITHUB_TOKENGitHubgithub.com/settings/tokens
SLACK_BOT_TOKENSlackapi.slack.com/apps

When prompting for these keys, Anvil shows helpful information:

🔑 Missing credential: NOTION_API_KEY
Notion API Key
Get yours at: https://www.notion.so/my-integrations
Enter value (or press Enter to skip):

When you enter a credential, Anvil offers to save it:

Save to .env file? [y/N]: y
✓ Saved NOTION_API_KEY to .env

The credential is appended to your .env file:

# Existing keys...
ANTHROPIC_API_KEY=sk-ant-...
# Added by Anvil
NOTION_API_KEY=secret_...

Entered credentials are cached for the session:

# First call - prompts for NOTION_API_KEY
tool1.run(query="test")
# Second call - uses cached value, no prompt
tool2.run(query="test")
# Clear the cache
anvil.credential_resolver.clear_session_cache()

Access the credential resolver directly:

resolver = anvil.credential_resolver
# Check if a key is known
info = resolver.get_key_info("NOTION_API_KEY")
print(info["url"]) # https://www.notion.so/my-integrations
# Manually prompt for a credential
value = resolver.prompt_for_credential("CUSTOM_API_KEY")
# Detect missing credential from error
error_msg = "CUSTOM_KEY not set"
key_name = resolver.detect_missing_credential(error_msg)
print(key_name) # "CUSTOM_KEY"

For CI/CD or automated environments:

# Disable interactive prompts
anvil = Anvil(interactive_credentials=False)
# Credentials must be in environment or .env file
# Missing credentials will raise errors

Specify a custom location for your environment file:

anvil = Anvil(
env_file="/path/to/custom/.env",
interactive_credentials=True,
)

Ensure .env is in your .gitignore:

Terminal window
anvil init # Automatically adds .env to .gitignore

2. Use Environment Variables in Production

Section titled “2. Use Environment Variables in Production”
Terminal window
# Production
export ANTHROPIC_API_KEY="sk-ant-..."
export NOTION_API_KEY="secret_..."
# Anvil reads from environment
anvil = Anvil() # No .env file needed

If a key is compromised:

  1. Revoke the old key at the provider
  2. Generate a new key
  3. Update your .env or environment variables

When possible, use API keys with minimal permissions:

  • GitHub: Use fine-grained tokens with specific repo access
  • Notion: Create integrations with limited workspace access
  • Slack: Use bot tokens with minimal scopes
┌─────────────────┐
│ Tool Executes │
└────────┬────────┘
┌─────────────────┐ ┌─────────────────┐
│ Success? │─Yes─▶│ Return Result │
└────────┬────────┘ └─────────────────┘
│No
┌─────────────────┐ ┌─────────────────┐
│ Credential │─No──▶│ Raise Error │
│ Error Detected? │ └─────────────────┘
└────────┬────────┘
│Yes
┌─────────────────┐ ┌─────────────────┐
│ Interactive │─No──▶│ Raise Error │
│ Mode Enabled? │ └─────────────────┘
└────────┬────────┘
│Yes
┌─────────────────┐
│ Prompt User for │
│ Credential │
└────────┬────────┘
┌─────────────────┐
│ Cache & Retry │
└─────────────────┘