Today I wanna talk about something I’ve been noticing that is creating a lot of confusion, especially in this fast-moving AI world.
More and more people are asking themselves: “Should I try to learn a bit of everything now, or double down on what I already know?” I hear this from teammates, from friends switching careers, from engineers who just started using AI tools daily. The question keeps coming back.
And it’s a fair one. AI changed how fast we can build, and that shift made a lot of people rethink their career shape. If a model can write backend code, frontend code, infrastructure code, and SQL, why wouldn’t you just become a generalist and orchestrate all of it?
I thought about this a lot. And the honest answer I keep coming back to is: build breadth on purpose, but pick a deep pillar. That is the heart of the T-shaped professional, an idea popularized by IDEO to describe people who combine deep skill with cross-discipline collaboration.
Because here’s the thing: code is becoming easier to produce, but good systems are still hard to design, hard to keep safe, and hard to keep simple. AI didn’t change that. Actually, it made the problem more obvious, because now you can see the gap between “code that works” and “systems that last” much faster.
Let me break it down with a simple example (and yes, it includes a duck).
The generalist and the duck principle
A generalist knows a little bit about many areas. That broad view is useful because it helps you connect ideas and adapt quickly, especially in fast-changing environments.
But breadth comes with a tradeoff: generalists often don’t go deep in one area.
Here’s my favorite mental model:
A duck can swim, run, and fly.
It can do all three, but it is not the best at any of them.
A shark swims better than a duck. A leopard runs better than a duck. An eagle flies better than a duck.
That’s not an insult to ducks. It’s a reminder: being able to do many things is different from mastering one.
And in software (especially now), this difference matters.
“But Julio… are you saying we should forget everything and focus on only one thing? Isn’t it good to know a little bit of everything?”
Great question. And no, I’m not saying “drop everything else.”
Breadth is still valuable. In fact, organizations often need both generalists and specialists, and the mix matters.
But there’s a hidden trap in pure generalism:
The hidden risk: generalism can feel like mastery
When you know a little bit about many topics, your brain can trick you into thinking:
“I know this.”
Sometimes you do. But sometimes you only know the surface.
Psychology research has shown that people can overestimate their ability, in part because lacking a skill can also mean lacking the ability to judge the skill accurately (the famous “unskilled and unaware” effect).
That is why I believe:
Knowing your limitations is more important than knowing a little bit of everything.
Not because learning broadly is bad, but because pretending you’re deep (when you’re not) creates risk. You can ship fragile systems. You can overpromise to business partners. You can build “clever” solutions that collapse under real production traffic.
This is where the T-shaped model becomes powerful.
The T-shaped professional explained
A T-shaped person has depth in one area (the vertical bar of the “T”) and breadth across many areas (the horizontal bar).
But the horizontal bar is not just “knowing stuff.” It is also the ability to collaborate across disciplines, powered by empathy and real interest in other domains. The idea is that you combine a broad set of general skills with a “spike” of deep expertise that makes you genuinely valuable.
Here’s a simple visualization you can copy into your notes:
Breadth: frontend | product | data | security | ops | UX | domain
-------------------------------------------------------
Depth: one area you go deepNow, here’s the key part for this article:
The “T” changes depending on the era.
The T-shape that made sense before AI is not the same T-shape that will protect your career and improve your impact after AI.
T-shaped software engineering before AI
Before AI-assisted coding became mainstream, a classic example of a T-shaped backend engineer looked like this:
Your deep stem was backend engineering: one primary language and runtime, API design, concurrency models, persistence strategies, performance tuning, and full service ownership from deploy to on-call.
Your horizontal bar was enough frontend to collaborate: you understood browser rendering, the HTTP lifecycle, UI constraints, and the reality of shipping product with designers and PMs who think in pixels, not packets.
Your exploration zone was where you grew next: databases, distributed architecture, mobile, messaging systems, cloud infrastructure, security. Where you went depended on what you wanted to become.
That model worked because the hard part was often writing correct code, learning syntax and frameworks, and moving features from idea to implementation. Now AI changes that balance.
The AI shift: from writing code to shaping systems
Today you can describe what you want in natural language and get a working codebase in minutes.
Tools like Claude Code, Cursor and GitHub Spark, explicitly promote building and deploying apps using natural language, “without writing any code.” This is a huge unlock: you can prototype fast, test ideas early, and reduce the cost of experimentation. “Vibe coding” became a popular term for exactly this: the idea that you can “give in to the vibes” and let an LLM generate a lot of code quickly, making software creation accessible to more people.
But there’s a second reality, and it matters even more:
AI can generate code fast… and still generate the wrong code.
The impact is mixed and well-documented. A randomized controlled trial by METR found that experienced open-source developers took 19% longer when AI tools were allowed. A snapshot of early-2025 AI capabilities suggesting that the overhead of reviewing, correcting, and steering AI output can eat into the speed gains. Meanwhile, security research on GitHub Copilot found a meaningful portion of generated programs contained common weakness patterns: things like SQL injection vectors, improper input validation, and insecure cryptographic defaults that a junior developer might miss but a senior one would catch immediately.
So the role is not “AI writes perfect code.” The role is becoming: humans define the right problem, choose the right design, and verify the result. AI accelerates implementation, but it also amplifies mistakes.
That naturally pulls us toward a new T-shape.
The new T for software engineers in the AI world
Here is the updated model I recommend:
- Specialist (deep stem): System design + architecture
- Solid knowledge (breadth): AI engineering
- Always improving (growth zone): Data engineering
This is not a universal truth. It’s a practical response to what AI changed: code is cheaper to produce (so architecture matters more), context is limited (so clarity matters more), data quality drives outcomes (so pipelines matter more), and security risks increase (so guardrails matter more).
Let’s walk through each pillar.
Why system design and architecture becomes the deep stem
In a world where code can be generated instantly, your biggest leverage is choosing good boundaries, keeping systems understandable, and shaping change so future work stays cheap.
There’s a well-known concept in software engineering: code “rots” over time. It becomes harder and harder to maintain as poor dependencies and unmanaged coupling accumulate. That problem does not disappear with AI. It actually accelerates: AI can generate more code, faster, which means it can also generate more mess, faster. A 2,000-line pull request that took a human two weeks to produce (giving reviewers time to intervene) can now appear in an afternoon.
There’s also an AI-specific reason architecture matters. LLMs operate under a finite context window. Even Claude’s context windows (200K tokens for most models, up to 1M for Opus) sound enormous until you realize that a medium-sized service with tests, configs, and schemas can easily exceed that. And even within the window, attention quality degrades as context grows; the model’s ability to reason about token 180,000 is not the same as its ability to reason about token 500. This is why context engineering (selecting the smallest set of high-signal tokens to get the best outcome) is becoming a first-class engineering discipline.
Clear architecture helps because it makes your system easier for humans to review, easier for AI agents to navigate (an agent that can follow a clean interface/implementation boundary wastes far fewer tokens than one wandering through a tangled dependency graph), and cheaper to reason about overall.
What to learn in system design + architecture
Start with the three qualities that every distributed system must balance:
- scalability (handle growth without rewrites, and when rewrites are needed, make them simple)
- reliability (keep working correctly even when parts of the system fail)
- observability (know what’s happening from logs, metrics, and traces so you debug reality instead of guessing).
These are standard system design concerns, but they become more urgent when AI increases delivery speed, because mistakes reach production faster.
Next, build fluency in design patterns. The Gang of Four catalog is a shared language for reusable solutions in object-oriented design. You don’t need to memorize all twenty-three. Focus on the ones that show up in real codebases: Factory and Builder for object creation, Adapter and Decorator for structural composition, Strategy and Chain of Responsibility for behavioral flexibility. Know what Singleton is, mostly so you can recognize when it becomes hidden global state that makes testing painful.
Then internalize the engineering principles that keep code simple and change-friendly.
- SOLID gives you class-level design constraints (single responsibility, open-closed, Liskov substitution, interface segregation, dependency inversion) and together they push you toward code that can evolve without cascading breakage.
- DRY (“every piece of knowledge must have a single, unambiguous, authoritative representation”) protects you from diverging copies.
- KISS and YAGNI protect you from yourself: simplicity as a design goal, and a refusal to build speculative features “just in case.”
- Domain-Driven Design (DDD) goes further by modeling the business domain so your software structure mirrors the real problem space: bounded contexts, aggregates, ubiquitous language.
Finally, understand the architectural patterns that define system shape.
- A modular monolith is often faster and safer early on (think POCs, MVPs, or any stage where you’re still discovering boundaries).
- Microservices earn their complexity cost only when boundaries are stable and teams genuinely need deployment autonomy.
- Event-driven architecture (EDA) lets systems communicate through events, which is powerful for decoupling but introduces eventual consistency challenges you need to design for.
- CQRS separates the write model from the read model, simplifying scaling in domains where read and write patterns differ dramatically (like a financial ledger with high-volume reads but carefully validated writes).
- Saga pattern coordinates distributed workflows across services, essential when a single business operation spans multiple bounded contexts.
- Self-Contained Systems (SCS) take this further by splitting a system into autonomous web applications that each own their UI, business logic, and data storage, minimizing shared infrastructure and cross-team coupling. SCS is gaining a lot of traction in the AI era, and for good reason: when everything a feature needs lives in one place, an AI agent can reason about the entire context without jumping across dozens of services, tracing network calls, or figuring out which microservice owns which piece of data. Microservices scatter context across the network (API contracts, retries, circuit breakers, eventual consistency), and that scattered context is exactly what makes AI struggle. An SCS gives the agent a complete, self-contained picture: the UI, the logic, the data, all in one boundary. Less navigation, less guesswork, better output.
Those patterns define how systems relate to each other. But how you organize code inside each service matters just as much. Hexagonal architecture is a great example: by defining explicit interfaces for every external dependency (database, message queue, HTTP client, AI model) and keeping the implementations separate, you create clear contracts that are trivial to mock in tests, trivial to swap in production, and critically, trivial for an AI agent to understand. When an agent sees a well-defined interface, it knows exactly what it can call and what it will get back, without needing to trace through implementation details. The tradeoff is real though: hexagonal adds indirection. Every interaction goes through an interface, which means more files, more boilerplate, and a steeper onboarding curve for developers who are used to calling things directly. For small projects or quick prototypes, that overhead can slow you down more than it helps. It pays off when the system grows, when multiple teams touch the same codebase, or when you need to swap implementations without rewriting business logic.
The AI bonus is real and measurable: maintainable architecture reduces AI “guesswork.” When the codebase follows consistent patterns, an agent needs less explanation and produces higher-quality output. When everything is “special” and inconsistent, you pay with more tokens, more retries, and more risk.
Why AI engineering becomes solid knowledge
If system design is your deep stem, AI engineering is your daily leverage. This is the skill that turns AI from a toy into a tool.
The goal is not “better prompts.” The goal is consistent outputs, safe behavior, clear boundaries, reduced hallucinations, and controlled cost. To achieve that, you need to treat AI like any other system component: design it, secure it, monitor it.
What to learn in AI engineering
Prompt and meta-prompt design. When you write a system prompt, you are defining rules, output formats, tool usage constraints, and refusal behavior. This is real engineering work, not “magic words.” A well-structured system prompt is like a well-structured API contract: it reduces ambiguity and makes behavior predictable. And just like code, overly complex prompt logic can become brittle and hard to maintain. Worse, it can make the model overthink: spending more tokens reasoning through conflicting or redundant instructions, and becoming more sensitive to hallucinations because the signal gets buried in noise. The best prompts are clear, minimal, and layered: a base system prompt for identity and constraints, then task-specific context injected at runtime.
RAG (Retrieval-Augmented Generation). RAG combines a model’s trained knowledge (“parametric memory”) with retrieved documents (“non-parametric memory”), grounding generation in real sources rather than letting the model guess. But the implementation details matter more than the concept. A production RAG pipeline typically flows through four stages: embed your documents into vector representations (using models like OpenAI’s text-embedding-3-large or open-source alternatives like bge-large), store those vectors in a purpose-built index (Pinecone, pgvector, Qdrant, or even a simple FAISS index for prototyping), retrieve the top-k most relevant chunks at query time using approximate nearest-neighbor search, and then rerank those candidates with a cross-encoder or reciprocal rank fusion before injecting them into the prompt. Each stage has its own failure modes: bad chunking strategies (splitting mid-sentence, losing context) can poison retrieval quality more than a bad embedding model can.
In practice, your own RAG pipeline becomes a competitive advantage because you ground outputs in your internal docs, architecture decisions, product rules, runbooks, and incident history. That reduces hallucination and makes answers verifiable. And when you combine a well-configured RAG pipeline with fine-tuned models and agentic orchestration on top, you get the closest thing possible to deterministic results from AI. Here's why that matters: without RAG, every time you start a new session you're spending tokens re-fetching the same documents through MCPs or tool calls.
Think about what happens when you open a new Claude Code window: the context from your last interaction is gone. The agent needs to reload MCP servers, re-fetch your codebase, re-read your docs, and rebuild its understanding from scratch. And here's the subtle part: even with the same question and the same documents, you can get different answers. That's not a bug, it's how transformers work. The model generates output one token at a time, where each token is a probability-weighted prediction based on all the tokens that came before it. Small differences in how context is loaded (the order of retrieved chunks, slight variations in token sequences, even floating-point rounding during computation) shift those probabilities just enough to produce a different path through the output. RAG with pre-embedded, pre-ranked, consistently structured context minimizes that variance. The model sees the same high-quality input every time, which pushes its predictions toward the same high-quality output every time. It's not perfect determinism, but it's the closest you'll get without adding hard validation layers on top.
There are also open-source, ready-to-use RAG frameworks (like OpenRAG) that give you a head start with pre-built pipelines and integrations. But “ready-to-use” does not mean “plug and forget.” You still need to configure your chunking strategy, choose the right embedding model, tune retrieval parameters, test with real queries, and monitor quality over time. The framework saves you from building the plumbing from scratch, but the engineering decisions are still yours.
Tooling and protocols, especially MCP. The Model Context Protocol (MCP) is an open standard introduced by Anthropic for connecting AI assistants to the systems where data lives: repos, databases, business tools, content systems. Under the hood, MCP structures its messages using JSON-RPC, but the transport layer can vary: stdio (stdin/stdout for local processes, like when Claude Code talks to a local server on your machine), SSE (Server-Sent Events over HTTP for remote servers), or the newer Streamable HTTP. Think of it like USB for AI tools: before USB, every peripheral had its own cable and protocol; before MCP, every AI-to-tool integration was custom code. MCP standardizes that connection. A server exposes a catalog of tools (functions the model can call) and resources (data the model can read), and a client (the AI host) discovers and invokes them at runtime. The power of MCP is that you define a tool once (say, a run_snowflake_query tool or a search_jira_issues tool) and any MCP-compatible AI assistant can use it without custom integration code. This matters because it turns your internal systems into a composable toolkit that AI can operate within controlled boundaries.
Skills, Agents, and Rules: the composition that changes everything.
This is where AI engineering gets genuinely powerful, and it’s worth understanding the three building blocks precisely because their combination creates something much greater than their sum.
Rules are persistent, declarative constraints that shape AI behavior across every interaction. Think of a CLAUDE.md file, Cursor's .cursor/rules/*.mdc files, or a system prompt that loads automatically. Rules define coding standards ("use pnpm, not npm"), architectural patterns ("follow hexagonal architecture with clear interfaces and separate implementations"), security boundaries ("never commit .env files"), and team conventions ("write commit messages in imperative mood"). They are always active, always enforced. Think of them as the AI equivalent of an .eslintrc or .editorconfig, but for reasoning behavior rather than syntax. Rules are not invoked; they are ambient. They form the constitution that everything else operates within.
Skills are reusable workflows that encapsulate a specific repeatable task. Depending on the tool, a skill can be invoked manually (like a command) or triggered automatically based on the user’s request. For example, a commit skill knows how to analyze staged changes and draft a commit message following your team’s conventions. A scaffolding skill might create an entire service with the right folder structure, dependency injection setup, and boilerplate tests. The implementation varies across tools (Claude Code, Cursor, and others each handle skills differently), but the concept is the same: focused, composable building blocks that encode how your team does things. Conceptually, the difference from rules is that skills are active capabilities (they do things) while rules are passive constraints (they shape how things are done). In practice, some tools blur this line. Cursor, for example, lets you configure rule files with different trigger modes (always-on, auto, agent-requested, or manual), so a “rule” can behave like a skill depending on how you set it up. The concepts are still useful to think about separately, even when the tooling merges them.
Agents are autonomous, goal-directed processes that can plan, reason, use tools, and iterate. An agent doesn’t just execute a single workflow; it decomposes a complex goal into steps, decides which tools or skills to invoke, observes the results, and adapts its plan. An agent might receive “investigate why the integration tests are failing” and autonomously read test logs, grep for error patterns, trace the failure to a specific file, read that file, identify the bug, propose a fix, and run the tests again to verify. Agents are where the orchestration lives: they combine multiple skills, follow rules, manage context across steps, handle retries, and spawn sub-agents for parallel work.
The composition is where the real leverage appears. Rules set the guardrails (“this is a hexagonal architecture codebase, never put business logic in the infrastructure layer”). Skills provide the capabilities (“here’s how to scaffold a new repository port, here’s how to create an integration test”). Agents orchestrate the workflow (“the user wants a new consumer, I’ll invoke the scaffold skill, then the test skill, then verify the build, all while respecting the architectural rules”). Without rules, agents drift. Without skills, agents reinvent the wheel on every task. Without agents, skills sit idle waiting for manual invocation. Together, they create something close to a programmable colleague: one that operates within your architecture’s constraints, uses your team’s proven workflows, and can independently handle multi-step tasks that would take a human an hour of context-switching.
This is not theoretical. Teams that invest in defining clear rules, building reusable skills, and configuring agents to compose them are seeing compounding returns: every new rule makes every agent more reliable, every new skill makes every agent more capable, and every improvement to agent orchestration makes the entire system more autonomous. It is the same leverage pattern as good software architecture itself: small, well-defined components composed through clear interfaces.
Agent orchestration more broadly is how you coordinate one model versus multiple models, one agent versus multiple agents, tool calls, planning, memory, and retries. The core idea is that agents get better results when they combine reasoning with actions: think about the problem, call a tool, observe the result, adjust, and repeat. In practice, you’ll face decisions like: should this task use a single agent with many tools, or a coordinator agent that dispatches to specialized sub-agents? The answer depends on context window pressure (one agent accumulates all context; multiple agents each start fresh) and task coupling (tightly coupled steps benefit from shared context; independent steps benefit from parallel agents).
Model choice and fine-tuning. Large language models (LLMs) are general and flexible; smaller language models (SLMs) can be cheaper and faster for narrow, well-defined tasks. Fine-tuning adapts a pre-trained model to a specific domain by training on curated examples. Techniques like LoRA (Low-Rank Adaptation) let you fine-tune efficiently by training only a small number of additional parameters rather than updating the full model, making it practical even with limited compute. But fine-tuning is not a silver bullet: it can fail if your training data is inconsistent, too small, or poorly labeled. You need evaluation datasets and iteration cycles, just like any other engineering process.
Tokenization and budget control. Tokens are the atomic units models process, roughly 3/4 of a word in English, though this varies by tokenizer and language. Cost and latency are both directly tied to token counts: a prompt that uses 50,000 input tokens and requests 4,000 output tokens has a predictable cost you can calculate before sending. Knowing this changes how you design AI-powered features. You learn to estimate token usage before calling an API, keep prompts short and high-signal (a well-structured 500-token prompt often outperforms a rambling 3,000-token one), cap output length with max_tokens to control cost, and route simple classification or extraction tasks to cheaper, faster models while reserving expensive frontier models (the most advanced, highest-capability models available at any given time, like Claude Opus or GPT-4o) for complex reasoning.
Another important cost lever is prompt caching. Providers like Anthropic (Claude) and OpenAI (ChatGPT) both offer this: when you send a request, the provider caches the internal computation (the key-value pairs from the attention mechanism) for the prefix of your prompt. On the next request with the same prefix, it reuses that cached computation instead of reprocessing everything from scratch. The result is lower latency (the model skips recomputing attention for the cached portion) and lower cost (cached input tokens are heavily discounted, up to 90% cheaper with Anthropic). The tradeoff is that caching only works for exact prefix matches. If even a single token changes in your prefix, the cache misses and you pay full price again. It also has a short TTL (time-to-live), typically around 5 minutes, so it works best for high-frequency, repetitive interactions, not sporadic calls hours apart. This means you need to be intentional about prompt structure: put the stable parts first (system prompt, rules, context documents) and the variable parts last (the user's message). Tools like Cursor benefit from this under the hood when making repeated calls to the same model with consistent system prompts.
And just like you wouldn't run a production service without observability, you shouldn't run AI-powered features without it either. Tools like Langfuse give you tracing, cost tracking, and latency monitoring for every LLM call, so you can see exactly which prompts are burning through your budget, which ones are slow, and where quality is degrading. It's the same idea as Datadog or New Relic, but built specifically for LLM pipelines. Without this kind of observability, you're flying blind on cost and quality.
Guardrails and access control. AI security is not optional. OWASP lists prompt injection and sensitive information disclosure among the top risks for LLM applications, alongside “overreliance” and “excessive agency.”
A simple example of least privilege: a fine-tuned model that writes Jira tickets should have access to templates, sprint goals, the engineering glossary, and acceptance criteria examples. It should not have access to HR files, payroll documents, or medical benefit information. That’s not paranoia. That’s basic system design applied to AI tools, the same principle you’d apply to any service account in a microservices architecture.
About “deterministic” AI. As we covered in the RAG section, the way transformers predict tokens means identical inputs can still produce different outputs. Beyond RAG, you have other levers to push toward consistency: lowering the temperature parameter (at 0, the model always picks the highest-probability token), enforcing strict output schemas (JSON mode, structured outputs), and adding validation layers after generation. But avoid promising stakeholders “100% deterministic behavior” unless you’ve also built automated checks that catch deviations.
Why data engineering becomes the always-improving layer
AI runs on data. RAG runs on data. Fine-tuning runs on data. Evaluation runs on data.
So even if you are not a data engineer, you now need to speak the language of pipelines and quality.
A data lake is a centralized repository that stores structured and unstructured data at any scale, kept “as-is” to support many forms of analytics and Machine Learning (ML). That matters because when you build a RAG pipeline, your data lake (or warehouse, or lakehouse) is where your retrieval corpus lives. The quality of your AI outputs is bounded by the quality of what goes in.
You also need to understand the difference between ETL (extract, transform, load: transform data before it lands in the target) and ELT (extract, load, transform: load raw data first and transform inside the target system using its compute power). ELT has become dominant in modern data stacks because storage is cheap, compute is elastic (Snowflake is a great example: you can spin up a warehouse, run your transformations, and shut it down, paying only for what you used), and preserving raw data means you can re-transform when requirements change. And they always do.
Focus your learning on four areas. Pipelines: understand ETL/ELT patterns, streaming versus batch processing (Kafka versus Airflow-scheduled jobs), and idempotency guarantees. Data quality: validation rules, anomaly detection, data lineage (knowing where a value came from and what transformed it), and schema evolution. Model-supporting datasets: curated corpora for RAG retrieval, labeled examples for fine-tuning, and evaluation sets for measuring whether your AI actually improved. Governance: access controls, retention policies, privacy boundaries, and audit trails. This is especially critical when AI agents can query data through tools like MCP, because a poorly scoped tool can expose data the model was never meant to see.
If system design is the skeleton, data is the bloodstream.
Code is cheap, show me critical thinking
Linus Torvalds is famously associated with:
“Talk is cheap. Show me the code.”
That quote still matters. But we are entering a new phase. My updated version:
“Code is cheap. Show me critical thinking.”
Because AI can produce code, but what it can’t reliably produce without you is the right problem framing, the right constraints, the right tradeoffs, and the right “no.”
A practical story about over-engineering
A product manager comes to engineering and says:
“We need a way for admins to update some configuration values without deploying. Things like feature copy, toggle thresholds, promotional banners. It should be flexible so we can add more settings over time.”
Engineers (trying to be helpful) design a “beautiful” solution: a full admin portal with role-based access control, audit logs, version history with rollback, an approval workflow, a custom form builder so any config shape can be defined dynamically, and a React frontend with its own design system. They ask AI to help, and AI happily generates thousands of lines of architecture across multiple services.
It looks impressive. It is also a month of work for something that changes maybe once a quarter.
Then someone finally asks the question that should have been asked on day one:
“How often does this actually change, and who changes it?”
And the answer is: “Five values. Updated by two people. Maybe four times a year.”
Suddenly, the best solution is not a custom admin portal. The best solution is: a simple config table in the database, a basic CRUD screen behind your existing admin auth, and a Slack notification when someone changes a value. Done in a day, not a month.
The solution is clarity, not complexity.
This is where senior engineering becomes less about code and more about judgment. And it matters even more with AI, because AI can overproduce patterns (especially when prompts reward “enterprise-grade design”), AI can generate insecure patterns if you don’t review carefully, and AI can slow you down if you let it drag you into unnecessary changes. Your job becomes: use AI to go faster, but use thinking to go right.
Conclusion: your shape is not your identity, it’s your strategy
Generalism is not “bad.” Specialization is not “good.” The value is in choosing the right mix for the world you live in.
In complex environments, generalists can outperform narrow specialists, especially when problems require connecting dots across domains. But in engineering, shipping resilient systems still demands real depth.
AI is pushing us toward a new truth: implementation is accelerating, mistakes are accelerating too, and the bottleneck is moving upstream, toward problem framing, design, safety, and verification.
So here’s the part I want to leave you with:
In the AI era, code is no longer the main proof of skill. Your skill is the ability to decide what code should exist at all.
When you build a strong architecture, AI becomes a multiplier instead of a risk. An agent that follows clean boundaries produces better code than one trying to make sense of a tangled, inconsistent codebase. When you build solid AI engineering practices (clear rules, reusable skills, well-orchestrated agents) you get more reliable outcomes with better security and lower cost. When you invest in data foundations, you feed every future system, including AI, with real truth instead of hallucinated approximations.
So yes, learn broadly. But pick your deep pillar. And make it strong enough that, even when code is cheap, your thinking stays priceless.
References
- IDEO T-shaped people (Tim Brown interview)
- McKinsey on T-shaped skills profiles
- OWASP Top 10 for LLM Applications
- Transformers (self-attention foundation)
- RAG paper
- Anthropic Model Context Protocol (MCP)
- Anthropic context engineering for agents
- OpenAI tokens and how to count them
- OpenAI token counting API docs
- Self-Contained Systems architecture
- Goodbye Microservices, Hello Self-Contained Systems
- OpenRAG
- Langfuse (LLM observability)
Comments
No comments yet. Be the first.