From Writing Kotlin to Directing Agents: The Mobile Engineer's New Role
How coding agents shift an Android engineer's work toward specifications, context, architecture constraints and verification, and which fundamentals matter more than ever.
This article is published in English.
Coding agents no longer stop at finishing your line. They explore a repository, plan a change, edit several files, run the build, read the error and try again. For a mobile engineer that raises an awkward question: if the agent writes most of the Kotlin, is the job still Android development, or has it quietly turned into prompt writing inside an IDE? This article argues that neither label fits, and lays out what the role becomes instead: writing precise specifications, engineering the context an agent works in, encoding architecture as constraints, and verifying results you did not type yourself.
The examples are Android-specific, but the reasoning carries over directly to React Native, web and backend teams using the same class of tools.
How far coding assistants have come
The classic Android workflow is familiar: open Android Studio, create a class, write Kotlin, wrestle with Gradle, chase a crash through Logcat, test on a device and open a pull request.
AI assistance crept into that workflow in stages. First it finished single lines, then whole functions, then entire classes. Current tools act as agents. At the time of writing, several products describe this capability explicitly:
- Gemini Agent Mode in Android Studio accepts a high-level development goal, drafts a plan, invokes tools, edits multiple files, builds the project and iterates when a step fails.
- Cursor's Agent explores a codebase, changes several files, runs terminal commands and fixes errors while working through a task rather than proposing the next line.
- OpenAI Codex runs from the terminal as a coding agent that reads, modifies and executes code.
Product capabilities in this space change quickly, so check the current documentation of whichever tool your team uses. The direction, however, is clear.
The work moves up the stack
A useful mental model is a ladder of engineering activities, from the most mechanical at the bottom to the most judgment-heavy at the top:
Write code
↓
Understand code
↓
Design architecture
↓
Define requirements
↓
Make engineering decisions
↓
Validate behavior
↓
Own the product
Agents are getting very good at the lower rungs. That does not make typing and reading code worthless, but it changes what those skills are worth. A standard repository implementation that takes half an hour by hand can be generated in seconds. Ten near-identical Compose screens are tedious to write manually; an agent can touch the relevant files and produce the repetitive parts. A simple compilation error can eat several minutes of your time, while an agent reads the message, finds the offending code, patches it, rebuilds and moves on.
The net effect is that an engineer spends less time producing code and more time choosing which code should exist in the first place.
A good prompt is really a specification
Take a typical product request: add a download queue to the app. An experienced Android engineer mentally expands that sentence into a layered design:
Database
↓
Repository
↓
Use Cases
↓
ViewModel
↓
UI State
↓
UI
↓
Background execution
↓
Notifications
An agent can now implement much of that stack, but the quality of what comes back depends heavily on what you asked for. Compare a three-word instruction ("add download queue") with something like this:
Build a queue that can run several downloads and persists across launches, backed by Room with WorkManager doing the work. Track progress in memory rather than saving each update to the database. When the process is killed, bring pending and active downloads back. The ViewModel should publish a read-only StateFlow. No Android framework types in the domain layer. Cover queue state changes and recovery from failures with unit tests. Do not change Room entities that have nothing to do with downloads.
Calling the second version a "better prompt" undersells it. It is an engineering specification: it names the persistence technology, the background execution mechanism, a performance decision (not writing every progress update to disk), a resilience requirement (survive process death), an API contract (immutable StateFlow), a layering rule, a test scope and an explicit blast radius. Every one of those clauses reflects Android knowledge the agent cannot infer from "add download queue".
The takeaway is that the engineer does not disappear. The engineer becomes the person who can translate a vague request from product into an exact description of a technical system.
Prompting versus engineering
The two roles ask different questions. Someone focused on prompting asks how to get the model to produce a given output. An engineer wants to know what to build, for what reason, under which constraints, and how anyone will know it works.
Suppose an agent hands you this ViewModel:
class DownloadViewModel(
private val repository: DownloadRepository
) : ViewModel() {
val downloads = repository.downloads
}
It compiles and reads cleanly. A seasoned Android developer still has a list of questions before accepting it:
- Is
downloadsa coldFlowor aStateFlow, and what does each collector trigger? - Where is the single source of truth for download state?
- What survives process death?
- Does every progress update trigger a Room write?
- What happens when two downloads complete at the same moment?
- How is cancellation modeled?
- Can WorkManager restart this work, and does the state reflect that?
- What happens when the network drops?
- How does it behave if the user force-stops the application?
- Is the repository safe with respect to lifecycles?
- Are one-off UI events kept separate from state?
- How does this behave on low-end devices?
Generating the class is easy. Interrogating the system around it is the hard part, and it is far harder to automate.
The agentic development loop
The traditional loop keeps the developer on the critical path of every step:
Requirement
↓
Developer writes code
↓
Build
↓
Error
↓
Developer investigates
↓
Fix
↓
Test
↓
PR
With an agent in the middle, the loop shifts. The developer sets the goal at the start and owns review and validation at the end, while the agent handles the exploration, editing and build-fix cycles in between:
Developer defines goal
↓
AI Agent explores codebase
↓
AI creates plan
↓
AI modifies files
↓
AI runs build/tests
↓
AI observes result
↓
AI fixes problems
↓
Developer reviews
↓
Developer validates behavior
↓
Ship
Vendor documentation describes the same pattern. Android Studio's Agent Mode is presented as planning, calling tools, changing files and iterating on results. Cursor describes its agent as a model that reasons, tools that let it search and edit files or run terminal commands, and a loop in which the agent observes outcomes and chooses the next step. That is no longer autocomplete; it is closer to delegating a piece of engineering work.
The IDE as an orchestration layer
That shift changes what an IDE is for. It used to be a workbench for a single developer. At the time of writing, Android Studio's AI tooling exposes features such as:
- Agent Mode
- several parallel agent conversations
- MCP server connections
- project-level
AGENTS.mdinstructions - access to Android-specific knowledge
- web search
- specialized skills
- permission management
- validation on the emulator
Google positions Agent Mode as able to handle multi-stage development tasks and offers MCP servers and AGENTS.md as ways to extend and steer it. The IDE stops being only the place where you write Kotlin and becomes the place where you run and supervise an AI-assisted engineering environment.
Fundamentals matter more, not less
It would be natural to assume that if agents write the code, engineers can know less. The opposite is true: agents make it cheap to produce wrong implementations quickly, so you need stronger fundamentals to catch them.
Kotlin
You still need a solid grip on the language features that most often hide subtle bugs:
Flow
StateFlow
SharedFlow
coroutines
structured concurrency
inline functions
sealed classes
value classes
delegation
generics
null safety
The point is not to type every line yourself. It is to notice when generated Kotlin is subtly wrong, for example a hot flow where a cold one was needed, or a coroutine launched outside structured concurrency.
The Android platform
Platform behavior is where generated code most often looks right and fails in production:
Lifecycle
Process death
Configuration changes
Services
WorkManager
Room
Navigation
Permissions
Storage
Background execution
Notifications
Compose
Views
Performance
An agent can produce a Worker class in seconds. That says nothing about whether the worker respects your app's lifecycle, retry and constraint requirements.
Architecture as agent constraints
Architecture knowledge gains a new purpose. Patterns like MVI and MVVM, Clean Architecture, module boundaries, repositories, DI, state handling and domain separation are not just ways to organize code; they become the constraints you hand to an agent. Instead of "build a feature", you can instruct:
Build this feature following our existing MVI architecture. Mirror the patterns in Feature A and Feature B. Introduce no new dependencies. Business rules belong in the domain layer.
Referencing existing features is especially effective, because it points the agent at concrete, reviewed examples in the codebase instead of relying on its generic idea of "MVI". Architecture becomes part of the language you use to direct agents.
Repository-level instructions with AGENTS.md
Many teams find themselves repeating the same reminders in every session: the project uses Kotlin and Hilt, business logic stays out of Composables, state is exposed with StateFlow, naming conventions apply, tests are required, generated files are off limits.
Those expectations can live in the repository itself. At the time of writing, Android Studio's Gemini tooling reads AGENTS.md files in which such preferences are recorded, so the agent sees them as project context. Other agents read similar files; the same idea is covered in depth in a practical playbook for writing an effective CLAUDE.md file.
It is a small change with large consequences. A repository has traditionally held:
source code
configuration
tests
documentation
Now it can also hold:
AI engineering instructions
The codebase starts describing both the software itself and how an agent should work on it. Treat those instructions like code: review changes to them, keep them short and specific, and delete rules that no longer apply.
MCP connects the agent to the rest of the toolchain
The Model Context Protocol lets AI systems connect to external tools and services, which means the agent is no longer confined to a chat panel. Through MCP servers it can potentially reach:
GitHub
Databases
Design tools
Documentation
Issue trackers
CI systems
Cloud services
Internal APIs
Android Studio's AI tooling currently supports connecting MCP servers, including remote ones. Consider a single request asking the agent to build a new Profile screen based on a Figma file, reuse the existing design tokens, connect the screen to the profile endpoint, handle loading and failure states, add tests and get a pull request ready. Fulfilling it touches many systems at once:
Developer
↓
AI Agent
├── Figma
├── Codebase
├── Documentation
├── API
├── Tests
├── Git
└── CI
Once a tool coordinates design files, code, documentation, APIs, tests, Git and CI, "code generator" is the wrong description. It is an engineering agent, and its reach is also why permissions and review matter: every connected system is something the agent can read from or change.
The trap: dependent but not capable
This new setup has a characteristic failure mode. A developer can become dependent on AI without becoming capable with it. It is entirely possible to generate code that uses all of these:
Flow
StateFlow
SharedFlow
CoroutineScope
SupervisorJob
Channel
without understanding what any of them does. Everything builds, the work feels fast, and months later production hits a race condition tied to lifecycle cancellation that nobody on the team can explain.
AI sped up the typing; it did not make the developer better. That is why reviewing what the AI produced is arguably becoming more valuable than the ability to generate it. A practical rule for teams: nobody merges generated code they could not explain line by line in review.
Context is the real lever
Coding agents depend heavily on the context they receive. Cursor's documentation, for instance, describes an agent system in terms of context, tools, instructions and models. That suggests a rough multiplicative relationship:
Agent Quality
=
Model
× Context
× Tools
× Instructions
× Verification
The multiplication is the important part. A strong model working with poor context produces poor software, because a near-zero factor drags the whole product down. A decent model working in a well-structured repository with clear architecture, solid tests, helpful docs and exact instructions can perform far better. The skill to build is context engineering, of which prompt wording is only one part.
Why "prompt engineering" is too narrow
The difference is easy to see side by side. A bare prompt looks like this:
"Create a login screen."
A context-engineered request looks like this:
Here is our architecture.
Here are our design rules.
Here is the API contract.
Here are existing authentication patterns.
Here are the tests.
Here are the project constraints.
Here is the expected behavior.
Now implement the feature and verify it.
The second version hands the agent the architecture, design rules, API contract, existing authentication patterns, tests, constraints and expected behavior, and then asks it to both implement and verify. That is much closer to how you would brief a new colleague, and the prompt is only one ingredient of it. When an agent misbehaves, it pays to ask which of these layers was missing; our guide to debugging AI agents by layer walks through that diagnosis.
The engineer designs the whole loop
The largest change may be where responsibility sits. The old relationship was direct:
Developer → Code
The emerging one runs through several stages, and the engineer owns all of them:
Developer
↓
Specification
↓
Agent
↓
Tools
↓
Code
↓
Tests
↓
Verification
Owning the loop means knowing which instruction a situation calls for:
- "Do it", when the task is well specified and low risk.
- "Plan it first", when the change spans several modules.
- "Leave the code alone for now and study the architecture first", when you need understanding before edits.
- "Reproduce the bug", before accepting any fix.
- "Stop; your assumption is wrong", when the agent is confidently heading in the wrong direction.
That last intervention may turn out to be one of the most valuable skills of all, and it depends entirely on knowing the platform well enough to spot the flawed assumption.
Neither Android developer nor prompt engineer
Neither label captures the role on its own. An Android developer who only writes Kotlin by hand will fall behind on efficiency. Someone who can ask an AI for Kotlin but lacks a grasp of Android architecture will sooner or later get stuck. The durable combination looks like this:
Android Engineering
+
AI Agent Skills
+
System Design
+
Context Engineering
+
Verification
=
AI-Augmented Android Engineer
In practice that means keeping your Android knowledge, deepening your architectural understanding, learning to communicate requirements precisely to machines, and getting comfortable with agents, their tools, MCP, repository instructions and automated checks. Above all, it means recognizing when the AI is wrong. An agent can confidently produce two thousand lines; it takes an engineer to judge whether those lines should exist.
The more realistic future is not AI replacing developers, but developers who work well with agents replacing workflows that do not. One engineer with strong fundamentals and a well-configured agentic setup can potentially deliver what used to take far more manual effort. Engineering does not go away; it moves to a higher level, where reasoning, defining constraints and validating results count for more than keystrokes, and where architecture acts as the map that keeps agents from wandering off.
Key takeaways
- Treat instructions to an agent as specifications: name the technologies, performance decisions, resilience requirements, contracts, test scope and what must not change.
- Review generated code by interrogating the system around it (state ownership, lifecycle, process death, concurrency, cancellation), not by checking that it compiles.
- Invest in fundamentals; they are what let you catch fast, plausible, wrong implementations.
- Encode team conventions in repository-level instruction files such as
AGENTS.md, and maintain them like code. - Improve results by improving context (architecture, tests, docs, examples), since a weak factor limits the whole outcome.
- Stay the owner of the loop: decide when the agent should act, plan, investigate, reproduce or stop.