The problem
Most agent safety work happens before the action: better prompts, a classifier on the output, a policy check in the agent’s own code. All of that runs in the same place as the credential. If the thing that proposes an action also holds a live, reusable credential to perform it, the check and the power sit side by side, and the power does not depend on the check.The idea
Split proposing from doing. The agent proposes. Something else holds the credential, and that something acts only after the checks pass, and only for the exact action that was approved. The agent never sees the key, so there is nothing for it to leak or reuse.How Parmana does it
In Parmana that something is the gateway. It is the only boundary through which an approved request reaches a connector, the code that actually calls Paytm, HubSpot, GitHub or Slack. The default server always builds it; there is no server code path that skips it. By the time a request reaches the gateway, a policy has approved it and a person has signed an approval for that exact action. Every agent action needs one, reads included, at any amount. Even so, the gateway does not trust the authorization it is handed. Before anything reaches a connector it checks, in order:- the format version and the signature on the authorization;
- that it has not expired, and that its lifetime is within the allowed maximum;
- that the content it is about to send hashes to the value that was signed, so nothing was swapped after approval;
- that the policy is still the exact content a human checker approved, which fails closed if anything is missing;
- for some actions, that the facts the decision rested on still hold;
- and only then, last, that the single-use nonce has not been seen.
finally block on every exit path:
success, connector failure, or a rejection after issue. The connector receives an opaque, already-resolved handle; it
never fetches a credential itself, and a raw credential that did not come through that path is rejected. The secret
is kept out of the connector’s evidence, out of error messages and out of the signed Trust Record. This isolation is
on by default. The only way to turn it off is a flag documented as “for tests only”.
It is tested through a real HTTP request, not only at the library level: the credential is issued and destroyed on
success and on connector failure, and when the gateway’s own attestation does not verify, no session or credential
is created at all.
For systems connected as external connectors there is no credential to protect. Parmana signs each release, the
endpoint verifies the signature, and the credential handle is empty.
A lesson from my own refund path
Refunds through Paytm show why where the key lives matters more than how good the checks are. Parmana never holds the Paytm merchant key. The gateway forwards an approved refund over HTTPS to a separate refund service, and that service is the only thing that holds the key and talks to Paytm. Parmana holds only a shared secret that proves the gateway is the caller. In September I found a flaw in that service. It also had a route that agents called to ask for a refund. That route asked Parmana, and when Parmana approved and released the refund through the gateway, the route then called Paytm itself as well. An approved refund could be paid twice. Every check in Parmana had passed correctly. The problem was that a component on the agent’s side of the line still had a Paytm client. The fix removed it: that route no longer has a Paytm client and reads the result from the signed Trust Record. It was deployed on 28 September, and a refusal through it was verified in production. An approved refund making exactly one Paytm call is covered by that service’s tests; I have not yet observed it live.What it does not do
- It governs only what is routed through it. An agent that has its own credentials to a system and never calls Parmana is outside the boundary. Keeping credentials away from agents is a deployment property; Parmana cannot enforce it.
- Enforcement is in software, not the network. Anyone who holds a connector credential can call the downstream system directly, and nothing records it.
- Isolation is proven for the mechanism and the connectors already wired (Paytm, HubSpot, GitHub, Slack). A new built-in connector needs bootstrap code; there is no “any connector gets this automatically” path yet.
- Connector secrets are static environment values in production today. A provider that reads them from AWS Secrets Manager exists but is not provisioned.
- The Paytm merchant key’s handling inside the separate refund service is outside this repository and is not verified here.
- It does not prove the policy is right, only that the approved one was applied.