Quality assurance · Production

Medium Android team encodes team coding conventions into Cursor agent skills to produce pattern-compliant code

The problem

Medium's small Android team had strong, opinionated coding conventions — where ViewModels get data, how analytics events flow, what a new screen looks like — but that knowledge lived in PR review comments, Slack threads, and the heads of veteran engineers. When AI coding assistants arrived, they produced generic Kotlin code that missed the team's specific conventions, component library, and testing style.

First attempt

Without custom skill files, the AI consistently generated composables tightly coupled to the ViewModel — missing patterns like listener splitting and the @VisibleForTesting overload — making previews and UI tests painful, and causing the same pattern-break comments to recur in PR reviews.

Workflow diagram · grounded in source
1
Developer prompts AI agent
trigger
“A single prompt like "create a new screen for user notifications" produces 6-8 files that follow our exact patterns.”
2
AGENTS.md loaded as baseline context
integration
“Before skills, we wrote an AGENTS.md file at the root of our Android project. Think of it as a README for the AI, a document that's automatically loaded into context whenever any Agents works on our code.”
3
Skill file loaded as runbook
integration
“An Agent skill is a Markdown file (stored in .agents/skills/) that teaches the AI a specific workflow. It's not a template, it's closer to a runbook: "here are the files involved, here's the order of operations, here are the patterns to …”
4
AI generates convention-compliant code
ai_action
“When it generates a ViewModel, it already knows to use @HiltViewModel, StateFlow, and @Immutable sealed interfaces. When it creates a test, it reaches for MockK and Turbine instead of Mockito and LiveData.”
5
Engineer review pass
human_review
“Setting up a new screen with ViewModel, listeners, composable, previews, test tags, and tests used to take most of a morning. Now it takes a prompt and a review pass.”
6
Skill updated from pattern breaks
feedback_loop
“We've iterated on most skills 3–5 times. The first version of create-compose-screen didn't mention the listener splitting pattern. The add-deeplink skill originally lacked the SUSI destination rule. Each time we caught a pattern break, w…”
Reported outcome

Setting up a new screen now takes a prompt and a review pass instead of most of a morning, and every new screen looks structurally identical regardless of who or what wrote it, eliminating convention drift across the small team.

Reported metrics
Boilerplate setup time replaced by scaffolding skills30-60 minutes
New screen setup time before skillsmost of a morning
Files generated per screen prompt6-8 files
Skills built13
Show all 6 reported metrics
boilerplate setup time replaced by scaffolding skills30-60 minutes
new screen setup time before skillsmost of a morning
files generated per screen prompt6-8 files
skills built13
material2-to-material3 component mappings in migration skill60+
skill iteration rounds per skill3–5 times
Reported stack
CursorMockKTurbineHiltApollo GraphQLDetektRobolectricWire
Source
https://medium.engineering/making-ai-write-android-code-our-way-a-practical-guide-to-agent-skills-4e7b085d8e50
Read source ↗

Frequently asked questions

What did this team achieve with this AI workflow?

Setting up a new screen now takes a prompt and a review pass instead of most of a morning, and every new screen looks structurally identical regardless of who or what wrote it, eliminating convention drift across the…

What tools did this team use?

Cursor, MockK, Turbine, Hilt, Apollo GraphQL, Detekt, Robolectric, Wire.

What results were reported?

Boilerplate setup time replaced by scaffolding skills: 30-60 minutes; New screen setup time before skills: most of a morning; Files generated per screen prompt: 6-8 files; Skills built: 13 (source-reported, not independently verified).

What failed first in this deployment?

Without custom skill files, the AI consistently generated composables tightly coupled to the ViewModel — missing patterns like listener splitting and the @VisibleForTesting overload — making previews and UI tests pain…

How is this quality assurance AI workflow structured?

Developer prompts AI agent → AGENTS.md loaded as baseline context → Skill file loaded as runbook → AI generates convention-compliant code → Engineer review pass → Skill updated from pattern breaks.