Raxx · internal docs

internal · gated

ADR 0096 — Per-PR Context Swap: Agent Identity Routing

Date: 2026-05-16 UTC
Status: Accepted
Deciders: Kristerpher (operator)
Tracking: #2070
Design doc: agent-identity-per-pr-context-swap-2026-05-16.md


Context

When the main orchestrator thread dispatches agents, every agent-dispatched PR was authoring as the operator's GitHub identity (MooseQuest) because agents were not consistently using the bot token wrapper. This causes two problems:

  1. GitHub's self-approval block prevents the operator from approving their own PRs through the normal review flow — admin-merge bypasses the check.
  2. Agent-dispatched work is indistinguishable from operator-authored work in the audit trail, degrading the traceability model established in workflow-uuid-tracing.md.

Three options were presented in #2070:


Decision

Option C — Per-PR context swap is adopted.

The bot identity used to open a PR is determined by the agent class that produced the PR, per the existing mapping in scripts/agents/agent_bot_map.yaml:

Agent class Bot
feature-developer, ux-polisher, ux-designer raxx-dev-bot
sre-agent, security-agent, card-groomer raxx-ops-bot
product-manager, software-architect, marketing-strategist, business-legal-researcher, data-scientist raxx-pm-bot

No new GitHub Apps are provisioned. The orchestrator (main thread) does not open PRs directly — it dispatches agents. The orchestrator's own GitHub actions (issue comments) remain operator-attributed for now.

Token injection mechanism: the orchestrator reads agent_bot_map.yaml at dispatch time, mints a scoped GH_TOKEN via mint_github_token.py, and injects it into the agent's environment before spawn. Agents with ≥3 gh calls use the session pattern; single-call agents use with_bot_token.sh.


Consequences

Positive: - Most precise per-agent attribution in the GitHub audit trail - Operator can approve all agent-dispatched PRs through the normal review flow — the self-approval block is structurally eliminated - No new GitHub Apps to manage; existing 3-App model is sufficient - agent_bot_map.yaml is already canonical and correct; changes are additive only - Aligns with the workflow UUID tracing model — bot identity is a stable classification signal

Negative / trade-offs: - Highest implementation complexity of the three options: orchestrator must read the map, mint a token, and inject it at spawn time — rather than using one shared token for everything - If agent_bot_map.yaml is not updated when a new agent class is added, the new agent defaults to the operator PAT (the fallback path in with_bot_token.sh), which re-introduces the self-approval problem. Mitigation: CI lint rule confirms every agent file in .claude/agents/ has an entry in agent_bot_map.yaml (tracked in SC-IDENT-2) - Agent prompt updates required for 6 agent files to standardize the PR body convention (tracked in SC-IDENT-3)

Neutral: - Token validity is 1 hour. For long-running agent sessions, the orchestrator may need to re-mint. This is existing behavior for the session pattern and is not new risk.


Alternatives Considered

Option A — Dedicated raxx-conductor-bot

Pros: cleanest conceptual separation (orchestrator has its own identity distinct from all agent classes). Cons: adds a 4th App to provision and maintain; the orchestrator itself does not open PRs (it dispatches agents that do), so the 4th App would be used only for issue comments and orchestrator-level PR creation, which is minimal. Rejected as over-engineered for the actual use case.

Option B — Share raxx-dev-bot for all orchestrator PR creation

Pros: no new App, minimal implementation complexity. Cons: raxx-dev-bot PRs could originate from either the feature-developer agent or the orchestrator directly, creating attribution ambiguity. This degrades the audit trail — the operator still cannot distinguish agent-typed work by PR author alone. Rejected because audit trail quality is a stated priority (per #2070 discussion).