> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rhinestone.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Restrict a session

> Drop the intent-execution fallback so a session runs only the calls it lists.

By default, a session with permissions also carries a wildcard intent-execution fallback: a call that matches none of its permissions is not rejected, it is executed as an intent through the Orchestrator. This is what lets a scoped session drive Warp intents instead of only the calls it lists.

Set `restrictToActions` to drop the fallback. The session's permissions and actions are then the only calls it can run, and any other call reverts:

```ts {14} theme={null}
const session = await rhinestone.createSession({
  chain: base,
  owners: {
    type: 'ecdsa',
    accounts: [sessionOwnerAccount],
  },
  permissions: [
    {
      abi: erc20Abi,
      address: usdcAddress,
      functions: { transfer: {} },
    },
  ],
  restrictToActions: true,
})
```

The tradeoffs:

* The session can no longer sign arbitrary Orchestrator intents. Only its explicit permissions and actions execute.
* It needs at least one permission or action. A restricted session with neither is rejected.
* It cannot be combined with `crossChainPermits` or `claimPolicies`, whose spending and time-frame guardrails live inside the fallback.
* Signing defaults to `disabled`, so the session key cannot sign an approval off-chain. Set [`signing`](./session-signing) explicitly if the session needs ERC-1271 signatures.

<Note>Requires `@rhinestone/sdk` 2.6.0 or later.</Note>

## Raw scoped actions

Permissions are derived from an ABI, so they can only address calls you can name as a function on a contract. Use `actions` for the rest — a call whose ABI you don't have, or one you want to scope by selector directly:

```ts {7-13} theme={null}
const session = await rhinestone.createSession({
  chain: base,
  owners: {
    type: 'ecdsa',
    accounts: [sessionOwnerAccount],
  },
  actions: [
    {
      target: routerAddress,
      selector: '0x3593564c',
      policies: [{ type: 'usage-limit', limit: 10n }],
    },
  ],
  restrictToActions: true,
})
```

Each entry takes a `target`, a `selector`, and optional `policies`. Three rules the SDK enforces:

* An entry must be scoped: both `target` and `selector` are required. A fallback-shaped entry is rejected, because it would map to the wildcard fallback target.
* An entry may not target the fallback sentinel, which would reintroduce the wildcard the restriction drops.
* A raw action must not collide with a `permissions` entry on the same `(target, selector)` pair. The two share one on-chain action id, so merge them into a single entry instead.

A [swap scope](./swap-sessions) is sugar over exactly these two primitives: it compiles to an approve permission plus one scoped action per swap venue, and implies `restrictToActions`.
