# Scoped Permission-aware agents. Same model, same prompt, different gateway scope. Built at the Agent Harness Workshop (TrueFoundry + HackerSquad). ## The problem Enterprises want AI agents on their internal tools. Most never ship them. The reason is permissions. Connect an agent to GitHub, Notion, or Slack and it inherits everything that connector can reach, all at once. The common workaround is to write the access rule into the system prompt: "do not touch production," "only read from these pages." That is theater. Anything expressible in a prompt can be argued around. The model still holds the tool. It is one clever message away from using it. ## The approach Move the boundary out of the prompt and into the gateway. Two agents run on the same model with byte-identical system prompts. The only variable is which tools the TrueFoundry MCP Gateway exposes to each one. | | Maintainer | External Contributor | |---|---|---| | Model | claude-opus-4-6 | claude-opus-4-6 | | System prompt | identical | identical | | MCP server | GitHub | GitHub | | Tools enabled | all | read-only subset | Ask both the same thing: > Merge the open PR and delete the stale branch. The Maintainer does it. The External Contributor cannot, and says precisely which capability it lacks rather than hallucinating a result or inventing a refusal. The restricted agent is not declining. It never received the tool. ## Architecture ``` ┌──────────────────────┐ │ TrueFoundry Gateway │ └──────────┬───────────┘ │ ┌───────────────────┴───────────────────┐ │ │ ┌─────▼──────┐ ┌─────▼──────┐ │ Agent A │ │ Agent B │ │ Maintainer │ │ Contributor│ └─────┬──────┘ └─────┬──────┘ │ │ ┌─────▼───────────┐ ┌──────▼──────────┐ │ GitHub MCP │ │ GitHub MCP │ │ all tools │ │ read-only tools │ └─────────────────┘ └─────────────────┘ ``` Both agents route through a Virtual Model with a configured fallback, so a provider rate limit degrades the response rather than killing the session. Every tool call is recorded in Request Traces. That view is the audit trail: it shows which calls fired and which were never issued at all. ## System prompt Identical for both agents. ``` You are a repository assistant. Use only your available tools. Name the tool you used for each action. If you cannot do something, say exactly which capability you lack. Never claim you did something you did not do. ``` The final line matters. Without it, a restricted agent tends to narrate a plausible success instead of reporting the gap. ## Reproducing it 1. Connect a model in Model Gateway. Add a second provider and wire a Virtual Model with the first as primary and the second as fallback. 2. Register the GitHub MCP server in MCP Gateway. 3. In Agents > Playground, create Agent A on that MCP server with all tools enabled. 4. Create Agent B on the same MCP server, then open the server chip and disable every write, merge, delete, and secrets tool. 5. Paste the system prompt above into both. 6. Run the demo prompt against each in a fresh session. Conversation history will leak context between runs otherwise. 7. Open Request Traces to compare issued tool calls. ## What did not work The original design used two scoped Notion integration tokens, one granted access to sensitive pages and one not, pointed at Notion's hosted MCP server. It failed. Notion's hosted MCP endpoint requires OAuth and does not accept internal integration tokens. The OAuth flow authenticates as the human operator, so both agents received the full workspace regardless of which token was configured. The tokens were silently ignored. This is worth stating plainly because the failure mode is quiet. Both agents answered every question correctly and nothing errored. The permission boundary simply was not there. Scoping at the gateway avoids the problem entirely. The restriction is enforced before the request reaches the upstream service, so it does not depend on that service supporting per-credential scoping. ## Limitations Scope is currently bound to the agent, not to the person using it. The next step is per-user scoping through role-based access control, so the boundary follows identity rather than configuration. Tool-level restriction is also coarse. It answers "can this agent merge" but not "can this agent merge in this specific repository." Resource-level scoping needs support from the upstream MCP server. ## Stack TrueFoundry (MCP Gateway, Virtual Models, Request Traces, Agent Playground), GitHub MCP, Claude Opus, Groq as fallback.
