Moses Adebayo ·

Learning AI Engineering AI-101

Forget the perfect roadmaps. Real AI engineering is fumbling through documentation, over-engineering solutions, then rebuilding everything simpler. Here's the actual journey with tools that don't suck.

AI agents tools workflows evaluation frameworks
AI Engineering Structure

AI actually has a structure. It’s not just “throw a model in there and hope for the best.” There are patterns, best practices, and a whole ecosystem of tools that have emerged to help us build better AI systems. and it’s also not as complicated as everyone makes it out to be.

when someone asks “how do I get started with AI engineering,” they’re usually expecting some sanitized roadmap with perfectly ordered bullet points. But that’s not how any of us actually learned this stuff (me for example). We (i particularly) fumbled around, broke things, read documentations and articles a lot, and slowly pieced together what actually matters.

AI engineering isn’t a linear path—it’s more like learning to cook by actually cooking, not by memorizing every ingredient in order, but since you want to build something useful, let’s break down what actually matters and how these pieces fit together. Not the theory. The practice.

Start Here: Python (But Not the Way You Think)

Yeah, Python. Everyone says Python. But here’s what they don’t tell you: you don’t need to be a Python expert to build AI systems. You need to be comfortable enough to read documentation, understand async/await (because you will run into it), and know how to debug when something inevitably breaks.

If you’re coming from another language—JavaScript, Go, whatever—you’ll pick up Python syntax in a week. What matters more is understanding how to work with APIs, handle HTTP requests, manage environment variables, and structure a project that won’t become a nightmare in three months.

** Some* Resources that actually helped me:**

The FastAPI docs are genuinely good. Like, unusually good. Start building a simple API that does something—doesn’t matter what—and you’ll learn more than any tutorial.

Models: The Thing Everything Else Wraps Around

Here’s where most guides get it backwards. They teach you all the tooling before you understand what you’re actually working with. That’s like learning to build a car engine before you understand what a car does.

Start by just calling a model. Any model. OpenAI’s API is straightforward. Anthropic’s is too (yeah, I’m using Claude, but that’s not why I’m saying this). The point is to understand the fundamental interaction:

# This is literally it
response = client.messages.create(
    model="claude-sonnet-4-5-20250929",
    max_tokens=64000,
    messages=[{"role": "user", "content": "What's the best thing after plantain?"}]
)

That’s the entire foundation of AI engineering. Everything else is just wrapping complexity around this basic interaction to make it more useful.

Start here:

Spend a day just calling these APIs. Try different prompts. Break things. See what happens when you hit rate limits. This is your foundation.

Tools and Function Calling: When Models Need to Do Things

Okay, so models can respond to text. Cool. But what if you need your AI to actually do something? Check a database? Call an API? This is where tools come in, and it’s where things start getting interesting.

Function calling (or tool use, depending on who made the API) is how you give models the ability to interact with the world. You define functions, tell the model what they do, and the model decides when to call them.

tools = [
    {
        "name": "get_weather",
        "description": "Get weather for a location",
        "input_schema": {
            "type": "object",
            "properties": {
                "location": {"type": "string"}
            }
        }
    }
]

The model sees this and thinks, “Oh, if someone asks about weather, I can use this tool.” Then it returns a structured request for you to execute.

This is where AI engineering stops being chatbots and starts being systems. You’re building applications that can reason about what they need to do and then do it.

Deep dive resources:

Agents: When You Let the Model Think

Here’s where people get confused. An agent isn’t a special type of model. It’s a pattern. A loop. You give the model a task, it thinks, it maybe calls some tools, it thinks again, and it repeats until the task is done.

The simplest agent is literally just:

  1. Get user input
  2. Send to model
  3. Model responds or requests a tool
  4. If tool requested, execute it and go back to step 2
  5. If response, return to user

That’s it. Everything else is optimization, error handling, and preventing infinite loops.

The hard parts? Knowing when to stop. Handling failures gracefully. Making sure your agent doesn’t go off the rails and make 500 API calls trying to solve a simple problem. This is where experience matters more than any framework.

Where to learn:

Start by building a simple agent that can use 2-3 tools max. Don’t try to build something that can “do anything.” That way lies madness and infra bills you’ll regret.

RAG: When Your Model Needs to Know Things It Wasn’t Trained On

Retrieval-Augmented Generation. Fancy term for: “Let me search through my documents and give the relevant parts to the model.”

This is how you build AI that knows about your specific data. Your company docs. Your codebase. Your customer support history. Whatever.

The pipeline:

  1. Chunking - Split your documents into smaller pieces (usually 500-1000 tokens). Too big and you lose precision. Too small and you lose context.
  2. Embedding - Convert those chunks into vectors (arrays of numbers that represent meaning)
  3. Storing - Put those vectors in a database designed for similarity search
  4. Retrieving - When user asks a question, embed their question, find similar chunks
  5. Generating - Give those chunks to your model as context

Everyone makes this sound more complicated than it is. The first time you build it, use the simplest possible approach:

# Embed your documents
chunks = split_document(doc)
embeddings = [embed(chunk) for chunk in chunks]

# Later, when searching
query_embedding = embed(user_question)
similar_chunks = vector_db.search(query_embedding, top_k=5)

# Give to model
response = model.generate(
    context=similar_chunks,
    question=user_question
)

Resources:

The hard part of RAG isn’t the technology. It’s figuring out how to chunk your data well, which documents to retrieve, and how much context to give the model without overwhelming it.

Vector Databases: Where Similarity Lives

Pinecone (pinecone.io) - Hosted, managed, just works. Pay for what you use. If you’re building a product and don’t want to think about infrastructure, start here. Their free tier is generous enough for prototyping.

Qdrant (qdrant.tech) - Open source, can self-host, Docker-friendly. If you’re comfortable with infrastructure or need to keep data local, this is excellent. I’ve used it for production systems. Documentation is clear, API is intuitive.

Weaviate (weaviate.io) - Another solid open-source option. Good for when you need more complex filtering alongside vector search.

Chroma (trychroma.com) - Lightweight, perfect for local development. Don’t use it for production at scale, but it’s great for prototyping.

We also have newer players like Redis Vector Search, Vespa, S3 Vector, Mongo Atlas Vector and more. The ecosystem is growing fast.

The truth? For most applications, the vector database matters less than you think. They all do similarity search. Pick one that fits your deployment model and move on. You can always migrate later.

Memory: The Difference Between a Chat and a Conversation

Memory is how your AI remembers things across messages. Not the model’s training data—actual conversation history, user preferences, previous decisions.

There are levels to this:

Short-term memory - Just keep the conversation history. Easy. Every message includes previous messages. Works until you hit context limits.

conversation_history = [
    {"role": "user", "content": "What's the weather?"},
    {"role": "assistant", "content": "I need your location"},
    {"role": "user", "content": "San Francisco"}
]

Long-term memory - Store things in a database. User preferences, facts they’ve mentioned, previous interactions. This is where you start building something that feels personalized.

Semantic memory - Use RAG on conversation history. When the conversation gets long, embed past messages and retrieve relevant ones. This is how you scale memory beyond context windows.

The trick is knowing what to remember and what to forget. Not everything matters. Users don’t want their AI to remember that one typo from three months ago.

Reading:

Context Management: Fitting Everything In

Context windows are getting bigger (Claude has 200K tokens, i think they announced 1m tokens with Opus 4.6 recently, GPT 5.2 has 400K), but you still need to manage what goes into that window. More context isn’t always better. It’s expensive, slower, and models can get “lost in the middle.”

Good context management means:

This isn’t a tool you install. It’s a design pattern you build into your system. Think about what your model actually needs to answer the current question, not everything it could possibly need.

Routing: Smart Decision Making

Routers are how you decide which model, which tool, or which workflow to use. The model acts as a classifier:

async def route_request(user_input):
    classification = await simple_model.classify(user_input)
    
    if classification == "simple_question":
        return await fast_model.answer(user_input)
    elif classification == "complex_reasoning":
        return await powerful_model.answer(user_input)
    elif classification == "needs_search":
        return await search_agent.process(user_input)

This is how you build systems that are both fast and capable. Most requests don’t need your most expensive model. Route intelligently.

Learn more:

Workflows: Orchestrating Complexity

When your system needs to do multiple things in sequence—search, then analyze, then format, then validate—you need workflows. This is where tools like LangGraph come in.

LangGraph (Langraph Workflows Agents) - Built on LangChain, lets you define AI workflows as graphs. State moves through nodes, each node can call models or tools. It’s more structured than “just let the agent figure it out.”

Think of it like this: Agents are “figure it out yourself.” Workflows are “here’s the exact path.”

Sometimes you want the flexibility of an agent. Sometimes you want the reliability of a defined workflow. Build both depending on your use case.

from langgraph.graph import StateGraph

workflow = StateGraph()
workflow.add_node("search", search_documents)
workflow.add_node("analyze", analyze_results)
workflow.add_node("respond", generate_response)

workflow.set_entry_point("search")
workflow.add_edge("search", "analyze")
workflow.add_edge("analyze", "respond")

Observability: Because You Will Need to Debug

This is the part no one talks about until they’re drowning in production issues. You need to see what your AI is doing.

LangSmith (smith.langchain.com) - From the LangChain folks. Traces every step of your LLM calls. See exactly what prompts were sent, what responses came back, how much it cost, how long it took. Essential for debugging.

LangFuse (langfuse.com) - Open source alternative. Self-hostable. Similar tracing capabilities. I’ve used this in production. It works.

Weights & Biases (wandb.ai) - More ML-focused, but has LLM tracing. Good if you’re already in their ecosystem.

You don’t need these day one. But the moment you’re running in production and something weird happens, you’ll be grateful you added tracing.

LangChain: The Controversial Framework

LangChain gets a lot of hate (not from me tho). “Too much abstraction.” “Does too much.” “Hard to debug.”

They’re not entirely wrong. But here’s the nuance: LangChain gives you batteries-included components for common AI patterns. It’s useful when you’re prototyping and want to move fast. It’s less useful when you need fine-grained control.

I use parts of LangChain selectively:

Don’t feel like you need to use the whole framework. Pick the pieces that help and ignore the rest.

The Order That Actually Makes Sense

If I were starting over today, here’s how I’d actually approach learning this:

  1. Week 1: Just call models - OpenAI or Anthropic API. Send prompts. Get responses. Understand tokens, temperature, and system prompts.

  2. Week 2: Add function calling - Build a simple tool. Weather API, database query, whatever. Make the model use it.

  3. Week 3: Build a simple agent - Let it loop. Give it 2-3 tools. See what breaks.

  4. Week 4: Add RAG - Take some documents, chunk them, embed them, search them. Use Chroma locally.

  5. Week 5-6: Build something real - A chatbot for your docs. A customer support assistant. Something with actual users (even if it’s just you).

  6. Week 7: Add observability - Now that you have something working, add tracing. See where time is spent, where money is spent.

  7. Week 8+: Optimize - Better prompts. Better chunking. Better routing. This never ends.

The Resources I Actually Use

Daily reading:

Documentation I bookmark:

Communities:

What I Wish Someone Told Me

Start small. Everyone wants to build the perfect AI system that does everything. You’ll burn out and ship nothing. Build one feature. Make it work. Then add the next.

Prompting matters more than tools. I’ve seen simple Python scripts with great prompts outperform complex LangChain setups with mediocre prompts. Get good at writing prompts.

Models are getting better fast. Don’t over-engineer for current limitations. Something you hack together today might be unnecessary when GPT-6 or Claude 5 or whatever drops.

Cost matters. Test on small models. Deploy on big ones only where needed. Your pocket will thank you, this things can get expensive very fast. this is not react/nextjs that you can easily host on vercel.

Users don’t care about your architecture. They care if it works and if it’s fast. Everything else is engineering ego.

The Projects That Teach You

Don’t just read. Build these:

  1. Personal document chatbot - RAG over your notes, bookmarks, whatever. You’ll learn chunking, embeddings, and retrieval.

  2. Automated research assistant - Give it a topic, let it search the web, summarize findings. You’ll learn agents and tools.

  3. Code review assistant - Take a GitHub repo, let it analyze code and suggest improvements. You’ll learn context management and prompting.

  4. Customer support classifier - Route support tickets to the right team. You’ll learn routing and classification.

Pick one. Build it start to finish. You’ll learn more than reading 100 articles. you’ll learn from this one baba mi.

Final Thoughts

AI engineering isn’t that different from regular engineering. You’re solving problems. You’re building systems. The only difference is one of your components happens to be a model that can reason.

Don’t get caught up in the hype or the framework wars. Just build things. Break them. Fix them. Ship them.

The best AI engineers I know aren’t the ones who memorized every LangChain component. They’re the ones who understand their users’ problems and build the simplest thing that could possibly work, try to walk away from complexity as much as you can 🙏🏾

Everything else is just tools in the toolbox. Learn them as you need them.

Now go build something. “You that boyyy”


“The best way to learn is to build. The second best way is to break what you built and figure out why. Everything else is just reading someone else’s build logs.” — Williams Moses Shakespeare, probably.

Previous motion: my 2025 year in review