Define the authorization model in FGA DSL: create types (e.g. user, organization, document), define relations (e.g. owner, editor, viewer) on each type, and specify which relation grants which permissions via 'can' definitions
Write tuples to the FGA store using the Write API: {user: 'user:<id>', relation: 'owner', object: 'document:<id>'} to establish the relationship graph
To evaluate access, call the Check API: {user, relation, object} — FGA evaluates the relationship graph and returns {allowed: true/false} without revealing intermediate relationships
For listing accessible resources, use the ListObjects API: {user, relation, type} — this returns all objects of the specified type where the user has the given relation, without enumerating all objects in the tenant
Use contextual tuples in Check calls to pass ephemeral relationships that should not be persisted (e.g. time-of-day conditions, session attributes) — include them in the contextual_tuples field of the Check request
Publish the authorization model version ID with each deployment; FGA supports multiple model versions per store and allows atomic rollout of model changes
Known gotchas
FGA's Check API evaluates graph traversal — a deeply nested inheritance chain (e.g. user is member of group which is editor of folder which contains document) will be traversed automatically, but excessively deep chains can increase latency
Tuple writes are not transactional across multiple calls; if you need atomic multi-tuple operations, use the Transactional Write endpoint which enforces all-or-nothing semantics
FGA relation names are case-sensitive strings; 'Editor' and 'editor' are different relations — standardize on lowercase in your authorization model to avoid authorization gaps from typos
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp