๐ง Agentic AI Fundamentals
๐ก An LLM answers. An
agent acts. The difference is not a longer
prompt โ it is a control loop with tools,
memory, a permission envelope, and a stop condition. Mix those
wrong and you get a token furnace that can also
DROP TABLE. Mix them right and you get boring,
reversible work.
๐บ๏ธ The map
Read this as a curriculum, not a glossary. Five layers, each one only justified when the layer below is not enough:
- ๐ฏ Definition โ LLM vs workflow vs agent. Answers: who chooses the next step?
- ๐งฉ Anatomy โ model, planner, tools, memory, guardrails, orchestrator. Answers: what is the system besides the LLM?
- ๐ Patterns โ ReAct, plan-and-execute, reflection, Anthropicโs five workflows. Answers: how does control flow?
- ๐ง Integration โ function calling, MCP, multi-agent, skills. Answers: how does it touch the world?
- ๐ญ Production โ memory, LLMOps, HITL (or HIL), prompt injection, evals. Answers: how do you ship it without a pager?
flowchart TB
subgraph LADDER["๐ช Complexity ladder"]
direction TB
A["1๏ธโฃ ๐ฌ Single LLM call"]
B["2๏ธโฃ ๐ RAG / in-context"]
C["3๏ธโฃ ๐งฑ Workflow
code chooses the path"]
D["4๏ธโฃ ๐ค Agent
model chooses the path"]
E["5๏ธโฃ ๐ฅ Multi-agent
roles + handoffs"]
end
A --> B --> C --> D --> E
๐ฏ What is Agentic AI?
Classic AI already had the word. Russell & Norvig treat an agent as something that perceives and acts toward a performance measure [7]. PEAS โ Performance, Environment, Actuators, Sensors โ is still the right checklist. LLM-era โagentic AIโ is that idea with a language model as the policy: the model interprets a goal, selects actions (usually tool calls), observes results, and continues until a stop condition.
The useful distinction is not โchatbot vs agent.โ It is who owns control flow [1]:
- ๐ฌ Traditional LLM generation โ prompt โ response. One shot, maybe a few turns of chat. No tools, no state machine, no side effects.
- ๐งฑ Workflow โ LLMs and tools orchestrated through predefined code paths. You wrote the graph. The model fills in nodes. Predictable, cheap to debug.
- ๐ค Agent โ the LLM dynamically directs its own process and tool use. Runtime observations change what happens next. Flexible, expensive, compounding-error-prone.
flowchart LR
subgraph SHOT["๐ฌ Single-shot LLM"]
P1["๐ Prompt"] --> M1["๐ง Model"] --> R1["๐ค Response"]
end
subgraph LOOP["๐ค Agentic loop"]
G["๐ฏ Goal"] --> PL["๐บ๏ธ Plan"]
PL --> ACT["๐ ๏ธ Action / tool"]
ACT --> OBS["๐๏ธ Observation"]
OBS --> ST["๐ฆ Updated state"]
ST --> DEC{"โ
Done?"}
DEC -->|no| PL
DEC -->|yes| OUT["๐ Result"]
end
A system becomes meaningfully agentic when all of these are true:
- ๐ฏ A persistent goal, not only a response request
- ๐ฆ State across multiple steps
- ๐ ๏ธ Dynamic selection of tools or actions
- ๐๏ธ Feedback from an environment (API, codebase, browser, user)
- ๐ Replanning after failures or new information
- ๐ Explicit completion and stopping criteria
- ๐ก๏ธ Bounded autonomy โ a permission envelope, not โdo whateverโ
A fixed chain of three predetermined LLM calls is a workflow, not an agent. The key test: do runtime observations change what the system decides to do next?
๐งฉ Anatomy of an agent
The LLM is not the agent. The agent is a system that uses an LLM as a policy. Strip the other parts and you have an eloquent intern with root access.
๐ง Decide
- ๐ง LLM / policy interpret goal, pick next action
- ๐บ๏ธ Planner tasks, deps, success criteria
- ๐งช Evaluator rubric / tests / schema
๐ ๏ธ Act
- ๐ ๏ธ Tool layer APIs, DB, search, code
- ๐ก๏ธ Guardrails auth, safety, cost, kill switch
๐ฆ Remember
- ๐งพ Working memory current task + observations
- ๐ Long-term memory facts, prefs, experience
- ๐พ State manager checkpoints, retries, approvals
| Component | Job | If you skip it |
|---|---|---|
| ๐ง LLM / policy | Interpret goal, reason, select the next action | You do not have an agent โ you have a script |
| ๐บ๏ธ Planner | Goal โ tasks, dependencies, completion criteria | Thrashing, duplicated work, no progress metric |
| ๐ ๏ธ Tool layer | Controlled access to APIs, DBs, search, code | Hallucinated side effects, or no side effects |
| ๐งพ Working memory | Current task, recent observations, tool results | Context overflow or amnesia mid-run |
| ๐ Long-term memory | Cross-session facts, preferences, experience | Stateless intern every morning |
| ๐พ State manager | Checkpoints, retries, approvals, resume | Crash = start over; HITL = hope |
| ๐งช Evaluator | Did the output actually satisfy the spec? | Confident wrong answers |
| ๐ก๏ธ Guardrails | Auth, data, safety, cost, operational bounds | The DROP TABLE demo |
| ๐๏ธ Orchestrator | Run the loop; decide continue / retry / pause / stop | Infinite loops and silent hangs |
โ When an agent is the wrong tool
An agent is usually the wrong choice when the process is predictable, rules-based, or high-risk without room for runtime judgment. Prefer a conventional workflow (or just software) when:
- ๐ Every step can be defined in advance
- ๐ฏ Deterministic output is required
- ๐ A simple API, SQL query, or rules engine solves it
- โ๏ธ Errors have severe legal, financial, or safety consequences
- โฑ๏ธ Latency or cost budgets are extremely tight
- ๐งช There is no reliable way to verify success
- ๐ The agent would have broad permissions but limited supervision
Rule: deterministic software for what can be specified; agentic decision-making only for the uncertain portion. Anthropicโs production note is the same: many apps only need a well-prompted single call with retrieval [1].
๐ก๏ธ Autonomy as a permission envelope
Autonomy is not a vibe in the system prompt. It is a permission envelope enforced outside the model. For every tool and action, specify:
- ๐ Which resources the agent can access
- ๐ Read-only vs mutating operations
- ๐ข Data and tenant boundaries
- ๐ธ Transaction and spending limits
- ๐ Actions that require human approval
- ๐ Max steps, retries, runtime, and token budget
- ๐ซ Prohibited actions
- ๐จ Escalation and shutdown conditions
flowchart TB USER["๐ค User / goal"] --> ORCH["๐๏ธ Orchestrator"] ORCH --> LLM["๐ง LLM
untrusted proposer"] LLM -->|"function call request"| POL["๐ก๏ธ Policy engine
schema + auth + limits"] POL -->|allow| TOOL["๐ ๏ธ Tool / sandbox"] POL -->|deny / HITL| HUM["๐ Human"] TOOL --> OBS["๐๏ธ Observation"] HUM --> OBS OBS --> ORCH
Enforce this with authorization services, sandboxing, typed
tool schemas, policy engines, database roles, and approval
workflows. Prompt instructions are not a security
boundary. If the model generates
DROP TABLE, its database identity should lack
permission to execute it.
๐ Control-loop patterns
Three loops cover most โrealโ agents. Workflows (next section) cover the cases where you should not let the model own the path at all.
๐ ReAct โ reason, act, observe
ReAct (Yao et al., ICLR 2023) [2] interleaves verbal reasoning traces with actions so the model can reason to act and act to reason. The loop:
- ๐ง Interpret the current goal and evidence (Thought)
- ๐ ๏ธ Select an action or tool (Action)
- โ๏ธ Execute it
- ๐๏ธ Observe the result (Observation)
- ๐ Update the approach and repeat
flowchart LR
T["๐ญ Thought"] --> A["๐ ๏ธ Action"]
A --> O["๐๏ธ Observation"]
O --> T
WHERE. The correct next step depends on external information โ support tickets, docs search, codebase inspection, browser tasks. Example: inspect an order โ observe it already shipped โ consult refund policy โ propose the right resolution.
TRADE-OFFS. High latency, token use, error accumulation, runaway loops. In production, keep reasoning internal; log actions, observations, and decisions as structured traces. Cap turns. Prefer structured tool arguments over free-form โthoughtโ leaking into the UI.
๐บ๏ธ Plan-and-Execute
Separate strategy from tactics. A planner creates a list or graph of subtasks. Executors complete them. The planner may revise based on results.
flowchart TB
GOAL["๐ฏ Goal"] --> PLANNER["๐บ๏ธ Planner"]
PLANNER --> GRAPH["๐ Task graph"]
GRAPH --> E1["โ๏ธ Executor A"]
GRAPH --> E2["โ๏ธ Executor B"]
E1 --> RES["๐ฆ Results"]
E2 --> RES
RES --> CHECK{"๐งช Still valid?"}
CHECK -->|yes| DONE["๐ Combine"]
CHECK -->|stale| PLANNER
- โ Better organization for long tasks
- โ Easier parallelization and progress tracking
- โ Specialized models for plan vs execute
- โ Per-step retry and approval
- โ ๏ธ Original plan goes stale
- โ ๏ธ Planning adds latency and tokens
- โ ๏ธ A bad plan poisons many downstream tasks
- โ ๏ธ Overkill for simple tasks
Strong implementations support incremental replanning โ patch the graph, do not regenerate it from scratch after every observation.
๐ช Reflection / self-correction
After a candidate answer or action, an evaluator scores it. The agent revises. Reflexion [4] stores those verbal critiques in an episodic buffer so later trials improve without weight updates โ linguistic RL.
flowchart TB
GEN["โ๏ธ Generate candidate"] --> EV["๐งช Evaluate vs rubric"]
EV --> OK{"โ
Pass?"}
OK -->|yes| STOP["๐ Accept"]
OK -->|no, under N| FIX["๐ช Critique + revise"]
FIX --> GEN
OK -->|budget hit| FAIL["๐จ Escalate / best-so-far"]
Reflection works when grounded in objective signals: tests, schema validation, policy rules, compilers, citations. Asking the same model to โcheck itselfโ with no external signal often reinforces the original mistake and burns tokens. Cap attempts. Prefer a cheaper/different evaluator than the generator when you can.
๐ช Goal decomposition
Turn a wish into a task spec before you turn it into steps:
- ๐ Desired final state
- ๐ง Constraints and permissions
- ๐ฅ Required inputs
- ๐ ๏ธ Available tools
- ๐ Dependencies
- โ Success criteria
- ๐จ Failure and escalation conditions
Subtasks should map to a tool or a verifiable operation โ โretrieve account status,โ โvalidate schemaโ โ not โinvestigate the problem.โ Represent complex work as a dependency graph, not only a linear checklist. After each step, update state and drop steps that are no longer necessary.
๐ณ Chain vs tree vs graph
How the model (or orchestrator) explores the plan:
| Shape | What it is | When |
|---|---|---|
| โ๏ธ Chain-of-thought [8] | One main path of intermediate reasoning | Mostly sequential, low branching |
| ๐ณ Tree-of-thought [3] | Generate candidate โthoughts,โ score, search (BFS/DFS), backtrack | Search problems, diagnosis, early choices that dead-end. Game of 24: CoT 4% vs ToT 74% on GPT-4 |
| ๐ธ๏ธ Graph planning | Shared deps, cycles, parallel branches, reusable intermediates | Software changes, research, multi-agent coordination, LangGraph-style state |
flowchart LR
subgraph COT["โ๏ธ Chain"]
C1["A"] --> C2["B"] --> C3["C"]
end
subgraph TOT["๐ณ Tree"]
T0["Start"] --> T1["A"]
T0 --> T2["B"]
T1 --> T3["A1"]
T1 --> T4["A2"]
end
subgraph GP["๐ธ๏ธ Graph"]
G1["Parse"] --> G2["Plan"]
G1 --> G3["Retrieve"]
G2 --> G4["Edit"]
G3 --> G4
G4 --> G2
end
Tree and graph search improve quality and explode cost. Use the simplest representation that meets the reliability bar. Store structured plans; do not stream raw private reasoning to users.
๐งฑ Workflow patterns โ stay on the ladder
Anthropicโs production catalog [1] is five composable workflows built on an augmented LLM (retrieval + tools + memory). These are not agents. Code still owns the path. Use them until you genuinely cannot hardcode the next step.
โ๏ธ Prompt chaining
Decompose into a fixed sequence. Output of call n is input to n+1. Put a programmatic gate (schema, regex, cheap classifier) between steps so a bad intermediate cannot poison the rest.
flowchart LR
IN["๐ฅ Input"] --> L1["๐ง Step 1"]
L1 --> GATE{"๐ช Gate"}
GATE -->|pass| L2["๐ง Step 2"]
GATE -->|fail| STOP["๐ Halt"]
L2 --> OUT["๐ค Output"]
WHERE. Outline โ (check outline) โ draft. Marketing copy โ translate. Each call is an easier task; you trade latency for accuracy.
๐ Routing
Classify the input, dispatch to a specialized prompt / tool set / model. Optimizing one category no longer hurts the others.
flowchart TB
IN["๐ฅ Request"] --> R["๐งญ Router"]
R --> B["๐ฌ Billing worker"]
R --> T["๐ง Tech worker"]
R --> G["๐ค General worker"]
WHERE. Support intents. Easy questions โ small model; hard ones โ large model. A router is a classifier; a manager (later) also plans and aggregates.
โก Parallelization
Two flavors:
- โ๏ธ Sectioning โ independent subtasks at the same time (speed + focused attention)
- ๐ณ๏ธ Voting โ same task, many attempts, aggregate (confidence)
flowchart TB
IN["๐ฅ Task"] --> W1["๐ง Worker 1"]
IN --> W2["๐ง Worker 2"]
IN --> W3["๐ง Worker 3"]
W1 --> AGG["๐งฉ Aggregate / vote"]
W2 --> AGG
W3 --> AGG
AGG --> OUT["๐ค Result"]
WHERE. Guardrail model in parallel with the answer model. Vulnerability review with several prompts. Evals that score different dimensions separately.
๐ท Orchestratorโworkers
A central LLM dynamically breaks the task, delegates, synthesizes. Topologically similar to parallelization; the difference is flexibility โ subtasks are not hardcoded [1].
flowchart TB
GOAL["๐ฏ Goal"] --> ORCH["๐ท Orchestrator"]
ORCH --> W1["โ๏ธ Worker A"]
ORCH --> W2["โ๏ธ Worker B"]
ORCH --> W3["โ๏ธ Worker C"]
W1 --> SYN["๐งฉ Synthesize"]
W2 --> SYN
W3 --> SYN
WHERE. Multi-file code edits. Research across unknown sources. This is the closest workflow to a true agent โ still wrap it in budgets and structured returns.
๐ช Evaluatorโoptimizer
Generator writes; evaluator critiques; loop until the rubric passes or the budget dies. Same shape as Reflection, but the path is a workflow you designed, not an open-ended ReAct wander.
Two signs of fit [1]: (1) human feedback would demonstrably improve the output; (2) an LLM can provide that feedback. Literary translation, iterative search, code that has tests.
๐ง Tool use, MCP, and trust
Treat the modelโs function call as an untrusted request, not an authorized command.
-
1
๐ง Model proposes untrusted function call โ not a command
-
2
๐ Typed schema allowlisted tools + JSON Schema only
-
3
โ Validate / normalize reject malformed or out-of-range args
-
4
๐ AuthN + AuthZ user identity and resource ACL, independently
-
5
๐ Least privilege scoped credentials, not the modelโs wishlist
-
6
โ ๏ธ Sensitive? payments, deletes, messages, infra, regulated calls
yes โ ๐ Human approve โ bind to this exact action; expire if state drifts
no โ continue
-
7
๐ฆ Sandbox execute isolated runtime, timeouts, idempotency keys
-
8
๐งน Sanitize result strip secrets and hostile instructions before the model sees them
-
9
๐ Trace log request, policy decision, and outcome
Also: allowlists, idempotency keys, timeouts, rate limits, output-size caps, and protection against SSRF, SQL injection, path traversal, and command injection. Expose high-level parameterized tools (โrefund orderโ) rather than arbitrary shells or SQL.
๐ Model Context Protocol
MCP [5] is an open JSON-RPC protocol for connecting LLM apps to external context. Three roles:
- ๐ Host โ the app the user sees (IDE, desktop, your agent)
- ๐ Client โ connector inside the host, 1:1 with a server
- ๐ฅ๏ธ Server โ exposes capabilities
Servers offer:
- ๐ ๏ธ Tools โ model-controlled functions with JSON Schema (side effects allowed)
- ๐ Resources โ application-controlled, mostly read-only context (files, schemas, docs)
- ๐ Prompts โ user-controlled templates for a domain workflow
flowchart LR U["๐ค User"] --> HOST["๐ Host / agent"] HOST --> C1["๐ Client"] HOST --> C2["๐ Client"] C1 --> S1["๐ฅ๏ธ MCP server
tools + resources"] C2 --> S2["๐ฅ๏ธ MCP server
prompts + data"]
MCP standardizes discovery and message exchange. It does not make tools safe. Auth, consent, sandboxing, and trust policy still live in the host and server. A random MCP server is a supply-chain decision.
๐ธ๏ธ Frameworks and state
Frameworks (LangChain, LangGraph, CrewAI, AutoGen/AG2, OpenAI Agents SDK, Claude Agent SDK) are accelerators. They are also abstraction traps [1]. Start with the API. If you use a framework, you should be able to draw the underlying calls.
- ๐ LangChain โ models, prompts, tools, retrievers, message history. Fine for pipelines. Do not hide business state, permissions, or checkpoints inside a memory abstraction you cannot inspect.
- ๐ธ๏ธ LangGraph [9] โ stateful graph (Pregel-style), not a DAG. Nodes read and update a typed state. Edges can be conditional. Cycles are the point: ReAct, retries, HITL pauses. Checkpointers snapshot state each super-step โ resume, time-travel, crash recovery. Requires recursion limits, reducers, and terminal states.
- ๐ฅ CrewAI / AutoGen โ role-playing multi-agent: sequential handoffs, manager delegation, group chat. Benefit is specialization. Risks: duplicated work, context loss, cost, undebuggable transcripts.
- ๐ฆ OpenAI Agents SDK โ hosted loop with handoffs, guardrails, tracing. Convenient on-rails; still version the whole config, not just the model.
flowchart LR
subgraph DAG["โก๏ธ DAG / chain"]
D1["A"] --> D2["B"] --> D3["C"]
end
subgraph LG["๐ Stateful graph"]
L1["Reason"] --> L2["Tool"]
L2 --> L3["Update state"]
L3 --> L1
L3 --> L4["HITL"]
L4 --> L1
end
A DAG assumes an acyclic, predetermined sequence. An agent graph revisits nodes based on updated state. That flexibility is why you need explicit stop conditions โ an agent that can always return โneeds more investigationโ will.
๐ฅ Multi-agent systems
Add a second agent only when roles are clearly separable or work is independently parallelizable. Otherwise you bought a meeting.
๐ Managerโworker vs ๐ routerโworker
- ๐ Router โ classify, send to one specialist. Light.
- ๐ Manager โ plan, delegate, dependency management, retries, aggregation, conflict resolution. Heavy.
Workers should receive minimal, task-specific context and return structured payloads: result, evidence, uncertainty, errors, recommended next action. The manager validates workers; it does not automatically trust them.
flowchart TB
U["๐ค Goal"] --> M["๐ Manager"]
M --> W1["๐ฌ Research"]
M --> W2["๐ป Coder"]
M --> W3["๐งช Reviewer"]
W1 -->|"structured result"| M
W2 -->|"structured result"| M
W3 -->|"structured result"| M
M --> F["๐ Final"]
๐จ Safe handoffs
Prefer structured messages over dumping the full transcript. A handoff should contain:
- ๐ Task ID and parent goal
- ๐ฏ Exact subtask
- ๐ Necessary facts only
- ๐ ๏ธ Allowed tools and resources
- ๐ท๏ธ Data sensitivity labels
- ๐ Expected output schema
- โฑ๏ธ Deadline / resource budget
- โ Completion criteria
Redact secrets; pass access-controlled IDs. Authorize each receiving agent independently. Version shared state with provenance โ which agent produced this fact, from which source.
โพ๏ธ Loops and circular handoffs
Enforce at the orchestrator, not in the prompt:
- ๐ข Max turns and handoff depth
- ๐ Per-agent retry limits
- โฑ๏ธ Global time and token budgets
- ๐ฃ Visited-state / handoff history
- ๐งฌ Duplicate-task detection (hash normalized task + state)
- ๐ Progress metrics that must move
- ๐ Explicit terminal states
- ๐ Escalate after repeated failure
๐ Skills
A skill is a packaged capability: instructions, tool defs, examples, validators, domain knowledge. Do not stuff every tool into the system prompt. Load on demand:
- ๐งญ Classify intent
- ๐ Search a skill registry (metadata / embeddings)
- ๐ Filter by user and tenant permissions
- ๐ฅ Load instructions + tools
- ๐ฆ Execute in a restricted environment
- โ Validate output
- ๐ Record skill version in the trace
Skills should be trusted/signed, versioned, tested, and permission-scoped. A skill file is prompt injection with a README if you load it from the open internet.
๐งช โDeterministicโ multi-agent tests
The LLM is probabilistic. Make the contract around it deterministic:
- ๐ Fixed state schemas and tool interfaces
- ๐ก๏ธ Low temperature where routing matters
- ๐ Pinned model, prompt, tool, and skill versions
- ๐ญ Mocked tools and replayable fixtures
- ๐ฑ Seeded execution where the API allows
- ๐ Explicit routing and stopping policies
- ๐ฅ Golden scenarios + property / invariant tests
- ๐ Trace comparison and repeated-run stability
Measure separately: task correctness, route consistency, tool selection, argument accuracy, steps, cost, latency, policy compliance. Goal is controlled variability, not pretending the whole system is a pure function.
๐ง Memory, state, and context
Two memories, one trap:
- ๐งพ Working memory โ this run: goal, recent messages, plan, tool results, pending calls. Lives in the prompt and/or a workflow state store. Precise and temporary.
- ๐ Long-term semantic memory โ cross-session facts, preferences, prior decisions. External store, retrieved when relevant. Selectively written, permission-aware, provenance-tracked, revisable.
flowchart TB RUN["โถ๏ธ Agent run"] --> WM["๐งพ Working memory
prompt + state store"] RUN --> RET["๐ Retrieve"] LTM["๐ Long-term store
profile / vectors / facts"] --> RET RET --> WM RUN --> WRITE["โ๏ธ Validated write"] WRITE --> LTM
๐งฎ Context budget
Assign tokens to buckets before the model sees anything:
- ๐ System and policy (pinned โ compaction cannot drop these)
- ๐ฏ Current user request
- ๐ฌ Recent interactions
- ๐บ๏ธ Active plan and state
- ๐ Retrieved evidence
- ๐ ๏ธ Tool results
- ๐ค Reserved output space
When you approach the limit: drop redundant tool output, replace older turns with structured summaries, persist large artifacts externally and pass references. Limit retrieval count and chunk size before data hits the model.
๐๏ธ Compaction and chunking
Chunk by semantic unit (turns, topics, tasks, documents, time), not arbitrary character counts. Overlap a little so references survive boundaries.
Compaction replaces old raw content with a structured summary: confirmed facts, preferences, decisions + rationale, open questions, completed actions, identifiers, source refs. Hierarchical: recent turns stay detailed; older sessions become task summaries; ancient history becomes durable facts. Keep links to originals when auditability matters. Compaction is lossy on purpose โ be honest about it.
๐ The agent that never forgets
Permanent memory is not a feature; it is a liability portfolio:
- ๐ Sensitive or stale data retention
- ๐ช Cross-user / cross-tenant leakage
- โ๏ธ Privacy and deletion compliance (right to be forgotten)
- โ ๏ธ Memory poisoning via malicious inputs
- ๐ Irrelevant retrieval, slower vector search
- ๐ธ Larger prompts, higher cost
- ๐ง Personalization on outdated facts
Need: retention policies, user controls, tenant isolation, encryption, access logs, expiration, deletion, relevance thresholds. More memory โ better agent.
โ๏ธ Retrieval conflicts
Rank by recency, source authority, confidence, and scope. Current explicit user instructions normally override inferred historical preferences. Verified records may override an unsupported claim when the fact matters. Keep value and provenance โ do not silently overwrite. For high-impact clashes, ask:
โYour current request says X; the saved config says Y. Which should I use?โ
Memory is evidence, not truth.
๐ค Safe personalization across stateless sessions
Keep the model call stateless. Store the profile externally, user-scoped. Inject only relevant authorized fields. Controls: strong identity, consent, field-level ACL, encryption, minimization, expiration, user review + deletion, provenance timestamps, separation of preferences vs sensitive records. The model must not decide which userโs memory to load.
๐ฆ Memorization of undesirable behavior
If a bad action, unsafe workaround, or injected โpolicyโ gets written to memory, retrieval will teach the next run to repeat it. Example: a user convinces the agent that approval is unnecessary; that sentence is stored as procedure; later sessions skip HITL.
Mitigations: never learn security rules from conversation; separate user facts from immutable system policy; validate memory writes; trust + provenance scores; expire low-confidence memories; review high-impact procedural memories.
๐พ State store and vectors
Durable transactional store as source of truth. Each run is a state machine: run ID, version, current node, completed / pending actions, tool results, approvals, retries, timestamps. Want: atomic transitions, optimistic concurrency, idempotency keys, checkpoint after material steps, replication, queues with DLQ, worker leases, recover from latest checkpoint, audit log. Side effects via outbox so state and the real world cannot diverge.
For vectors: stable ID + version + timestamp + source on every record. Write the primary row first; embed asynchronously. Readers filter by active version. Dedup with content hashes and novelty thresholds โ long-running agents otherwise embed the same observation forever, inflating index size, latency, and prompt tokens.
๐ญ LLMOps for agents
Classic MLOps versions datasets, training jobs, and model artifacts [10]. LLMOps versions the behavior-producing system:
- ๐ง Foundation model + provider version
- ๐ System prompt
- ๐ ๏ธ Tools and schemas
- ๐ Retrieval / memory config
- ๐ธ๏ธ Agent graph
- ๐ก๏ธ Guardrails and evaluators
- ๐ Knowledge sources
The weights can sit still while a tool description change wrecks production. Treat the whole bundle as one release manifest.
๐ Human-in-the-loop
Pause before irreversible, expensive, sensitive, or low-confidence actions: external messages, payments, deletes, infra changes, regulated decisions.
flowchart LR
A["๐ ๏ธ Proposed action"] --> CP["๐พ Checkpoint"]
CP --> UI["๐ Approval UI"]
UI -->|approve, unexpired| X["โถ๏ธ Execute"]
UI -->|deny| ALT["โฉ๏ธ Replan"]
UI -->|state drifted| RE["๐ Re-request"]
The screen shows: proposed action, exact target, arguments, evidence, expected impact, risk, alternatives. Bind the approval to the exact action; expire it if state changed so an old yes cannot authorize a mutated call.
โ ๏ธ Prompt injection
OWASP still ranks prompt injection as LLM01 [6]. Retrieved pages, emails, PDFs, images, and tool outputs may contain hostile instructions. For agents this is not a parlor trick โ it is confused-deputy with tools.
- ๐งฑ Separate trusted instructions from untrusted content; label origin and trust
- ๐ซ Never treat retrieved text as system policy
- ๐ ๏ธ Least-privilege tools for the current task
- ๐ก๏ธ External policy checks on every action
- ๐ HITL for high-risk ops
- ๐ Do not put secrets in the prompt
- ๐ Restrict network and filesystem
- ๐งน Sanitize tool output; test with adversarial content
Content can inform an answer. Content cannot grant itself permissions.
๐ฃ Destructive actions
Defense in depth, not a polite system prompt:
- ๐ Read-only DB credentials by default
- ๐งฉ Parameterized tools, not arbitrary SQL
- โ Allowlisted statements and tables; AST-parse SQL; reject DDL
- ๐ HITL for authorized destruction
- ๐งช Transactions, dry-run previews, row and time limits
- ๐พ Backups and audit logs
๐ธ Cost of the loop
Optimize at the workflow, measure cost per successful task (a cheap model that retries forever is expensive):
- ๐งญ Route simple work to small models; large models for hard planning / validation
- ๐๏ธ Compact context; retrieve fewer, better chunks
- ๐พ Cache stable prompts, embeddings, tool results
- โก Parallelize independent steps
- ๐ Structured tool outputs (less prose to re-ingest)
- ๐ Stop when marginal gain is flat; cap reflection
- ๐งฑ Replace LLM decisions with rules where you can
๐ก Tracing
One trace ID per user request. Every model call, retrieval, tool call, handoff, state transition, approval, and error is a child span (LangSmith, OpenTelemetry, your tracer). Record: model/prompt versions, sanitized I/O, tool name + validated args, latency, tokens, cost, retrieved IDs, routing decisions, retries, policy decisions, outcome, user feedback. Redact before log. Dashboards: success, latency, cost, loop rate, tool failures, escalations, policy violations.
๐ก๏ธ Layered guardrails
flowchart TB IN["๐ฅ Input checks"] --> PLAN["๐บ๏ธ Plan checks"] PLAN --> TOOL["๐ ๏ธ Tool checks"] TOOL --> OUT["๐ค Output checks"] OUT --> POST["๐ Post-action checks"] POST --> RUN["โฑ๏ธ Runtime
budgets / kill switch"]
Prefer deterministic validators when the rule is code-shaped. Model-based judges are for semantic quality โ calibrate them, version them, and never let a judge be the only lock on a high-risk action.
๐บ Streaming UI
Separate user-visible events from internal tokens. Publish structured events: accepted, planning, searching, tool running, waiting for approval, partial answer, retrying, done/failed. Stream safe response text; show concise tool status. Do not stream private reasoning or unvalidated tool dumps. Support cancel, reconnectable streams, ordered event IDs, backpressure, resumable state.
๐ฆ Versioning, rollback, A/B
Ship a manifest, canary it, keep the previous bundle deployable. Pin in-flight runs to the version they started on. For A/B: assign users or stable sessions so a conversation does not switch mid-thread; change one major factor at a time; pre-register metrics (completion, accuracy, corrections, tool success, steps, latency, cost per success, escalations, safety, satisfaction). Stratify by task difficulty โ a win on easy tickets can hide a regression on hard ones. Sequence: replay โ shadow โ limited live โ rollback thresholds. Same traffic-strategy instincts as model serving [10].
๐ช My 2 cents
Stop asking โshould we use agents?โ Ask the questions that force an architecture:
- ๐ Can I write the steps as a DAG today?
- ๐ฅ What is the blast radius of a wrong tool call?
- ๐งช How do I know the task is done โ test, schema, human?
- ๐ธ What is the token budget per successful outcome?
- ๐ Who approves irreversible actions?
Answer those and the pattern almost picks itself:
- ๐ฌ Single call + RAG when the path is a paragraph
- ๐งฑ Workflow when the path is a recipe
- ๐ค Agent when the path is unknown and the environment gives ground truth
- ๐ฅ Multi-agent only when roles are separable
- ๐ก๏ธ Permission envelope outside the model โ always
Contracts that are non-optional:
- ๐๏ธ Orchestrator-enforced budgets, not prompt manners
- ๐ Skills over god-prompts
- ๐ Memory is evidence, never policy
- ๐ฆ Version the whole agent config, not the weights alone
- ๐ก Traces you can replay; evals you can fail a release on
๐ฑ Treat agentic AI as something you design โ a control loop with a kill switch โ not a prompt you hope stays on the rails.
๐ References
- Erik S. and Barry Zhang, โBuilding effective agents,โ Anthropic Engineering, anthropic.com/engineering/building-effective-agents
- Shunyu Yao et al., โReAct: Synergizing Reasoning and Acting in Language Models,โ ICLR 2023, arxiv.org/abs/2210.03629
- Shunyu Yao et al., โTree of Thoughts: Deliberate Problem Solving with Large Language Models,โ NeurIPS 2023, arxiv.org/abs/2305.10601
- Noah Shinn et al., โReflexion: Language Agents with Verbal Reinforcement Learning,โ NeurIPS 2023, arxiv.org/abs/2303.11366
- Model Context Protocol, specification, modelcontextprotocol.io
- OWASP GenAI Security Project, โLLM01: Prompt Injection,โ genai.owasp.org/llmrisk/llm01-prompt-injection
- Stuart Russell and Peter Norvig, Artificial Intelligence: A Modern Approach, aima.cs.berkeley.edu
- Jason Wei et al., โChain-of-Thought Prompting Elicits Reasoning in Large Language Models,โ NeurIPS 2022, arxiv.org/abs/2201.11903
- LangChain, โLangGraph checkpointers,โ docs.langchain.com/โฆ/langgraph/checkpointers
- Amirhessam Tahmassebi, โMLOps Deployment Strategies,โ 2-Cents, two-cents/mlops-deployment-strategies.html
- LangChain, LangSmith tracing, docs.smith.langchain.com
- OpenAI, Agents SDK, openai.github.io/openai-agents-python
- CrewAI, documentation, docs.crewai.com
- AG2 (AutoGen), ag2.ai
- OWASP, โTop 10 for Large Language Model Applications,โ owasp.org/www-project-top-10-for-large-language-model-applications