Agentic AI: The 7 Pillars of a Robust Architecture

Le brief IA que les pros lisent chaque soir
Les 7 actus IA du jour, décryptées en 5 min. Gratuit.
Inclus dès l'inscription : notre sélection des meilleurs guides & comparatifs IA.
Choisis ton rythme
Gratuit · Pas de spam · Désabonnement en 1 clic
Understanding the Foundations of an Agentic AI System
In this article, we will explore the seven key components that differentiate a production agentic AI system from a simple demonstration script. These components are essential for ensuring a seamless integration into the agent's central feedback loop.
Essential Components to Analyze
We will examine the following elements:
-
The specific role of each component, namely perception, memory, reasoning and planning, tool execution, orchestration, safeguards, and observability.
-
The potential vulnerabilities of each component in real-world systems and the importance of maintaining their separation.
-
A Python code example illustrating the individual responsibility of each component.
Introduction to Agentic Architecture
Most tutorials on creating an AI agent merely present a 40-line script that calls a LLM in a loop, thus concluding the process. While this may suffice for a demonstration, such a script does not hold up in more complex scenarios, such as interacting with multiple users simultaneously, an unstable API, or tasks requiring multiple steps.
The difference between a demonstration and a production system lies in the architecture. Production agentic AI systems rely on a coherent set of interconnected components: perception, reasoning, planning, memory, tool execution, orchestration, and safeguards. This structure is common in serious architectural analyses, research papers, and recently published post-mortem production reports, regardless of the framework or provider.
The fundamental loop remains constant: Goal → Perception → Reasoning → Planning → Action → Observation → Memory Update → back to Reasoning. This sequence repeats until the goal is achieved, a stopping condition is met, or the agent decides that human intervention is necessary. This article examines each element of this loop as a distinct component, detailing its responsibilities, weaknesses, and providing a code snippet to concretely illustrate its functions. Each element is presented in isolation, which is also how you should consider your own system when deciding what it needs.
Overview of the Seven Components
Architectural surveys converge on a core set: Perception, Memory, Reasoning/Planning, Tool Execution, and Orchestration form a closed feedback loop — the cycle that actually works, step by step. Safeguards and observability envelop this entire loop as cross-cutting concerns rather than as steps within the sequence. You do not "do" safeguards at step 4; safeguards exist between each proposed action and the world, monitoring each step.
This distinction shapes the rest of this article. The first five sections traverse the loop in the order in which data flows through it. The last two sections cover the protective layers that make the loop survivable once real money, real customers, and real side effects are involved.
Transforming Raw Inputs into Usable Data
The role of perception is to transform raw inputs — whether text, voice, API payloads, sensor data, or file uploads — into a structured representation that the reasoning engine can process. This component is often overlooked in tutorials, as in a demonstration, "the user simply types text," and there is nothing to normalize. However, in real systems, inputs come from webhooks, structured API calls, file uploads, and multiple channels simultaneously. Each of these inputs must be normalized before any further processing can trust it.
# perception.py
# Prerequisites: none beyond the standard Python library
# Execution: python perception.py
from dataclasses import dataclass, field
from typing import Any
from enum import Enum
import json
from datetime import datetime, timezone
class InputSource(Enum):
USER_TEXT = "user_text"
WEBHOOK = "webhook"
FILE_UPLOAD = "file_upload"
@dataclass
class AgentInput:
"""
The normalized internal form that each downstream component consumes,
regardless of where the raw input comes from. This is the whole point of a perception layer: everything that comes after this point
only sees this unique structure.
"""
source: InputSource
content: str
metadata: dict[str, Any] = field(default_factory=dict)
received_at: str = field(default_factory=lambda: datetime.now(timezone.utc).isoformat())
def perceive_user_text(raw_text: str) -> AgentInput:
"""Raw chat input -- the simplest case, but it still requires normalization."""
return AgentInput(
source=InputSource.USER_TEXT,
content=raw_text.strip(),
metadata={"channel": "chat"},
)
def perceive_webhook(raw_payload: str) -> AgentInput:
"""
A webhook delivers structured JSON, not raw text. Perception extracts
the part that the agent needs to reason about and eliminates transport-level noise like headers and signatures.
"""
payload = json.loads(raw_payload)
event_type = payload.get("event_type", "unknown")
description = payload.get("description", "")
return AgentInput(
source=InputSource.WEBHOOK,
content=f"Event '{event_type}' received: {description}",
metadata={"event_type": event_type, "raw_payload": payload},
)
def perceive_file_upload(filename: str, file_size_bytes: int, mime_type: str) -> AgentInput:
"""
A file upload event has no natural language content at all -- perception
must build something that the reasoning engine can actually use.
"""
return AgentInput(
source=InputSource.FILE_UPLOAD,
content=f"The user uploaded the file '{filename}' ({mime_type}, {file_size_bytes} bytes)",
metadata={"filename": filename, "mime_type": mime_type, "size_bytes": file_size_bytes},
)
if __name__ == "__main__":
text_input = perceive_user_text(" What is the status of my refund? ")
webhook_input = perceive_webhook(json.dumps({
"event_type": "payment_failed",
"description": "Card declined for order #4821",
}))
file_input = perceive_file_upload("invoice_q3.pdf", 184320, "application/pdf")
for inp in [text_input, webhook_input, file_input]:
print(f"[{inp.source.value}] content='{inp.content}'")
print(f" metadata keys: {list(inp.metadata.keys())}\n")
To run: python perception.py, no dependencies required.
Three completely different raw forms — plain text, JSON webhook payload, and file upload event — all transform into the same AgentInput structure. The downstream reasoning component never needs to know or care which channel something arrived through. This is the entire value of treating perception as its own component rather than integrating ad hoc parsing where the input enters the system.
Working Memory vs. What Actually Persists
Memory is the most nuanced component, and one that demonstration code often mistakenly considers simply as "the conversation so far." In a production memory architecture, it is crucial to distinguish between working memory — the immediate context window for the current task — and long-term memory, which itself divides into episodic memory (what happened), semantic memory (learned facts), and procedural memory (skills and know-how). Short-term memory lives in context and is essentially free; long-term memory typically resides in a vector store, indexed for semantic retrieval rather than for exact matching.
The operational distinction is important: working memory is fast.
Brief IA — L'actualité IA en français
L'essentiel de l'actualité de l'intelligence artificielle, décrypté et expliqué chaque jour.