DEV Community

The Seventeen
The Seventeen

Posted on

We Built a Python SDK Where the Credentials Never Enter Your Code

I want to show you something before I explain it.

from agentsecrets import AgentSecrets

client = AgentSecrets()

response = client.call(
    "https://api.stripe.com/v1/balance",
    bearer="STRIPE_KEY"
)

print(response.json())
Enter fullscreen mode Exit fullscreen mode

That code calls the Stripe API. It uses a real credential. The credential value never entered this Python process. Not as a variable. Not as a return value. Not in any log.

Here is what actually happened: the SDK sent the key name to the AgentSecrets proxy running locally. The proxy resolved the value from the OS keychain, injected it into the outbound HTTP request, and returned only the API response. The value never crossed into application code.

That is not a trick. That is what zero-knowledge credential management looks like as a Python SDK.


Why This Matters

Every secrets SDK you have used works like this:

key = os.getenv("STRIPE_KEY")        # value is now in your process
key = vault.get("STRIPE_KEY")        # value is now in your process
key = keyring.get_password(...)      # value is now in your process
Enter fullscreen mode Exit fullscreen mode

Once the value is in your process, it is reachable. By prompt injection. By a compromised plugin. By a malicious MCP server in the same context. By any CVE that gives an attacker process memory access. The attack surface is the value being in memory at all.

The AgentSecrets SDK removes that attack surface entirely. There is no get() method. There is no retrieve(). The only operations are: make the call, or spawn the process. In both cases the value resolves inside the proxy and never crosses into your code.

You cannot leak what was never there.


The SDK

Install:

pip install agentsecrets
Enter fullscreen mode Exit fullscreen mode

Requires the AgentSecrets CLI installed and running.

Six injection styles — one for every auth pattern:

# Bearer token
response = client.call("https://api.stripe.com/v1/balance", bearer="STRIPE_KEY")

# Custom header
response = client.call(
    "https://api.sendgrid.com/v3/mail/send",
    method="POST",
    body=payload,
    header={"X-Api-Key": "SENDGRID_KEY"}
)

# Query parameter
response = client.call(
    "https://maps.googleapis.com/maps/api/geocode/json",
    query={"key": "GMAP_KEY"}
)

# Basic auth
response = client.call(
    "https://yourcompany.atlassian.net/rest/api/2/issue",
    basic="JIRA_CREDS"
)

# JSON body injection
response = client.call(
    "https://api.example.com/token",
    method="POST",
    body_field={"client_secret": "CLIENT_SECRET"}
)

# Form field
response = client.call(
    "https://oauth.example.com/token",
    method="POST",
    form_field={"api_key": "API_KEY"}
)
Enter fullscreen mode Exit fullscreen mode

Async works exactly as you would expect:

response = await client.async_call(
    "https://api.openai.com/v1/models",
    bearer="OPENAI_KEY"
)
Enter fullscreen mode Exit fullscreen mode

Process spawning — inject secrets as environment variables into a child process:

# The child process reads os.environ normally
# The calling code never sees the values
result = client.spawn("python", ["manage.py", "runserver"])
result = client.spawn("stripe", ["mcp"])
Enter fullscreen mode Exit fullscreen mode

Why There Is No get() Method

This was a deliberate design decision and it is worth explaining.

If the SDK had a get() method, developers would use it. Not maliciously — just because it would be the path of least resistance when they need a credential value for something the call() method does not cover. They would call get(), assign it to a variable, and the zero-knowledge guarantee would be gone.

By structurally removing the method, we make the secure path the only path. A developer building on this SDK inherits the guarantee without having to think about it. They cannot accidentally break it.

This is what infrastructure means. The security property is not something you configure. It is something you get by default because the design makes the insecure alternative impossible.


The Multiplier

Here is the part that matters most to developers building tools.

When you build an MCP server, a LangChain tool, or any agent integration on this SDK and publish it, every user of your tool gets zero-knowledge credential management automatically. They do not know AgentSecrets exists. They do not configure anything. They install AgentSecrets once, set their credentials, and every tool built on the SDK works.

One SDK import. The guarantee extends to everyone downstream.


What Is Next

Go and JavaScript SDKs are on the roadmap. The Zero-Knowledge MCP template ships next — a fully working MCP server built on the SDK, zero credential storage, ready to clone and build on.

The SDK is open source: github.com/The-17/agentsecrets-sdk

The CLI it depends on: github.com/The-17/agentsecrets

If you build something on it, I want to know.

Top comments (0)