Skip to content

Grant scoped access

A capability is a signed token for one action on one service, with an expiry. It is not a network hole and not an account: nothing about the service changes when you issue one, and nothing needs changing when it expires.

Terminal window
fabric grant llm://codegen-llm --action invoke --ttl 30m

The output is the token. Give it to whoever needs the access.

The holder exchanges the token for the live coordinates of the service:

Terminal window
fabric resolve codegen-llm --action invoke --cap <token>

The gateway checks the capability before answering. A resolve without a valid token is refused, so the token — not network position — is what grants reach. From there the caller talks to the service directly over the mesh; the exchange is the last time the control plane is involved.

When the caller is you, on the machine that runs the gateway, minting and pasting a token every ten minutes guards nothing. Run the gateway in self-serve mode instead and point the SDK at it with any placeholder key:

Terminal window
fabric gateway proxy --self-serve
Terminal window
export OPENAI_BASE_URL=http://127.0.0.1:7777/gw/<network>/codegen-llm
export OPENAI_API_KEY=local

Each request that carries no capability gets one minted on your session and renewed before it expires, for as long as the gateway runs. The base URL keeps working; nothing to re-grant. A request that carries a real capability is still authorized by that capability, so a teammate’s token works through the same gateway.

Self-serve only binds to loopback. Anything that can reach the port can reach every service your session can, so the gateway refuses to self-serve on an address other machines could reach.

The action must match what the caller will actually do. Granting more than they need is the whole thing this mechanism exists to avoid.

service kindusual action
llm, router, endpointinvoke
mcpread
a2adelegate
tcpconnect

--ttl defaults to 10 minutes, which is right for handing someone a token in chat while they are at their keyboard. Longer lifetimes are for automation that cannot be re-issued interactively.

Terminal window
fabric grant mcp://local-files --action read --ttl 8h

Prefer a short lifetime and a re-issue over a long one you will forget about. There is no revoke-a-single-token command by design — the expiry is the revoke, which is why it is worth setting deliberately.

If the service was published with --scope, a capability only works when it carries the matching scope. Publishing and granting have to agree:

Terminal window
# on the machine hosting it
fabric serve http://127.0.0.1:8080 --name payroll-api --kind endpoint --scope finance
# when granting
fabric grant endpoint://payroll-api --action invoke --ttl 1h

A caller without the scope gets a refusal from the gateway, not a timeout.

--json gives a parseable result rather than the human-readable block:

Terminal window
TOKEN=$(fabric grant llm://codegen-llm --action invoke --ttl 15m --json | jq -r .token)
fabric resolve codegen-llm --action invoke --cap "$TOKEN" --json

The control plane mints and verifies the capability, so it knows that a token was issued for a resource and an action, and it counts the resolve. It does not see the traffic that follows — the caller reaches the service directly over the encrypted mesh.