Skip to content

Bot-token credential tenancy

Family
credential-tenancy
Status
proven
Complexity
low
Advances
PL4-least-privilege PL3-communication PL2-agent-audit-trail
Prerequisites

Bot-token credential tenancy

Purpose

Narrow the blast radius of a credential by using a purpose-built identity whose reach is inherently smaller than the acting user’s, rather than constraining what a broader credential can do after the fact. Permission lists are advisory; credential tenancy is structural.

Architecture

  • Create a dedicated bot / service / project-scoped account on the target platform (Slack bot, GitHub App, Google service account, purpose-created free Granola account, etc.).
  • The account’s own identity determines reach: a Slack bot can only see channels it’s invited to; a GitHub App can only see repos it’s installed on; a project Granola account can only see notes shared with it.
  • Use the account’s token or installation credential for agent operations. Never use the operating user’s personal token to proxy agent actions.
  • Where available, pair with a second-layer enforcement at the tool / MCP layer (env var pinning, tool registration allowlists) — see the two-layer MCP scoping recipe.

The central property: removing a permission from a broad credential requires ongoing vigilance; keeping a narrow credential narrow is the default. The mechanism inverts the failure mode from “scope creeps up” to “scope stays at ground” until a human explicitly broadens it.

Criteria advanced

  • PL4-least-privilege IAM scoped read-only by default — direct level-2 contributor. Strict least-privilege is credible because the credential’s reach is structurally bounded, not because the permission list is currently short. A user OAuth with the same “current” scope is not equivalent — future permission additions to the upstream identity would silently broaden the agent’s reach.
  • PL3-communication Communication actions — partial contributor to level-2. The mechanism narrows who the agent can reach, which is one of the five structural-safety layers level-2 requires (recipient allowlist); other layers (content filter, dry-run default, rate limiting, human approval) are independent.
  • PL2-agent-audit-trail Agent action audit trail — partial contributor to level-2. Platform-level action logs are naturally scoped to the bot’s identity, giving clean separation between agent activity and human activity. Doesn’t provide decision-level reasoning on its own — that needs additional instrumentation.

Prerequisites

None structural — the recipe works from a clean start. The platform must expose a bot / service / project-account primitive, which most major platforms do. Where one doesn’t (legacy systems with user-only auth), this recipe is not applicable and a different mechanism is needed.

Failure modes

  • Scope creep. The bot gets added to more channels / folders / orgs over time because each addition seems reasonable in isolation. A year later it can reach far more than anyone remembers. Mitigation: record scope rationale in the corresponding internal/integrations/* entry, and treat every scope broadening as requiring an updated rationale line. Quiet broadening is the signal of mechanism failure.
  • Credential handling. Bot tokens are still secrets; a leaked token grants whatever the bot can reach. Mitigation: treat bot tokens as first-class secrets (see CLAUDE.md secret handling), store in gitignored .env.local or equivalent, rotate on any exposure.
  • Platform startup scopes. Some platforms require broader read scopes than the agent’s registered tools use — e.g. Slack’s users.list / conversations.list cache warm. These enumeration surfaces don’t reflect operational capability but can be mistaken for it during scoring. Mitigation: document the enumeration surface explicitly in the integration entry, distinguishing it from operational reach.
  • “Bot approves bot” loop collapse. If the bot account can approve PRs, sign releases, or merge changes that affect its own scope, the least-privilege property collapses at the first mistake. Mitigation: keep write-authority on policy artefacts (the PR-elevation template, the Slack app config) behind human credentials, not bot credentials.

Cost estimate

Low. Most of the cost is one-time platform setup: creating the account, installing the app, collecting the token. Ongoing cost is negligible for a single bot; the discipline investment is the scope-rationale convention, which only bites when someone tries to quietly broaden scope.

Case studies

  • Slack — Apptivity Lab workspace (internal/integrations/slack-apptivity-lab.md). Bot token for #agentic-engineering, scoped to a single channel via two-layer enforcement (bot invitation + SLACK_MCP_ADD_MESSAGE_TOOL env pin). Contrast: a user OAuth would have exposed every channel Jason sees in the Apptivity Lab workspace; the bot-token mechanism kept the agent’s reach to exactly what was deliberately granted.

  • Adjacent: the Granola integration (internal/integrations/granola.md) applies the same tenancy-narrowing principle on a platform without a formal bot primitive — a dedicated free account becomes the “bot” and collaborators share into it. That mechanism is captured separately as the project-scoped reader account recipe in the same family. Use bot-token where the platform offers a first-class bot primitive; use project-scoped reader account where it doesn’t.

  • Same family as: project-scoped reader account — the no-bot-primitive variant of the same tenancy-narrowing principle.
  • Composes with: two-layer MCP scoping (credential layer + tool-registration layer). Neither alone is sufficient; the pair is structural.
  • Composes with: tool-level enumeration denial (keep get_by_id, remove list / search from the registered tool surface). Narrows the credential’s effective reach further at the tool layer.
  • Alternatives to: scoping a user OAuth via permission revocation. Same surface area on paper; structurally weaker because any future permission granted to the user silently flows to the agent.