Adding an `S-N-A` / `S-N-H` Serial Prefix to Epic Sub-Issues to Split Work Between AI Agents and Humans
When we break an Epic issue into sub-issues before starting implementation, we increasingly see sub-issues owned by AI coding agents like Claude Code or OpenAI Codex sitting next to sub-issues owned by human engineers. “AI coding agent” here means an agent that reads the issue body and the surrounding code, cuts a branch, and files a PR by itself.
We used to draw the split too coarsely: a single sub-issue’s checklist would mix tasks an AI agent could handle with tasks only a human could do (rotating production-equivalent credentials, coordinating with an external integration partner, making a UX judgment call). The agent would tick the boxes it could handle and file a PR, and someone was supposed to come back later to pick up the remaining checkboxes. In practice that pickup got deferred, and sub-issues piled up in the “not closable yet” state.
We ended up with a simple convention to fix that: treat each serial number S-N as one work unit, and split it into separate sub-issues by owner, with -A (Agent) or -H (Human) appended to the serial. When one work unit needs both an agent and a human, we file S-N-A and S-N-H side by side and let each close independently. When one side is enough, we file only that side. The result is that every sub-issue is owned by exactly one side, so we no longer see the old “the agent finished its part but the sub-issue can’t close yet” backlog. This post covers the reasoning and the rules we settled on.
Why the Marker Lives in the Title
There are other places we could have parked the ownership marker: introduce a new label, split assignees between a dedicated bot account for the agents and human accounts, or add a custom field on the GitHub Project. We deliberately didn’t adopt labels or a dedicated assignee for this; the only marker is the -A / -H tail on the serial-number prefix in the sub-issue title.
The serial-number prefix follows the title everywhere. The sub-issue list, the GitHub Projects board, notification subject lines, posts from the Slack GitHub integration, and PR titles (which we usually derive from the sub-issue title, as covered below) all show S-N-A / S-N-H without any additional configuration.
That simplicity keeps the situational-awareness cost the same both for someone crossing many repos and many issues every day, and for an engineer heads-down on one Epic. In daily standups and team meetings, lining up an Epic’s sub-issues and seeing the mix of -A and -H at a glance is enough to say things like “this Epic is stuck on the human side right now.”
The Actual Naming Rules
There are only three rules.
First, treat S-N as one work unit’s serial. File the agent’s share as sub-issue S-N-A and the human’s share as S-N-H. When a work unit needs both sides, file both side by side and each closes independently. When one side is enough, file only that side. The parent Epic issue does not carry this tail. An Epic isn’t a unit of ownership; it’s a container for the sub-issues.
Second, -A means “a sub-issue the AI agent is expected to complete on its own,” and -H means “a sub-issue a human is expected to complete on their own.” Even when S-N-A and S-N-H sit side by side under the same serial, the two sub-issues are scoped so that each one closes on its own owner, without a mixed close condition.
Third, if ownership changes mid-flight, either rewrite the -A / -H tail on the serial prefix, or close the current sub-issue and file its counterpart next to it. If S-3-A couldn’t land a PR after two attempts, we either rename it to S-3-H and a human picks it up, or we close S-3-A as-is and file S-3-H next to it. The serial number S-3 stays shared, so the Epic view keeps the two sides of the same work unit lined up.
Titles end up looking like this. Here, S-2 is one work unit split into -A and -H:
[Epic] Refactor the checkout screen
├─ S-1-A [feat] Auto-generate Stripe Webhook types with openapi-typescript
├─ S-2-A [feat] Add a retry dialog when payment fails
├─ S-2-H [chore] Final copy and accessibility pass on the retry dialog
├─ S-3-H [refactor] Split responsibilities out of the legacy PaymentGateway class
└─ S-4-H [chore] Rotate the staging Stripe test keysHow We Decide Between -A and -H
We use four heuristics to decide the suffix. None is absolute; we revisit them per Epic.
The first is locality of change. If a change fits within one to three files and existing tests pin down the current behavior, we lean toward -A. Changes that redistribute responsibilities across multiple modules, or where deciding the scope itself requires judgment, go to -H.
The second is whether the sub-issue touches external systems or secrets. Anything that involves production-equivalent credentials, billing accounts, or irreversible API calls goes to -H. It’s less about keeping the agent away entirely and more about pinning the human-approval point to a specific sub-issue.
The third is requirement ambiguity. If the sub-issue itself requires judgment about “how far to polish the UX,” we mark it -H. Agents implement the requirements as written, but they’re weaker at pushing back on whether the requirements themselves are right, so we keep judgment on the human side.
The fourth is asymmetric review cost. For sub-issues that are quick to write but slow to review (architectural choices, tricky data-model decisions), having a human write them under -H finishes the cycle faster than having an agent draft under -A and burning the saved time in review. Conversely, sub-issues that are tedious to write but light to review (generating type definitions, adding CRUD endpoints) are where -A pays off most.
Carrying the Prefix Through to PR Titles
Since we typically reuse the sub-issue title as the PR title verbatim, the S-N-A / S-N-H prefix also travels to PR titles. Agent-authored PRs carry S-N-A; human-authored PRs carry S-N-H.
That means reviewers know up front whether they’re looking at an agent-authored PR. For Claude Code or Codex PRs, we prioritize checking for hallucinated API calls, assertions that repeat the same wrong assumption as the implementation, and error handling that’s either too paranoid or too loose. We use the PR title prefix as a marker for applying a different review checklist than for human-authored PRs.
If You Want Searchability, Pairing With a Label Is an Option
This convention is used across several teams in parallel but isn’t formally documented as an org-wide guideline; it’s socialized inside each Epic as a local rule. For me, at-a-glance readability has been enough on its own, and I haven’t felt a shortfall on searchability or automation. That said, teams that want aggregation or GitHub Actions-style automation hooks could reasonably layer complementary agent / human labels on top of -A / -H. Labels are directly filterable with queries like label:agent is:open and play well with Projects automation rules. I’m skipping labels only because visual scanning of the title covers what I need; it’s a deliberate simplification, not a stance against labels.
That’s all from tacking an -A / -H tail onto the sub-issue serial prefix so the split between AI agents and humans reads at a glance on GitHub, from the Gemba.