DEV Community

Cover image for How to safely let AI agents act on behalf of users
Saif
Saif

Posted on

How to safely let AI agents act on behalf of users

When you introduce AI agents into production systems, they don’t just run in isolation. They often act on behalf of real users—querying dashboards, triggering deploys, posting comments, or raising incidents.

The problem? Traditional OAuth and identity systems were built for single-user sessions, not autonomous agents. If you let agents impersonate users directly, you end up with over-permissioned, untraceable access.

That’s where On-Behalf-Of (OBO) authentication comes in. It creates a secure way for agents to operate with scoped, revocable permissions, while maintaining a clear audit trail that says exactly who acted, on whose behalf, and within which scopes.

The challenge: Delegation in AI workflows

Imagine your DevOps team builds an AI agent called InfraBot. Its job is to:

  • Query metrics from Datadog
  • File alerts in PagerDuty
  • Post comments on GitHub pull requests
  • Trigger rollbacks in ArgoCD

InfraBot should act only with the permissions of the engineer who initiated the action. But today’s identity systems don’t support this dual identity (user + agent). Without OBO, you end up with:

  • Tokens tied only to agents means no attribution to the human who delegated authority
  • Over-permissioning means agents get more access than they need
  • Weak audit trails mean logs just say “InfraBot did X”

How OBO works: dual identity in tokens

OBO authentication encodes both the agent and the user inside a single token. This is done using structured JWT claims.

Here’s a simple example of a decoded JWT payload:

{
  "sub": "agent:infrabot",
  "act": {
    "sub": "user:eng123",
    "scope": ["incident:read", "monitoring:query"]
  }
}
Enter fullscreen mode Exit fullscreen mode

This tells downstream systems:

  • The agent making the request is agent:infrabot
  • The user who delegated authority is user:eng123
  • The scopes permitted are incident:read, monitoring:query

Now, when InfraBot calls GitHub or PagerDuty, those systems know both who executed the request and who authorized it.

Scoped, explicit, and revocable permissions

Delegation should never mean “full access.” Tokens must be:
Explicit: Only the required scopes (e.g., deploy:create)
Scoped: Limited to specific resources or environments
Temporary: Short-lived (5–15 minutes)
Revocable: Tied to user state so that if Sam loses deploy access, InfraBot loses it too

Here’s an example of a structured, short-lived delegation token:

{
  "sub": "agent:infrabot",
  "act": {
    "sub": "user:sam",
    "scope": ["urn:infra:monitoring:read"],
    "context": {
      "trigger": "ci_pipeline",
      "environment": "prod"
    }
  },
  "exp": 1722000000,
  "revocation_url": "https://auth.company.com/revoke/token123",
  "log_url": "https://audit.company.com/logs/token123"
}
Enter fullscreen mode Exit fullscreen mode

Multi-level delegation: Chaining identities

Things get more complex when agents call other agents. For example:
Sam → InfraBot → ArgoCD → AWS

Nested claims in the token can represent that chain:

{
  "sub": "agent:argocd",
  "act": {
    "sub": "agent:infrabot",
    "act": {
      "sub": "user:sam",
      "scope": ["deploy:create"]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Downstream services can then parse the chain and know:

  • Sam triggered the workflow
  • InfraBot delegated to ArgoCD
  • ArgoCD is the final executor
  • Enforcing delegation in your services

Issuing tokens is only half the work. Every service receiving the token must:

  • Validate the chain of actors (sub + act.sub)
  • Enforce scopes against allowed operations
  • Log both the agent and the user

Here’s a simple Node.js middleware example:

function delegationMiddleware(req, res, next) {
  const token = req.headers.authorization?.split(" ")[1];
  const payload = jwt.verify(token, publicKey);

  req.agent = payload.sub;
  req.user = payload.act?.sub;
  req.scope = payload.act?.scope || [];

  if (!req.user) return res.status(401).send("Missing delegation context");
  next();
}
Enter fullscreen mode Exit fullscreen mode

Takeaways

Are your AI agents still using service accounts or static tokens? Start by:

  • Issuing structured tokens with both agent + user identities
  • Enforcing scopes at runtime in your APIs
  • Shortening token lifetimes and adding revocation checks
  • Logging both the actor and delegator in every request

Building trustworthy delegation is the difference between uncontrolled automation and secure, enterprise-ready AI workflows.

Want to go deeper? Check out the full write-up here: Understanding On-Behalf-Of in AI agent authentication

Top comments (0)