Skip to content
API Reference
Get Started
Use Cases

Act as the user who asked

An agent reaches a downstream system as the specific person who requested the work, so every action is attributable to a named individual and carries only that person's entitlements.

A user asks an agent to do something that requires a system the user already has access to. The agent should reach that system as that person, with that person’s entitlements and nothing more.

Most agents reach downstream systems one of two ways. They hold a shared service account, or they borrow the user’s own long-lived bearer token and pass it along.

Both break the same two things.

Attribution collapses. When ten people’s requests arrive at a database under one service account, the log shows the service account. It cannot tell you which person asked, which agent acted, or whether a given query was a human running a report or an agent working through a task. For a system under audit, that is the difference between having evidence and reconstructing a guess.

Scope collapses with it. An agent holding a user’s token can do everything that user can do, not the one thing the task needed. A request to summarize last quarter’s tickets carries the authority to delete them. Nothing about the token distinguishes the two, so nothing stops the second.

Reissuing narrower service accounts does not fix this. It multiplies the credentials you have to track while leaving each one still shared, still long-lived, and still anonymous at the point of use.

flowchart LR
    A[Anyone asks] --> B[Your Agent]
    B -->|"Shared service account, long-lived"| C[Resource]
    C -->|"Full access, one identity"| D["Log: 'svc-agent' did something"]

This is the right pattern when a person is present and the work is theirs. Concretely:

  • Someone triggers the agent, so there is a live session to authenticate
  • The system the agent needs already knows that person and already scopes their access
  • You need the downstream log to name the individual rather than the automation
  • Different users of the same agent should reach different data

Suppose you run an internal support desk. An engineer asks an agent to pull the recent tickets for one customer and summarize them. The ticketing system should see a request from that engineer, limited to what that engineer can see, for as long as the task takes. Not an agent holding a permanent key to every ticket in the company.

Two situations want a different pattern.

Where nobody is present, there is no live session to exchange, so scheduled and event-driven work belongs in Act on Behalf of Absent Users instead.

Where the agent’s work is its own rather than a person’s, it wants an identity of its own. Give an agent its own identity covers that.

Keycard sits between the agent and the system it wants to reach. The user authenticates to the identity provider you already run. The agent then asks Keycard for a credential to reach one named Resource, presenting the user’s verified identity rather than the user’s standing access.

Keycard evaluates policy against the full picture, meaning the User, the Application acting for them, the Resource, and the context of the session. When policy allows the request, Keycard issues a credential scoped to it and short-lived. The agent uses that credential for that call, and it expires on its own rather than being held.

The credential is the enforcement point. Because it is issued per request rather than held, the question “should this agent do this, for this person, right now” gets answered every time rather than once at setup.

flowchart LR
    A[User] -->|"Signs in"| B[Identity Provider]
    B -->|"Verified identity"| C[Your Agent]
    C -->|"Token exchange for one Resource"| D[Keycard]
    D -->|"Evaluate policy"| D
    D -->|"Short-lived scoped credential"| C
    C -->|"Calls as the user"| E[Resource]
    D -->|"Identity chain, Resource, session"| F[Audit Log]
  1. The User signs in through your existing identity Provider. Keycard federates over OpenID Connect, so Okta, Microsoft Entra, Auth0, and Google all serve as the identity source without moving your directory.
  2. Your agent presents that verified identity to Keycard and requests access to one named Resource. This is standard OAuth token exchange, RFC 8693, so the flow is inspectable by your security team rather than proprietary.
  3. Keycard evaluates your Policies at the moment of issuance, against the User, their group membership, the Application, the Resource, and session context. A request outside what policy permits is denied before any credential exists.
  4. Keycard issues a credential scoped to that User, that Resource, and that request, with a bounded lifetime. Nothing long-lived lands on the agent’s host.
  5. The agent calls the Resource with that credential. The Resource sees a request from a named person.
  6. Every authentication, authorization decision, and credential issuance lands in the Audit Log, carrying the identity chain, the Resource, and the session. A refusal records its reason and the deciding policy. The same events export to your own bucket in OCSF v1.7.0.

Every call an agent makes carries a credential belonging to one person and scoped to one Resource, which expires rather than persisting. There is no shared service account and no long-lived secret sitting on the agent’s host to find.

The audit question changes shape. Instead of correlating a service account across three systems and inferring who was behind it, you query one trail. Every authorization decision on it already names the person, the Application that asked, and the Resource it asked for, and a refusal carries the policy that decided it.

Access follows your directory. Policy reads group membership from the Provider rather than from a copy, so when someone changes teams or leaves, the entitlement change you make governs what their agents can reach once they next authenticate.

Every boundary below follows from one design choice, which is that policy runs at credential issuance rather than at the network edge or at login. Knowing where that puts the edges is worth more before an evaluation than after one.

You write and maintain the policy. Access becomes a property of policy rather than of how the agent happens to behave, which means someone owns those policies. The behavior is explicit and reviewable, and it is also now yours to keep current.

Your agent asks for what it needs. Code that previously read a key from the environment requests a credential per Resource instead. The SDKs handle the exchange, though it is a change to the calling path rather than a proxy you put in front of an unchanged service.

Keycard authorizes the request, and the Resource authorizes its own contents. Because policy evaluates before the call is made, it decides which Resource and which operation rather than which rows come back. A warehouse that already enforces row and column rules keeps enforcing them, and the credential it receives names the person those rules apply to, which is what makes them work at all.

Policy decides at issuance, so a change lands at the next issuance. Credentials are short-lived by design, which keeps that window small, and it does mean a policy edit reaches an agent when its current credential expires rather than mid-request.

Coverage follows the credentials Keycard issues. An agent holding a credential it obtained elsewhere is outside this pattern, so what you govern is what you route through it. That is the same property that lets you adopt this one Resource at a time rather than all at once.

The first four come up most often from security reviewers rather than builders, and they tend to come early.

Do you issue your own tokens, or broker ours?

Section titled “Do you issue your own tokens, or broker ours?”

Both, and the Resource decides which.

For a Resource inside your Zone’s trust domain, such as an MCP server or an API that integrates with Keycard directly, Keycard signs a JWT you validate against your Zone’s public JWKS endpoint. For an external Provider like GitHub, Google, or Slack, that provider issues its own tokens and Keycard brokers and stores them for the user. For a legacy system that only accepts a static credential, Keycard Vault holds it encrypted and brokers it on demand.

No proprietary token is forced onto a system that already has its own authorization server.

Why does authorization policy live outside our identity provider?

Section titled “Why does authorization policy live outside our identity provider?”

Because the decision happens at a different moment. Your identity provider answers who this person is, once, at login. This pattern needs a decision per request, evaluated against the Resource being asked for, the agent asking, and the session it is asking in, none of which exist at login time. Your provider stays the source of identity and group membership, and policy reads from it rather than copying it.

It stops Keycard issuing anything new for that User and Resource, and it stops refresh. It does not reach out and kill a credential already in flight.

A token the agent already holds keeps working against the Resource until it expires. Containment is therefore bounded by that credential’s remaining lifetime rather than being instant, and there is no per-token kill switch. Confirm the configured lifetime for your Zone before you size that window, because it is what decides how long the gap is.

Brokered access to an external Provider needs one extra step. Revoking the Keycard grant stops Keycard brokering new credentials, and it does not revoke what that provider already issued, so cut that off in the provider’s own connected-apps settings too. Revoke a Grant covers the full behavior.

How do we prove an action was taken by a specific person?

Section titled “How do we prove an action was taken by a specific person?”

Each authorization decision carries the identity chain, meaning the User and the Application that acted for them, alongside the Resource and the session. Sessions groups those events so one agent’s activity reads in order, and the same records export to your own bucket so your SIEM holds the evidence rather than us.

Can an agent see which tools it is allowed to use before it calls one?

Section titled “Can an agent see which tools it is allowed to use before it calls one?”

Today the agent asks and policy answers, so an attempt outside what policy permits is refused at issuance rather than filtered from a list beforehand. That ordering is what makes the refusal authoritative: the decision is made against the live request, with the User and session in hand, instead of against a list built earlier. Shaping what an agent is offered up front, so it never forms the intent, is a separate problem from deciding whether to allow the call, and the two work best together.

No, and it is built not to. Keycard federates to the Provider you already run and reads identity and group membership from it rather than copying them. Your directory stays the system of record for who someone is, and Keycard decides what their agent may reach. Where a team has no identity provider at all, that is the piece to solve first, because everything here derives from a verified person.

What if the system we need does not speak OAuth?

Section titled “What if the system we need does not speak OAuth?”

Keycard Vault stores the static credential encrypted, brokers it to the Application on demand, and audits every retrieval. What changes is where the secret lives and who can account for it, so a database password or a legacy API key stops sitting in each agent’s configuration and starts being requested under policy like anything else.

Two boundaries are worth stating plainly. The Application does receive the credential, so this brings the access under policy and audit rather than keeping the secret out of the agent’s hands. And a static credential is withdrawn by rotating it rather than by letting it expire, so containment behaves differently from the short-lived path above. Resources covers all three credential paths and what each one gives you.

The support desk above is one shape. The same flow covers:

  • A business intelligence agent querying a warehouse as the analyst who asked, so row and column permissions already in the warehouse still apply
  • An operations agent filing a change request as the engineer requesting it, so the approval chain sees a person rather than automation
  • A sales agent reading and updating CRM records as the rep who owns them, rather than through an integration user that can see the whole pipeline
  • A document agent retrieving files as the employee who asked, so anything they could not open themselves stays closed

In each case a person makes a request, an agent does the work, and a downstream system needs to see the person rather than the agent. That is the invariant, and the identity provider, the Resource, and the agent framework are all variables you can change without changing the pattern.