Vinith Raj

Engineering reliable systems that help people do meaningful work.

  • About me
  • Articles
  • Contact me

Agentic AI Series – Introduction

December 19, 2025

Agentic AI has quickly become one of those terms that carries more weight than clarity. Depending on where you encounter it, it is either framed as the next inevitable step toward autonomous systems or dismissed as unnecessary complexity layered on top of language models. Both views miss the point. Agentic AI is neither magical nor reckless. At its core, it is a design approach—one that shifts how we express intent, coordinate services, and adapt systems to real-world variability.

This article is not meant to sell a framework or declare a best practice. Its purpose is to build a clear mental model for what agentic systems actually are, how they behave, and why you might choose this approach over more traditional orchestration patterns. Everything here is grounded in system design rather than speculation.

What an agent actually is

An agent is not a sentient entity and it is not autonomous in the human sense. An agent is a loop. It observes input, reasons about the current situation, proposes a next step, executes that step through predefined mechanisms, observes the result, and repeats if necessary. The only difference between an agentic system and a traditional one is that the reasoning step is performed by a language model rather than by hand-written conditional logic.

This distinction matters. The language model does not own execution, memory, or authority. It proposes. The surrounding system disposes. All real power—state management, permissions, retries, termination—lives outside the model, in software you design and control.

Once this is understood, agents stop feeling mysterious. They become predictable components in a larger system.

This makes agentic AI far less risky than it is often portrayed, especially when compared to opaque, deeply embedded decision logic in large legacy systems.

Why take the agentic route at all?

To understand the appeal of agentic AI, it helps to contrast it with traditional orchestration. In a conventional system, coordinating multiple services requires procedural code that explicitly encodes the flow of execution. Developers must anticipate possible paths, write branching logic, handle edge cases, and update that logic whenever behavior needs to change. As systems grow, orchestration code often becomes the most complex and brittle part of the stack. The following diagram highlights where control shifts in an agentic system—from hard-coded branching logic to an orchestrated reasoning loop.

flowchart TB
    %% Title
    TT["Traditional Procedural Orchestration"]:::title

    %% Spacer for padding
    SP1[ ]:::spacer
    SP2[ ]:::spacer

    U[User / Request]
    C[Hard-coded Orchestration Logic]
    D{Conditional Branching}
    S1[Service A]
    S2[Service B]
    S3[Service C]
    E[Edge Case & Error Handling]

    TT --> U
    U --> C
    C --> D
    D -->|Path 1| S1
    D -->|Path 2| S2
    D -->|Path 3| S3
    S1 --> E
    S2 --> E
    S3 --> E
    E --> SP2

    %% Styling
    classDef title fill:#FFFFFF,stroke:transparent,color:#263238
    classDef user fill:#E3F2FD,stroke:#1565C0,color:#0D47A1
    classDef orchestration fill:#FFF3E0,stroke:#EF6C00,color:#E65100
    classDef logic fill:#FCE4EC,stroke:#AD1457,color:#880E4F
    classDef service fill:#F3E5F5,stroke:#6A1B9A,color:#4A148C
    classDef edge fill:#ECEFF1,stroke:#455A64,color:#263238
    classDef spacer fill:transparent,stroke:transparent

    class TT title
    class U user
    class C orchestration
    class D logic
    class S1,S2,S3 service
    class E edge
flowchart TB
    %% Title
    TT["Agentic Orchestration"]:::title

    %% Spacer for padding
    SP1[ ]:::spacer
    SP2[ ]:::spacer

    U[User / Intent]
    O[Orchestrator]
    L[LLM Reasoning Engine]
    T1[Tool / Service A]
    T2[Tool / Service B]
    T3[Tool / Service C]

    TT --> U
    U --> O
    O --> L
    L --> O
    O --> T1
    T1 --> T2
    T2 --> T3
    T3 --> SP2

    %% Styling
    classDef title fill:#FFFFFF,stroke:transparent,color:#263238
    classDef user fill:#E3F2FD,stroke:#1565C0,color:#0D47A1
    classDef orchestration fill:#FFF3E0,stroke:#EF6C00,color:#E65100
    classDef llm fill:#E8F5E9,stroke:#2E7D32,color:#1B5E20
    classDef service fill:#F3E5F5,stroke:#6A1B9A,color:#4A148C
    classDef spacer fill:transparent,stroke:transparent

    class TT title
    class U user
    class O orchestration
    class L llm
    class T1,T2,T3 service

Figure: Comparison between traditional and agentic orchestration.

Agentic systems move that complexity out of rigid code paths and into structured reasoning expressed in natural language. Instead of writing code to determine what should happen step by step, you describe the goal and the available capabilities. The agent interprets that intent and decides which actions to take, while the system enforces how those actions are carried out.

One important consequence of this shift is that end users no longer need to write orchestration code. They express intent in language. The agent translates that intent into executable steps using tools the system provides. Developers still write code, but at a different level: defining capabilities, constraints, and safety boundaries rather than enumerating every possible workflow.

This approach also makes systems more adaptable. When inputs vary or requirements evolve, behavior can often be adjusted by changing instructions rather than rewriting logic. This lowers the cost of iteration and makes experimentation feasible in domains where workflows are difficult to fully specify in advance.

How to think about agents as a system designer

A useful mental model is to treat the language model as stateless reasoning embedded inside a stateful system. The model does not remember anything unless the system feeds it context. It does not retry unless the orchestrator asks it to. It does not persist decisions unless state is explicitly recorded.

What looks like memory or adaptation is simply repeated invocation with updated context. This makes agentic systems easier to reason about than they initially appear, because all durability and control remain explicit.

Once you adopt this framing, agents stop feeling like a new category of software and start looking like an evolution of orchestration patterns you already know.

flowchart TB

    USER["User or Automation (Web UI, CLI, Scheduler)"]:::user

    ACCESS["Access Layer (API Gateway, Auth, Rate Limits)"]:::edge

    ORCH["Orchestrator (Agent control loop)"]:::orchestrator
    POLICY["Policies and Guardrails (what the agent is allowed to do)"]:::security
    PROMPTS["Prompt Instructions (how the agent should think)"]:::config

    LLM["LLM Runtime On Prem (Ollama with local model)"]:::llm

    STATE["State and Memory (tasks, steps, context, outputs)"]:::db

    TOOLS["Tool Registry (what capabilities exist)"]:::config

    SERVICES["Execution Services (data, files, compute, notifications)"]:::service

    SANDBOX["Execution Safety (sandbox, allowlists, limits)"]:::security

    OBS["Observability (logs, metrics, traces, audit)"]:::obs

    DATA["On Prem Data Sources (databases, NFS, repositories)"]:::storage

    USER --> ACCESS
    ACCESS --> ORCH

    ORCH --> POLICY
    ORCH --> PROMPTS
    ORCH --> LLM

    ORCH --> STATE
    ORCH --> TOOLS
    TOOLS --> SERVICES
    SERVICES --> SANDBOX
    SANDBOX --> DATA

    ORCH --> OBS
    LLM --> OBS
    SERVICES --> OBS

    classDef user fill:#E3F2FD,stroke:#1565C0,color:#0D47A1
    classDef edge fill:#FFF8E1,stroke:#F9A825,color:#6D4C00
    classDef orchestrator fill:#FFF3E0,stroke:#EF6C00,color:#E65100
    classDef llm fill:#E8F5E9,stroke:#2E7D32,color:#1B5E20
    classDef service fill:#F3E5F5,stroke:#6A1B9A,color:#4A148C
    classDef db fill:#E0F7FA,stroke:#00838F,color:#004D40
    classDef storage fill:#ECEFF1,stroke:#455A64,color:#263238
    classDef obs fill:#F1F8E9,stroke:#689F38,color:#33691E
    classDef security fill:#FFEBEE,stroke:#C62828,color:#8E0000
    classDef config fill:#FAFAFA,stroke:#616161,color:#212121

This diagram should show an external trigger or user request entering an orchestration service. The orchestrator sits at the center, communicating with a language model for reasoning and with a set of tools or services for execution. Persistent state and logging exist beneath the orchestrator, not inside the model.

At a high level, an agentic system is composed of an entry point that defines intent, an orchestrator that owns the task lifecycle, a language model that proposes actions, and an execution layer that performs real work. The orchestrator mediates everything. Nothing moves directly from reasoning to execution without passing through it.

The role of the language model

Within this architecture, the language model’s role is narrow but powerful. It interprets intent, evaluates context, and suggests what should happen next. It does not execute code, open network connections, or mutate state. Those responsibilities remain firmly within the system.

This separation is intentional. It allows models to be swapped, prompts to be refined, and reasoning behavior to evolve without destabilizing execution. It also makes failures understandable. When something goes wrong, you can inspect whether the issue lies in reasoning, orchestration, or execution rather than treating the system as a black box.

flowchart TB

    INPUT["Input Received (user request or event)"]:::user

    ORCH["Orchestrator (controls the loop)"]:::orchestrator

    STATE_CHECK["Evaluate Current State (what is known so far)"]:::state

    LLM["Invoke Language Model (reason about next step)"]:::llm

    DECISION["Proposed Action Valid?"]:::decision

    EXECUTE["Execute Permitted Action (tool or service call)"]:::service

    UPDATE["Update State (store results and progress)"]:::state

    CONTINUE["Continue or Terminate?"]:::decision

    DONE["Task Complete"]:::done

    INPUT --> ORCH
    ORCH --> STATE_CHECK
    STATE_CHECK --> LLM
    LLM --> DECISION

    DECISION -->|Yes| EXECUTE
    DECISION -->|No| UPDATE

    EXECUTE --> UPDATE
    UPDATE --> CONTINUE

    CONTINUE -->|Continue| ORCH
    CONTINUE -->|Terminate| DONE

    classDef user fill:#E3F2FD,stroke:#1565C0,color:#0D47A1
    classDef orchestrator fill:#FFF3E0,stroke:#EF6C00,color:#E65100
    classDef llm fill:#E8F5E9,stroke:#2E7D32,color:#1B5E20
    classDef service fill:#F3E5F5,stroke:#6A1B9A,color:#4A148C
    classDef state fill:#E0F7FA,stroke:#00838F,color:#004D40
    classDef decision fill:#FFFDE7,stroke:#F9A825,color:#6D4C00
    classDef done fill:#ECEFF1,stroke:#455A64,color:#263238

The orchestrator is responsible for enforcing boundaries. It decides when the loop runs, how many iterations are allowed, and when a task is considered complete. Agents do not run indefinitely unless explicitly designed to do so.

Tools and capabilities

Agents are only as useful as the tools they can access. These tools are not intelligent components; they are ordinary services exposed through well-defined interfaces. What makes them suitable for agentic use is clarity. Each tool should have a narrow purpose, predictable inputs, and explicit outputs.

The agent does not discover tools dynamically. The system introduces them, usually by describing available capabilities in natural language or structured schemas. The agent reasons about when a tool should be used; the orchestrator ensures that it is used safely.

Poorly defined tools lead to unpredictable behavior. Well-defined tools make agentic systems reliable.

flowchart TB

    ORCH["Orchestrator (controls execution)"]:::orchestrator

    LLM["Language Model (reasons about tools)"]:::llm

    REGISTRY["Tool Registry (catalog of capabilities)"]:::config

    TOOL1["Tool A (name, description, input, output)"]:::service
    TOOL2["Tool B (name, description, input, output)"]:::service
    TOOL3["Tool C (name, description, input, output)"]:::service

    EXEC["Tool Execution Layer (actual service calls)"]:::security

    ORCH --> LLM
    LLM --> REGISTRY

    REGISTRY --> TOOL1
    REGISTRY --> TOOL2
    REGISTRY --> TOOL3

    ORCH --> EXEC
    EXEC --> TOOL1
    EXEC --> TOOL2
    EXEC --> TOOL3

    TOOL1 --> ORCH
    TOOL2 --> ORCH
    TOOL3 --> ORCH

    classDef orchestrator fill:#FFF3E0,stroke:#EF6C00,color:#E65100
    classDef llm fill:#E8F5E9,stroke:#2E7D32,color:#1B5E20
    classDef config fill:#FAFAFA,stroke:#616161,color:#212121
    classDef service fill:#F3E5F5,stroke:#6A1B9A,color:#4A148C
    classDef security fill:#FFEBEE,stroke:#C62828,color:#8E0000

There is no single correct architecture

One of the most important ideas to internalize is that there is no universally correct way to build an agentic system. What works well for one use case may be unnecessary or even harmful for another. Some systems benefit from tight constraints and short loops. Others require more flexibility and iteration. Some can remain simple indefinitely. Others naturally grow more complex over time.

Designing agentic systems is therefore an exercise in adaptation. You build something small, observe how it behaves, and change it until it fits your needs. That process never really ends, and that is not a weakness. It is simply how systems that interact with human intent evolve.

Exploring this together

This series is written from within that process, not from a distance. I am building and testing these systems as I write about them, and the articles will reflect that reality. Some approaches will work better than expected. Others will need to be revised or discarded. That iteration is intentional.

If you are reading this, you are part of that exploration. There is no checklist to follow and no single architecture to copy. Instead, we will develop an understanding of the principles and trade-offs that matter, and apply them contextually.

The goal is not to arrive at the “right” way to do agentic AI, but to develop the judgment needed to build systems that work for your environment, your constraints, and your goals.

In the next article, we will move from theory to practice by setting up a minimal on-prem agentic environment and building the simplest possible orchestrator—one that you can observe, debug, and extend without guesswork.

Posted in: Agentic AI, Articles, Series, Systems Architecture Tagged: agentic ai, ai agents, ai infrastructure, ai system design, applied ai, distributed systems, llm orchestration, llm systems, microservices architecture, on-prem ai, software orchestration, systems architecture, workflow orchestration