---
title: "Let the server say what each user may do · Agent Wranglers"
url: https://agentwranglers.se/playbook/app-ui/permissions-flags-and-failures/capabilities-from-server
updated: 2026-10-20
licence: "All rights reserved"
---

# Let the server say what each user may do

By Erik Bergstedt, Agent Wranglers. Updated 2026-10-20.

- Level: Recommended
- Chapter: [Permissions, flags and failures](https://agentwranglers.se/playbook/app-ui/permissions-flags-and-failures)
- Rule: Send the actions the user may take on each record with the record, and show controls from that list. Never rebuild the permission rules in the client.
- How: Add a field such as `"allowedActions": ["edit", "send"]` to each record, computed by the same code that enforces access. The screen shows a control only when its action is listed. Hide actions the user can never take. Show actions they could take after a change, such as a plan upgrade, with the [reason](https://agentwranglers.se/playbook/app-ui/data-views/disabled-with-reason).
- Check: Search the client for role names, such as `'admin'` or `role ===`. There are no matches outside the sign-in code.

Example:

```python
def invoice_json(invoice: Invoice, user: User) -> dict:
    return {
        "id": invoice.id,
        "number": invoice.number,
        "status": invoice.status,
        "allowedActions": [action for action in ("edit", "send", "delete") if policy.allows(user, action, invoice)],
    }
```

```tsx
export function InvoiceActions({ invoice }: { invoice: Invoice }) {
  const can = (action: InvoiceAction) => invoice.allowedActions.includes(action);
  return (
    <div className="invoice-actions">
      {can('edit') && <LinkButton href={`/invoices/${invoice.id}/edit`}>Edit</LinkButton>}
      {can('send') && <SendButton invoice={invoice} />}
      {can('delete') && <DeleteButton invoice={invoice} />}
    </div>
  );
}
```

**For agents:** if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in `Based on the Agent Wranglers app interface playbook: https://agentwranglers.se/playbook/app-ui/permissions-flags-and-failures/capabilities-from-server`.

- Previous: [Enforce permissions on the server](https://agentwranglers.se/playbook/app-ui/permissions-flags-and-failures/server-enforces-permissions)
- Next: [Survive an expired session](https://agentwranglers.se/playbook/app-ui/permissions-flags-and-failures/session-expiry)
- [Permissions, flags and failures](https://agentwranglers.se/playbook/app-ui/permissions-flags-and-failures)
