From .NET to AI Engineer — Part 6: Chatbot vs. Agent
Part 6 of the series on staying current by adding AI, from a .NET background. Days 16–19 of the journey — the agents stage, where the model stops just answering questions and starts deciding what to do.
"Agent" is one of the most hyped words in AI, so I'll give you the version that finally made it concrete for me, as a developer: the difference between a chatbot and an agent is who's in control. Once you see that, everything else — tools, loops, guardrails — falls into place. This stage took four days.
Theory
Function calling: who decides?
Here's the distinction that unlocked it. In a normal function call, you — the programmer, at code-writing time — decide which function runs, when, and with what arguments. With LLM tool calling, you instead describe a set of tools to the model, and the model decides at runtime which one to call and what arguments to pass, based on the user's request.
You don't call the tool from the prompt. You hand the model a menu and it places the order.
tools = [{
"name": "get_stock_price",
"description": "Get the latest closing price for a stock symbol",
"input_schema": {
"type": "object",
"properties": {"symbol": {"type": "string"}},
"required": ["symbol"],
},
}]
You expose get_stock_price; the model, when it sees "how's Tesla doing?", figures out on its own that it should call that tool with symbol="TSLA". Your code then runs the real function and hands the result back.
The agent loop
An agent is that idea in a loop:
- The model receives the goal.
- It decides whether to call a tool.
- Your code runs the tool and returns the result.
- The model looks at the result and decides the next step — another tool, or a final answer.
- Repeat until done.
That cycle — reason, act, observe, repeat — is the whole engine. The popular ReAct pattern is exactly this. Frameworks like LangGraph give you a prebuilt version, or let you build the loop yourself as an explicit state machine when you need control.
Guardrails (the part backend devs won't forget)
A loop that decides its own next step can loop forever, or call something it shouldn't. So you cap it: a maximum number of iterations, and an allowlist of actions it's permitted to take. If you've ever put a circuit breaker or a retry limit around a service call, this is the same instinct — and it matters more here, not less, because the caller is non-deterministic.
Agent vs. "agentic," single vs. multi
Two bits of vocabulary worth having straight. An AI agent is one model-plus-tools loop pursuing a goal. Agentic AI is the broader pattern of systems that plan and act over multiple steps — sometimes several specialized agents collaborating (multi-agent) rather than one generalist (single-agent). Start with a single agent; reach for multiple only when one is genuinely juggling too many unrelated jobs.
Build: a tool-using agent
The Stage 5 project was an agent that could actually do things — a financial-auditor agent wired to a few tools (look up a figure, run a check, fetch a record) that it chose between on its own to answer a multi-step question. I built one version on a framework's prebuilt loop and one as an explicit state machine, to feel the difference between convenience and control.
The takeaway
The leap from RAG to agents is the leap from "answer me" to "go accomplish this." The model becomes a decision-maker that drives your code, instead of a function your code calls. That's powerful — and it's exactly why the engineering discipline you already have (limits, allowlists, observability, failing safely) becomes more important, not less. The non-determinism is the feature; the guardrails are what make it shippable.
The 4-day plan (if you want to follow along)
| Day | Time | Learn (theory) | Build | Why it matters | Reference | Output |
|---|---|---|---|---|---|---|
| 16 | ~6h | Function/tool calling — the model decides | Define a tool; let the model choose to call it | The core shift: you hand over the menu, the model orders | LangChain tools; provider tool-use docs | A model calling one tool correctly |
| 17 | ~7h | The agent loop (ReAct) | Build a multi-step loop: reason → act → observe → repeat | This cycle is the entire agent engine | DeepLearning.AI agents course | An agent chaining two or three tool calls |
| 18 | ~7h | Guardrails; LangGraph (prebuilt vs custom) | Add iteration limits and an action allowlist | A self-driving loop needs brakes, same as any service | LangGraph docs | A bounded, safe agent |
| 19 | ~6h | Agent vs agentic; single vs multi-agent | Finish the auditor agent; write up the distinctions | Knowing when one agent is enough saves a lot of complexity | HuggingFace Agents course | Finished agent pushed to GitHub |
What I used to learn this
- LangChain tools docs: https://python.langchain.com/docs/concepts/tools/
- LangGraph docs: https://langchain-ai.github.io/langgraph/
- DeepLearning.AI short courses on functions, tools, and agents: https://www.deeplearning.ai/short-courses/
- HuggingFace Agents course: https://huggingface.co/learn/agents-course
- Prompt Compression: https://learn.deeplearning.ai/courses/prompt-compression-and-query-optimization/lesson/c14k8/introduction
- FAST API: https://www.youtube.com/watch?v=G0dhZces5XM
Related code: https://github.com/ashaniwale-codestack/llm-agents-experiments
Next up — Part 7, the finale: shipping it. FastAPI, Docker, caching, and all the production discipline that turns a clever notebook into something other people can actually use.