What is AgentSecrets?
The Zero-Knowledge Difference
How AgentSecrets Works
Installation
Quick Start
Migrating from .env Files
Migrating from Vault / AWS
Migrating from dotenv-vault
Production Checklist
Credential Exposure
What Zero-Knowledge Means
The Proxy Model
The Three-Layer Model
Environments
Agent Identity
Storage Modes
The No get() Principle
Secret-Level Policies
Cloud Overview & Architecture
The Dual-Engine Model
Cloud Resolver Data Plane
Workload & Agent Tokens
Egress Allowlists & Audit Streams
Cloud REST API Reference
Account (init / login)
Server & Self-Hosting (server)
Docs
Shell Autocompletion
Keychain Auth
Secrets
Environments
Credential Proxy
env Injection
Workspaces & Teams
Projects
Agent Identity
Audit & Governance
Integrations Overview
Claude Desktop
Cursor
OpenClaw
HTTP Proxy (Any)
LangChain (Soon)
CrewAI (Soon)
CI/CD Pipeline
SDK Overview
Python SDK
Python API Reference
Python SDK Manual Testing
JavaScript SDK (Soon)
Ecosystem Overview
Zero-Knowledge MCP Server
Server Overview
5-Layer Architecture
Self-Hosting Guide
Authentication & Keys
Workspaces & Teams
Projects & Scope
Environments
Secrets & Sync Protocol
Agent Identity Resolution
Telemetry & Metrics Engine
Audit Log Sync
API Endpoint Reference
Security Overview
Anti-Impersonation & Process Verification
Encryption Model
Zero-Knowledge Sync
Proxy Security Layers
Threat Model
OWASP Top 10 Mitigation
Security FAQ
Third-Party Audit
Reporting Vulnerabilities
Guides Overview
Building on the SDK
Stripe Integration
OpenAI Integration
Multi-Agent Setup
Onboarding Team
CI/CD Pipeline
Publishing ZK MCP
Rotating Credentials
Auditing Team Activity
Dev to Production
Kubernetes Deployment
Monorepo Setup
Production Proxy Hardening
vs .env Files
vs HashiCorp Vault
vs AWS Secrets Manager
vs dotenv-vault
vs Infisical
When Not to Use
Proxy Not Starting
Proxy Not Resolving
Domain Blocked
Sync Conflicts
MCP Not Connecting
Session Token Errors
Proxy Session Authorization
Keychain Storage & Backends
SSRF & Destination Rules
Installation Issues
Error Codes Reference
Frequently Asked Questions
v3.1.x
v3.0.0
v2.1.0
v2.0.0
v1.4.0
v1.3.x
v1.2.0
v1.1.x
v1.0.x
Fundamental ConceptsThe No get() Principle

The No get() Principle

The AgentSecrets Python SDK has no get() method. This is not an oversight. It is the single most important design decision in the SDK, and understanding why it exists changes how you think about building on top of AgentSecrets.


Why the SDK has no get() method

A get() method would look like this:

# This method does not exist in AgentSecrets value = client.get("STRIPE_KEY") # value is now "sk_live_51H..." — in your process, in memory, accessible

If this method existed, every downstream use of the SDK would carry the same credential exposure risk as any other retrieval-based approach. The tool you use to avoid credential exposure would itself become a credential exposure path.

The absence of get() is not a convenience omission — it is the enforcement mechanism for the zero-knowledge guarantee at the SDK layer. You cannot retrieve a credential value into your calling code because the method to do so does not exist.


What this means for developers building on AgentSecrets

If you are building an MCP server, an agent tool, or any other system on top of AgentSecrets, the no get() constraint extends to everything you build. Your users' code cannot retrieve credential values through your tool because your tool cannot retrieve credential values itself.

This is the point. When you build on AgentSecrets, the zero-knowledge guarantee is inherited by everything downstream. An MCP server built on AgentSecrets cannot leak credentials to Claude regardless of what Claude is instructed to do, because there is no mechanism to retrieve the values in the first place.

The Zero-Knowledge MCP Template is built on this principle. Every MCP server scaffolded from it inherits the same structural protection.


How this changes how you design agent tools

Conventional tool design:

# Conventional — retrieves the value to use it def call_stripe_api(endpoint): key = secrets.get("STRIPE_KEY") # value retrieved into this function return requests.get(endpoint, headers={"Authorization": f"Bearer {key}"})

AgentSecrets tool design:

# AgentSecrets — passes the key name, never the value def call_stripe_api(endpoint): return client.call(endpoint, bearer="STRIPE_KEY") # proxy resolves STRIPE_KEY, injects it, returns API response # STRIPE_KEY value never exists in this function

client.call() accepts a key name, not a credential value. Your function never holds the value. If this function is called by a prompt-injected agent, there is nothing for the attacker to extract — the value was never here.


Common patterns that get() would enable and why they are excluded

1. Storing raw credentials in memory or configuration dictionaries:

# This pattern is not possible with AgentSecrets config = { "stripe_key": client.get("STRIPE_KEY"), "openai_key": client.get("OPENAI_KEY"), }

Configuration dictionaries and memory blocks holding raw credential values are a major source of accidental exposure — they get dumped into debugging logs, serialized across processes, or extracted by prompt-injected LLMs.

2. Returning raw credentials from agent tools:

# This pattern is not possible with AgentSecrets def get_api_key_for_agent(key_name): return client.get(key_name) # would give the agent the plaintext value

An agent tool that returns plaintext credential values is a direct credential exfiltration path. The tool cannot exist in AgentSecrets because the method it would call does not exist.


How to use third-party libraries without get()

A common question is: “If get() doesn't exist, how do I configure official client SDKs (like OpenAI, Stripe, Anthropic, or LangChain) that require an api_key parameter?”

The answer is Transparent HTTP Client Interception:

Instead of extracting raw secrets into your Python runtime, you initialize official SDKs using Zero-Knowledge Placeholders (via the credential helper or AS_SECRET_ strings):

import openai import stripe from agentsecrets import init, credential # 1. Initialize the transparent interceptor at application startup init() # 2. Pass zero-knowledge placeholders into vendor SDKs openai_client = openai.OpenAI(api_key=credential.OPENAI_API_KEY) stripe.api_key = credential.STRIPE_SECRET_KEY # 3. Use the SDKs normally — requests are automatically intercepted response = openai_client.chat.completions.create( model="gpt-4o", messages=[{"role": "user", "content": "Hello!"}] )

How this preserves the Zero-Knowledge Guarantee:

  1. Application Memory: Only holds the placeholder string "AS_SECRET_OPENAI_API_KEY". Even if an attacker compromises the process, there are no secrets in RAM.
  2. Network Layer Hook: init() monkey-patches requests and httpx internally. When the vendor SDK sends an HTTP request, the interceptor strips the placeholder and routes the call to http://localhost:8765/proxy.
  3. Transport Boundary Injection: The local proxy checks the workspace allowlist, resolves the real credential from the OS Keychain via keychain-auth, injects it directly into the outbound TLS stream to the vendor API, and returns the response safely.

The secure path is the only path

The SDK is designed so that the secure usage pattern is the only usage pattern available. The operations that exist are:

  • agentsecrets.init() — register transparent HTTP client interception for standard libraries (requests, httpx)
  • client.call() / AsyncAgentSecrets.call() — make an authenticated HTTP request; the value is injected by the proxy at transport time
  • client.spawn() / client.spawn_async() — start a process with credentials injected into child process memory with mandatory output stream masking
  • client.secrets.list() — list key names; never values
  • client.secrets.check() — check whether keys exist; returns booleans, not values
  • client.secrets.pull() / client.secrets.push() / client.secrets.diff() — zero-knowledge sync operations
  • agent module — manage scoped agent identities, cryptographic tokens, and access capabilities

Every operation keeps the credential value out of your process memory and agent context. That is the complete design surface of the SDK.

Was this helpful?
Thanks for your feedback!
Your feedback helps us improve the platform.