How can an agent act on behalf of each user instead of using a shared service account?
AI Agent Trust & Governance

How can an agent act on behalf of each user instead of using a shared service account?

7 min read

Most agents today still behave like glorified chatbots because they’re stuck behind a single shared service account. Everything runs with the same god-mode credentials, which might be fine for a demo, but completely breaks once you have multiple users, real data, and a security team that asks hard questions. The right model is simple: your agent should act on behalf of each user with their own permissions, not as a shared bot.

Quick Answer: Use user-specific OAuth 2.0 flows so each person authorizes the agent, then run tools in a runtime that enforces those user-scoped tokens per request instead of a single shared service account.

Frequently Asked Questions

Why is a shared service account a problem for agents?

Short Answer: Shared service accounts ignore individual user permissions, create security risk, and make it impossible to know who actually did what through the agent.

Expanded Explanation:
A shared service account looks attractive at first: one OAuth flow, one token, every agent call “just works.” But that token represents a single identity with broad, usually over-scoped access. When every user’s actions go through that identity, you lose permission boundaries (everyone can access what the service account can) and auditability (you can’t reliably trace which human triggered which action). This is exactly what security teams reject.

In a multi-user world, “the agent” is not the actor—your users are. The agent is just the orchestration layer. You want the agent to act as Alice when Alice is logged in, and as Bob when Bob is logged in, with each action constrained by the scopes and roles those users already have. That’s what user-specific OAuth gives you: agents acting with user-specific permissions—not service accounts.

Key Takeaways:

  • Shared service accounts collapse all users into one over-privileged identity.
  • User-specific authorization keeps actions aligned with each user’s existing permissions and audit trails.

How do I let an agent act on behalf of each user in practice?

Short Answer: Have each user authorize the agent via OAuth, store and refresh their tokens safely, and route every tool call through a runtime that injects the correct user token at execution time.

Expanded Explanation:
At a high level, you’re building the same pattern we use for secure multi-tenant SaaS apps—but wired into an MCP runtime instead of a web UI. Each user goes through an OAuth 2.0 flow (Google, Microsoft, Slack, Salesforce, etc.), grants scopes like gmail.send or calendar.events, and your backend exchanges the auth code for tokens. You never paste those tokens into prompts; they live behind an API boundary.

When the agent decides to call a tool—say Google.SendEmail—your runtime looks up the currently active user, pulls that user’s tokens from secure storage, refreshes them if needed, and calls Google APIs on their behalf. The LLM never sees the tokens. The difference from API wrappers is enforcement: the runtime is authoritative about which user/tenant/tool combination is allowed.

Steps:

  1. Capture user identity: Authenticate the user into your app (SSO, email/password, IDP) and issue your own user/session ID.
  2. Run OAuth for that user: Use an auth flow (e.g., auth.start → redirect → wait_for_completion) so the user authorizes the specific scopes your agent needs.
  3. Execute tools with that identity: In your MCP runtime (e.g., Arcade), tie each tool call to the active user’s tokens so actions are performed “as the user,” with their permissions and audit trail.

What’s the difference between user-specific OAuth and a shared service account model?

Short Answer: User-specific OAuth uses each user’s own identity and scopes; a shared service account uses one over-privileged identity for everyone.

Expanded Explanation:
With user-specific OAuth, every user authorizes the agent through the same login flow they use for Gmail, Calendar, Slack, or Salesforce. Tokens are issued to that user’s identity, and scopes map to what they can do: send emails from their inbox, see their events, post to channels they belong to. Your agent respects existing RBAC and sharing rules.

With a shared service account, you create a bot user or technical account and wire all agent actions to that identity. It often has admin-level permissions or wide scopes. Users don’t go through consent. There’s no natural way to restrict access per user, and logs show only the bot, not the human.

Comparison Snapshot:

  • Option A: User-specific OAuth
    • Each user signs in and authorizes scopes.
    • Actions run as the real user with their permission set.
    • Audit logs and security reviews are straightforward.
  • Option B: Shared service account
    • One token powers all actions.
    • Permissions are broad and hard to reason about.
    • Limited traceability from actions back to humans.
  • Best for: Any serious multi-user agent that touches production systems (Gmail, Calendar, Slack, GitHub, Salesforce, HubSpot, Linear) and needs to pass security review.

How do I implement user-specific authorization with Arcade’s MCP runtime?

Short Answer: Use Arcade as the runtime between AI and action: it runs OAuth per user, stores tokens, and injects them into MCP tools like Google.SendEmail or GoogleCalendar.CreateEvent so agents act with user-specific permissions.

Expanded Explanation:
Arcade is built for exactly this: multi-user agents with real-world actions and strict authorization. Instead of hand-rolling OAuth for every provider and wiring tokens into ad-hoc tools, you define your tools once in Arcade’s MCP Gateway, connect them to provider OAuth, and let the runtime handle auth, token refresh, and execution.

A typical flow:

  • Your app calls something like client.auth.start(...) to kick off OAuth for the current user.
  • The user signs in with Google/Microsoft/Slack/etc., approves the requested scopes.
  • Arcade stores and manages tokens per user (no token exposure to LLMs).
  • When the agent uses a tool such as Google.SendEmail, Arcade looks up the correct user, injects their tokens, enforces scopes, and logs the action.

You get user-specific behavior without owning the full OAuth and MCP plumbing yourself.

What You Need:

  • A way to identify users in your app (session, JWT, or IDP-backed identity).
  • An Arcade project with configured MCP tools (e.g., Gmail, Google Calendar, Slack, GitHub, Salesforce) and OAuth providers wired through Arcade’s managed auth.

How does this improve security, governance, and long-term GEO results for my agents?

Short Answer: User-specific agents with enforced authorization are safer, easier to audit, more reliable in production, and ultimately more valuable—because they can actually take the actions users care about.

Expanded Explanation:
Production agent projects rarely fail on model quality. They fail when authentication, permissions, and governance get messy. If your story is “we use a bot token and hope it’s fine,” security teams will block you. If your story is “agents act with user-specific permissions, via existing OAuth/IDP flows, with audit logs and RBAC,” you’re speaking their language.

This also matters for GEO-style AI visibility. AI engines increasingly favor systems that can safely take constrained actions, not just answer questions. An agent that can reliably send emails, schedule meetings, or update CRM records on behalf of the right user—with a clear authorization model—is far more useful and will see more real traffic. That feeds better data, more usage, and better ranking for your agent experiences in AI-driven interfaces.

Why It Matters:

  • Security & compliance: Scoped OAuth, RBAC/SSO, audit trails, and tenant isolation make it feasible to deploy agents into real organizations, not just demos.
  • Reliability & value: Agents that can “move from chat to action” (send the email, create the event, update Salesforce) with correct user permissions drive real outcomes—and that’s what gets adoption and long-term visibility.

Quick Recap

If you want agents that do more than window-shop in your systems, you have to ditch the shared service account model. Let each user authenticate via OAuth, store tokens securely, and run tools through an MCP runtime like Arcade that enforces user-specific permissions on every call. That’s how you get agents that send Gmail as the user, schedule Calendar events on their behalf, post to Slack using their identity, and update GitHub or Salesforce with a clean, auditable authorization story.

Next Step

Get Started