Context
Multi-agent swarm operation requires GitHub-authenticated tooling (issue creation, PR operations, repo metadata reads). Currently a single GH_TOKEN env var is loaded from .env and used by any agent's tooling. The token is bound to one GitHub user identity; any agent that loads it appears as that GitHub user in commit/PR/issue authorship metadata.
This ticket is preventive operational substrate / MX hardening — it makes per-agent identity attribution structurally enforceable for GitHub-authenticated actions.
The Problem
A single shared GH_TOKEN produces three downstream concerns:
- False author attribution — any agent's GH-authenticated action shows the same GitHub user, even if a different agent identity authored the underlying work.
- Cross-agent credential scope — any agent that can read
.env has full GitHub-write capability tied to that user.
- Audit difficulty — post-hoc forensics can't distinguish which agent identity actually performed an action; only the shared GitHub user identity is recorded.
The Architectural Reality
.env is loaded at process start by tooling that reads it directly (or via a config helper).
- The github-workflow MCP server reads credentials at startup; no per-call credential selection.
- The agent's identity (e.g.,
@neo-opus-4-7) is bound at MCP-session level and surfaced via RequestContextService.getAgentIdentityNodeId().
- Each named agent identity could have its own GitHub user account + PAT, with the env var following a naming convention like
GH_TOKEN_<NORMALIZED_AGENT_ID>.
The Fix
- Naming convention:
GH_TOKEN_NEO_OPUS_4_7, GH_TOKEN_NEO_GEMINI_3_1_PRO, GH_TOKEN_NEO_GPT (uppercase, underscore-separated, derived from agent identity by stripping @neo- prefix and replacing dashes with underscores).
- Token lookup helper in github-workflow MCP server: at every authenticated call, derive the env var name from
RequestContextService.getAgentIdentityNodeId(); use that token; fall back to legacy GH_TOKEN if per-agent variant is absent (with WARN log). Hard-cut the legacy fallback in a follow-up after migration window.
- Per-agent PAT setup runbook in
learn/agentos/: documents how operator generates a PAT per agent identity + sets the corresponding env var.
- Audit log: every github-workflow MCP call logs
{ agentIdentity, githubUser } pair so post-hoc forensics can verify expected attribution.
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback / Edge Case |
Docs |
Evidence |
GH_TOKEN_<NORMALIZED_AGENT_ID> env var |
Per-agent .env or process env |
Used by github-workflow MCP for that agent's authenticated calls |
Falls through to legacy GH_TOKEN with WARN (deprecation window) |
Per-agent PAT setup runbook (new doc) |
Unit test: bound-identity-uses-correct-token |
RequestContextService.getAgentIdentityNodeId() → token resolution |
github-workflow MCP server helper |
Maps agent ID to env-var name + reads token |
Returns null if neither per-agent nor legacy token available; tools refuse with structured error |
Same |
Unit test: identity-without-token-refuses-cleanly |
Acceptance Criteria
Out of Scope
- Multi-tenancy / external-user PAT management — internal swarm only
- Token rotation primitive — orthogonal; can land as follow-up
- OAuth instead of PAT — out of scope; current substrate uses PAT
Avoided Traps / Gold Standards Rejected
- Single shared service-account PAT with custom commit author signing — doesn't fix attribution at the GH-API level (GH author = the PAT's user); only changes commit author email which is a different surface.
- Hard-cut without deprecation window — risks immediate breakage if any tool still reads
GH_TOKEN directly. Soft-cut with WARN allows migration; follow-up ticket hard-cuts later.
Related
- #10845 (block destructive AI substrate ops on production paths) — pairs as preventive isolation primitive
- Substrate-mining note: a
.env GH_TOKEN accidentally synchronized across two clones in this session caused PR author attribution to mismatch the underlying-work author; per-agent variable naming would have made the cross-clone copy structurally impossible (different variable names → no overlap on accidental copy).
Origin Session ID: 8b31fd62-6a53-40b5-aae2-c5288f8ced09
Retrieval Hint: "per-agent GH_TOKEN credential namespacing identity-scoped GitHub PAT attribution"
Context
Multi-agent swarm operation requires GitHub-authenticated tooling (issue creation, PR operations, repo metadata reads). Currently a single
GH_TOKENenv var is loaded from.envand used by any agent's tooling. The token is bound to one GitHub user identity; any agent that loads it appears as that GitHub user in commit/PR/issue authorship metadata.This ticket is preventive operational substrate / MX hardening — it makes per-agent identity attribution structurally enforceable for GitHub-authenticated actions.
The Problem
A single shared
GH_TOKENproduces three downstream concerns:.envhas full GitHub-write capability tied to that user.The Architectural Reality
.envis loaded at process start by tooling that reads it directly (or via a config helper).@neo-opus-4-7) is bound at MCP-session level and surfaced viaRequestContextService.getAgentIdentityNodeId().GH_TOKEN_<NORMALIZED_AGENT_ID>.The Fix
GH_TOKEN_NEO_OPUS_4_7,GH_TOKEN_NEO_GEMINI_3_1_PRO,GH_TOKEN_NEO_GPT(uppercase, underscore-separated, derived from agent identity by stripping@neo-prefix and replacing dashes with underscores).RequestContextService.getAgentIdentityNodeId(); use that token; fall back to legacyGH_TOKENif per-agent variant is absent (with WARN log). Hard-cut the legacy fallback in a follow-up after migration window.learn/agentos/: documents how operator generates a PAT per agent identity + sets the corresponding env var.{ agentIdentity, githubUser }pair so post-hoc forensics can verify expected attribution.Contract Ledger Matrix
GH_TOKEN_<NORMALIZED_AGENT_ID>env varGH_TOKENwith WARN (deprecation window)RequestContextService.getAgentIdentityNodeId()→ token resolutionAcceptance Criteria
GH_TOKENwith WARNprocess.env.GH_TOKENreads){ agentIdentity, githubUser }per authenticated calllearn/agentos/per-agent-credentials.mddocumenting setup + naming convention@neo-opus-4-7,@neo-gemini-3-1-pro,@neo-gpt) has its own PAT + env var set in operator's environment (operator-side action; doc only)Out of Scope
Avoided Traps / Gold Standards Rejected
GH_TOKENdirectly. Soft-cut with WARN allows migration; follow-up ticket hard-cuts later.Related
.envGH_TOKENaccidentally synchronized across two clones in this session caused PR author attribution to mismatch the underlying-work author; per-agent variable naming would have made the cross-clone copy structurally impossible (different variable names → no overlap on accidental copy).Origin Session ID: 8b31fd62-6a53-40b5-aae2-c5288f8ced09 Retrieval Hint: "per-agent GH_TOKEN credential namespacing identity-scoped GitHub PAT attribution"