Use cases/Lanes Link/Run Claude Tag on your own access layer

Run Claude Tag on your own access layer

Add one Lanes Link endpoint to a Claude Tag access bundle and the channel gets exactly the connections and capabilities that profile grants, narrowed in a policy file rather than by minting service accounts.

Claude Tag gives a Slack channel an agent, and an access bundle gives that agent credentials. The idea is right: name a set of connections, attach it to a scope, and everyone in that channel acts through it.

The granularity is the problem. A bundle can say which tools Claude reaches. It cannot say how far into any one of them.

Anthropic's own docs are direct about it:

A connection has no setting for which pages, folders, or projects Claude can reach inside a tool. The connection's reach is whatever the connected account can access in that tool. To narrow Claude to a subset, narrow the account.

So scope is not a setting. It is a second service account created in the vendor, a second credential, and its own bundle to keep it out of every other channel.

Do that for four channels and three tools and you are maintaining twelve identities to express twelve lines of policy. Most people do not. They connect one account with broad reach and over-provision every channel that touches it.

  • One row per connection, with its own rules. A profile's grants: names each connection as <provider>.<id> and carries its own allow and deny globs. Read one mailbox and write the other is a thing you can actually write down, on the same profile, without a second account anywhere.
  • A connection with no row is absent, not denied. An agent asking that profile never learns the connection exists. An unused connector is not something to hope nobody talks their way into, because it is not in the tool list.
  • Narrowing is a line in a file. lanes link policy deny gmail.send --profile support takes effect at once. A deny always beats an allow whatever the order, an absent rule grants nothing, and a rule can carry expires_at for access you want to hand out for an afternoon.
  • One connection in the bundle, however many accounts behind it. The bundle holds a single Bearer credential and a single allowed host. Everything past that host is your profile's business, so connecting a twelfth account changes nothing in the admin console.
  • The token is the profile. auth.token_ref lives inside the profile file, so the credential a channel holds resolves to exactly one profile's grants. Two channels, two tokens, two profiles, and no shared ceiling between them.
  • One audit log across every provider. Append-only, one record per invocation with refusals included, hash-chained, and lanes link audit verify walks the chains. A bundle leaves you reading each vendor's own log, where every call is attributed to the same service account.
  • The same grants serve every other client. Claude Code, Codex, claude.ai, ChatGPT, a phone, and a Slack channel read one profile. An access bundle only ever applies in Slack, and personal claude.ai connectors only ever apply in DMs.

The workflow

One profile per channel scope, named after the work rather than the team: support, data-readonly, deploys. Grant narrowly, then let refusals tell you what the channel actually needs.

lanes link audit tail --denied-only is a better specification than any guess you make up front. A refused call is the boundary working, not an obstacle to route around.

After that the operations are small. Adding an account is connect. Widening is one policy line. Revoking is lanes link token rotate, which invalidates what that channel holds without touching another channel.

None of it is a trip through the admin console, and none of it is a new identity in someone else's product.

Set it up

Claude Tag runs its sessions in a cloud sandbox Anthropic hosts, and it can only attach an MCP server it can reach at a URL. A loopback endpoint on your laptop is not reachable, so this is the deployed path:

console
$ bun install -g @lanes-sh/link
$ lanes link profile add support
$ lanes link deploy --workspace cloud
$ lanes link connect zendesk --id helpdesk --workspace cloud
$ lanes link grant add zendesk.helpdesk --profile support --workspace cloud
$ lanes link outputs --workspace cloud

Then:

  1. Answer public, and yes to a remote connector. Two of the deploy questions decide whether an agent can reach the endpoint at all. The iam default has Cloud Run demand a Google-signed token no MCP client can mint, and the second answer is what lets the endpoint issue its own.

  2. Grant only what the channel does. lanes link grant add per connection, then policy deny for the verbs it should not have. Everything you do not name stays denied.

  3. Add it to the bundle. In Claude Tag's admin settings, the Plugins tab takes a plugin whose .mcp.json points at the endpoint URL. The Credentials tab takes Custom tool, credential type Bearer, the token from outputs, and Allowed websites set to the endpoint host.

    That pair is the documented way to attach a remote MCP server. An .mcp.json in a repository Claude clones is not loaded.

  4. Attach the bundle to the channel, then read the log. Ask Claude in a new thread for a small read to confirm the credential is live, and watch audit tail --denied-only for the first week to find a scope that is too tight.

This does not take the admin console out of the loop, and it should not be sold as if it did. You still create a bundle, and everyone in the channel still shares the profile: members: gates who may mint a token, not who may type @Claude in a channel whose bundle already holds one. What changes is the shape of the thing in the bundle: a credential you can narrow per connection and per capability, rather than an account whose reach you can only reduce by making a different account.

Further reading

Browse the source at lanes-sh/link, Apache-2.0, or read the announcement.