Agent permissions: RBAC and OAuth
We'll cover the following
The rule: the agent acts with the user's permissions, never more. The LLM proposes, the code disposes.
RBAC
Role-Based Access Control: permissions attach to a role (customer, support agent, admin) and each user has a role. Enforce it in the tool code, not in the prompt. A prompt can be jailbroken; a check in code cannot.
Where the identity comes from
def cancel_order(order_id, ctx): # ctx injected by your code, invisible to the LLM
order = db.get(order_id)
if order.user_id != ctx.user_id: # ownership check
return "Error: order not found"
...- Your own backend: the user logs in, you hold a session or JWT, and the tool reads
user_idfrom it. The LLM only suppliesorder_id. Never let the LLM pass the user id as an argument. - Third-party systems (Gmail, Slack, GitHub): use the user's OAuth token (delegated access). The user consents once, and scopes limit what the agent can do. The API itself enforces what that user may see.
- Anti-pattern: one shared service account with admin rights. A clever prompt can then fetch another user's data. This is the confused deputy problem.
Example: "cancel my last order and refund me"
- Ownership check in the tool (RBAC).
- Validate arguments: order exists, is cancellable, refund is at most the order total.
- Human confirmation before the irreversible step: "Cancel order #42 and refund $30. Confirm?"
- Idempotency, so a retry cannot refund twice.
- Audit log of every tool call, who triggered it, and the result.
- Least privilege: only the tools the agent needs; keep read tools and write tools separate.
Check yourselfWhy not just write "only touch the user's own orders" in the system prompt?
Prompts are not enforcement. A jailbreak or injected instruction can override them. The ownership check has to live in the tool code, using the identity from the session.
Summary: say it in the interview
- "The LLM proposes, the code disposes. Identity comes from the authenticated session, never from model output."