Access Profiles | Lanes Link

5 min read Original article ↗

An Access Profile is the answer to one question: what may this agent reach, and who is allowed to use it?

Everything else in Lanes Link, the accounts you connect, the memory you keep, the skills you write, is reached through a profile. Create one per boundary you actually keep. Most people start with one and add a second the first time they want work and personal kept apart.

What a profile decides

Which accounts it reachesOf everything connected to the workspace, a profile reaches only what it has been granted. Anything else is not listed at all, so an agent never learns it exists
What it may do with eachPer connection, an allow list and a deny list. Read one mailbox, write another
Who may use itThe people whose sign-in resolves to this profile. Empty means nobody
Its own materialIts memory, tasks, assets, skills, entities and vault are its own. What you write under work is absent under personal

Two things it does not decide. Connecting an account belongs to the workspace, not to a profile: you connect Gmail once and then grant it to whichever profiles should see it. And the audit log is the workspace's, so one log covers everything every profile did.

Create one

An empty members list means nobody, not everybody. Identity is deny-by-default too, so a profile with nobody on it serves nobody. profile add puts the signed-in subject on the profile it creates, which is why there is no second command here. A profile created before anyone signed in has an empty list, and lanes link profile members add --me --profile <name> is how you fix that.

Members come in two roles, owner and member. Neither changes what a caller reaches or may call: being on the list decides the first, and grants decide the second. The roles are recorded against the day one of them means something here, and today the check that decides who may edit a list is the workspace's own: on a profile in a workspace bound to a Lanes workspace, editing members: asks for an admin there. It is CLI-only either way, so an agent that reaches a profile still cannot add itself to another.

Give it an account

Connecting and granting are separate steps. Connect once at the workspace, then grant per profile:

lanes link revoke takes it away again. A connection you never granted is invisible to that profile rather than merely refused, which means an agent cannot even discover the account is there to ask about.

Say what it may do

Three rules worth knowing, because they decide what actually happens:

  • A deny beats an allow, wherever either sits in the file. You never have to reason about ordering.
  • Patterns are globs. gmail.* grants the provider; gmail.send_message grants one call.
  • A rule can expire. Give it an expires_at and the access ends on its own, which is how you hand out something temporary without having to remember to take it back.

Start narrow and let refusals tell you what the work actually needs:

A refused call is the boundary doing its job. What got refused is a better specification than any list you write up front.

What arrives switched on

A new profile can already reach your own material: memory, tasks, assets, skills, entities, the vault, and the setup surface. None of them touches a third-party account, none has a credential, and each is empty until you put something in it, so there was never anything to authorise. lanes link policy deny is how you take one away.

Two profiles, one endpoint

One endpoint serves every profile in the workspace, and every tool call names the profile it is for. There is no current profile to switch and no default to get quietly wrong, and naming a connection from another profile is refused before anything is dispatched.

Where the boundary really is

Worth being plain about, because it decides how far this protects you.

Profiles separate what a caller reaches, and every way in asks who is calling. An agent's token names the person it was issued to, and the dashboard's names the person who signed in, so both reach the profiles whose members: list them and no others. A profile you are not on is not listed to you, rather than listed and refused.

What a profile does not separate is what one agent does with what it was given. A token that reaches work reaches all of work, so an agent you have handed that token to is inside that boundary rather than held by it. When you need one that holds against the agent itself, use a second workspace. It has its own credential store, its own tokens and its own audit log, and nothing crosses between them.

Naming them

Name a profile after the work rather than the person or the team. support, data-readonly and deploys each say what may happen inside them; alex and team-2 do not, and drift the moment either changes.


Next: Scopes and permissions for what a grant can and cannot express.

Notes

Where a profile lives. ~/.lanes-link/profiles/<name>/profile.yaml, holding grants: (one row per connection, each with allow and deny) and members:. It is a file you can read, and the CLI edits it for you.

Removing one. lanes link profile remove <name> --workspace <name> names its workspace explicitly, because it destroys. --dry-run shows what would go, and --migrate-to <other> moves what it owns rather than deleting it.

A default for the CLI only. lanes link profile default <name> saves you typing --profile on every command. It is a convenience for your terminal, not a setting agents see: a tool call still names its profile every time.