Agency AI Access Model

How an agency team shares one capability layer with different levels of access. The owner and the automation engineer build the tools; everyone else consumes them through scoped channels. Access is enforced at the channel, not inside each skill.

1 — Agency Team
2 — Access Interfaces
3 — Shared Capability Layer
👑
Owner (James)
Full access to every repo, every skill, every channel. Builds tools alongside the engineer.
🛠
Automation Engineer
Builds new skills, edits CLAUDE.md and hooks, ships updates. No client-data access by default.
📝
Content Lead
Reviews and merges content PRs, uses scoped local CLI, approves writer work before it ships.
Content Writer
Writes blog posts, social copy, and article drafts. Local CLI on content repos, or Discord only.
💼
Account Manager
Pulls client reports, runs CRM-scoped skills, drafts client-facing updates. Discord-only.
👤
Junior / Client-Facing
Minimal access. One Discord channel. Can only run what their channel exposes.
Full Local Claude Code CLI
Clones every repo locally. Runs Claude Code with no scope restrictions. Can git push directly to main. The "build the tools" tier.
git push main all repos all skills
Scoped Local CLI + Pull Requests
Clones only approved repos. Runs Claude Code locally. Pushes go to feature branches, merging is via pull request and requires review.
cloned repos only PR workflow review required
Discord Bot
No local clone. No git. The only interface is a Discord bot that runs inside specific channels. Each channel exposes a different subset of skills.
#owner-ops #dev-ops #content-writing #client-ops
Each channel's bot knows which skills it is allowed to expose.
The runtime sees the request and trusts the channel's permission check.
GitHub Repos (granular access)
The source of truth for every skill, hook, and CLAUDE.md rule. Access is per-repo — team members see only what they need.
Claude Code Runtime
Executes any skill that has been loaded from the repo. Does not enforce role-based access itself — trusts the calling channel's permission check.
~/apps/cc/ + ~/.claude/ · hooks · skills
External APIs
Every service the runtime reaches out to. Credentials live in shared-secrets.env, never in any role's hands directly.
Owner access
Automation Engineer
Content Lead
Content Writer
Account Manager
Junior / Client-Facing
Shared-layer flow

How to read this diagram

Three columns, three levels of trust.

Column 1 — who the person is. The role they hold in the agency.

Column 2 — how they reach the tools. This is where access control actually lives. A full CLI user can do anything. A scoped CLI user can only touch specific repos and must go through pull requests. A Discord user never touches code at all — they just talk to a bot in a specific channel, and the channel decides what they are allowed to run.

Column 3 — what they are reaching. One shared capability layer: the GitHub repos that define the skills, the Claude Code runtime that executes them, and the external APIs the skills call. Everyone hits the same layer. The difference is how they get there.

Four example flows

Owner writes a blog post locally. Owner opens Claude Code CLI, runs /create-blog-post, the runtime invokes the skill, the skill edits a markdown file in the TMS repo, Owner pushes to main, Vercel deploys.

Content Writer writes a blog post via Discord. Writer types /write-post about X in #content-writing. The Discord bot checks the channel's permission list — /create-blog-post is on the allow list. The bot invokes the skill in the runtime. The runtime opens a pull request against the TMS content repo. The Content Lead reviews the PR. On approval, it merges and Vercel deploys.

Automation Engineer ships a new skill. Engineer clones the cc repo locally, writes ~/.claude/commands/new-skill.md, tests via full CLI, commits and pushes to main. The next time anyone's runtime reloads, the new skill is available to whichever channel has been granted it.

Account Manager pulls a client report. AM types /hottest-prospect gkp in #client-ops. The Discord bot checks the channel's permission list — /hottest-prospect is on the allow list, and the gkp scope matches what the channel is allowed to see. The runtime hits the GHL API, pulls contact data, returns the result to the channel as a message. The AM never touches a repo, never sees credentials, never sees any client the channel is not scoped to.

What this protects against

A Discord-only user cannot accidentally push to main, leak a token, or run a skill their channel does not expose. A scoped CLI user cannot bypass the PR process. The Automation Engineer cannot see client data unless their own channel grants it — the local CLI is for building tools, not running client queries. The Owner is the only role that sees everything, and that is on purpose.