Module 1 · Foundations of agents & security
What is an autonomous agent
An autonomous agent is a program that repeatedly perceives its environment, decides what to do next, and acts on that environment through tools — closing a loop and pursuing a goal over time, rather than running a fixed sequence once.
Learning objective
Define an autonomous agent through the perception→decision→action loop, understand what autonomy, tools and environment mean operationally, and draw a clear line between an agent, a plain script and a single LLM call.
- Track
- Fundamentals
- Module
- 1 · Foundations of agents & security
- Prerequisites
- None
Conceptual introduction
The word "agent" is overloaded, so start from behaviour, not hype. An autonomous agent is a system that sits inside an environment, observes it, chooses an action aimed at a goal, performs that action, observes the result, and repeats. The defining feature is the loop: the output of one action changes what the agent sees next, and that new observation feeds the next decision. A program that reads a fixed input, transforms it, and exits has no such feedback — it is a pipeline, not an agent.
This framing comes from a long tradition in artificial intelligence of describing a rational agent as something that perceives through sensors and acts through actuators to maximise some measure of success. In a software context the "sensors" are API responses, file reads and tool outputs; the "actuators" are the tools the agent is allowed to call. Keeping this concrete matters, because the security of the whole system follows from exactly what the agent can perceive and what it can do.
Autonomy is a matter of degree, not a yes/no flag. The useful question is never "is it autonomous?" but "which decisions does it make without a human, and over which actions?"
Technical foundation
Four elements are enough to describe any agent precisely. Fix them for a given system and you have fixed its capabilities and its attack surface.
- Environment
- Everything outside the agent that it can observe or change — files, APIs, databases, other agents, users. The agent never sees the environment directly, only observations of it.
- Perception
- How observations enter the agent: a tool result, a retrieved document, a user message, a sensor reading. Perception is where untrusted data enters the loop, which makes it the first place to think about trust.
- Decision (policy)
- The function that maps the current observation and internal state to a chosen action. It may be hand-written rules, a planner, an LLM, or a mix.
- Action (tools)
- The finite set of operations the agent can perform on the environment. Autonomy is bounded by this set: an agent cannot do what it has no tool for.
A fifth element is implicit: the goal. Without a goal the loop has no direction. The goal may be given once ("resolve this ticket"), standing ("keep the queue below 50"), or derived from a parent agent. How the goal is set, and who is allowed to set it, is itself a security question returned to in later modules.
The agent loop as a model
The control loop can be written as a small state machine. State carries memory across iterations; the policy maps (observation, state) to an action; the environment maps an action to the next observation. This schematic is deliberately agnostic about whether the policy is an LLM or a block of if-statements — that choice is the subject of the next lesson.
the perception→decision→action loop (schematic)state = initial_state(goal) while not done(state): observation = perceive(environment) # sensors / tool results action = policy(observation, state) # decision result = act(environment, action) # actuators / tools state = update(state, observation, result) done = stop_condition(state) # goal met, budget spent, halt # a plain script has no loop and no 'policy over observations': # result = transform(fixed_input); exit
Three knobs turn this from a toy into a real agent. The stop condition decides when the loop ends and must always terminate (a budget of steps, a cost cap, or a satisfied goal) or the agent can run forever. The update step is the agent's memory and determines what it can learn within a run. The action set determines its reach. Lock these three down and the agent is bounded; leave any of them open-ended and you have an unbounded process.
Step by step: one iteration
- 1Perceive: gather the current observation — a new user message, the result of the last tool call, a freshly retrieved document. Treat everything that entered from outside as untrusted data, not as instructions.
- 2Decide: the policy proposes an action given the observation, the goal and accumulated state. For an LLM policy this is a model call; for a rule policy it is a branch.
- 3Validate: before acting, check the proposed action against the allow-list of tools and the permissions attached to this run. This step is outside the policy, and the next lessons explain why it must be.
- 4Act: invoke the chosen tool. The tool, not the policy, is what actually touches the environment.
- 5Observe & update: record the result into state, append it to the audit trail, and re-evaluate the stop condition. Loop or halt.
Practical example (synthetic)
Consider a synthetic "inbox triage" agent whose goal is to label incoming support emails. Its environment is a mailbox and a label store; its tools are read_next_email, set_label(email_id, label) and escalate(email_id). One iteration: it perceives the next unread email, the policy decides the label is "billing", validation confirms set_label is on the allow-list, the agent acts by calling set_label, observes success, updates state (one more handled), and checks whether the inbox is empty.
synthetic — inbox triage, one iterationobs = read_next_email() # perceive (untrusted content) action = policy(obs, state) # decide -> set_label(id, "billing") assert action.tool in ALLOWED_TOOLS # validate (outside the policy) res = set_label(obs.id, "billing") # act state = remember(state, obs, res) # update memory + audit # contrast: a non-agent cron job would just run # for e in all_unread(): set_label(e.id, classify(e)) # no loop over its own results
The same classifier wrapped in a one-shot cron job is not an agent: it applies a fixed rule to every item and never reacts to what its own actions produced. Give the loop the ability to, say, escalate when it is unsure and then change its own next observation by doing so, and it becomes an agent — gaining usefulness and, simultaneously, the need for control.
Application to agents
This lesson is the vocabulary the rest of the track depends on. Every security concept that follows is a constraint on one of the four elements. Identity (Module 1, lesson 4) constrains perception, so an agent can tell who sent an observation. Authorization (lesson 5) constrains the action set per run. Trust boundaries (lesson 6) are the lines in the environment across which perception must not be believed blindly. Being able to say precisely where a risk lives — "this is a perception problem" versus "this is an action problem" — is what makes the later material tractable.
The distinction between an agent and a single LLM call is also practical, not pedantic. A single call maps a prompt to text and stops; it has no tools, no loop and no state, so it cannot act on the world or react to the result of acting. An agent is the loop built around such calls, plus the tools, plus the control that decides which calls get to become actions. Most of the risk — and most of the engineering — lives in that surrounding machinery, not in the model call itself.
Risks & limitations
- ▸An unbounded loop (no step budget, no cost cap, no terminating stop condition) can run away; every agent needs a guaranteed halt.
- ▸Perception is an untrusted channel: content fetched or returned by a tool can contain instructions aimed at the policy — never treat observed data as commands (the indirect prompt-injection problem).
- ▸The action set is the agent's true power ceiling. Granting a broad or open-ended tool (shell, arbitrary HTTP, send-money) hands the loop that reach; scope tools narrowly.
- ▸Autonomy without a clear goal and stop condition produces busy-work or drift; "more autonomy" is not a feature on its own.
- ▸Calling something an "agent" does not make it safe or capable. The guarantees come from the bounds on perception, decision, action and memory — not from the label.
Exercise
Take a tool you use that feels "automated" (a CI pipeline, an autoresponder, a scheduled report). Classify it: does it close a perception→decision→action loop over its own results, or is it a one-shot pipeline? Identify its environment, perception channel, action set and stop condition — and name the one change that would turn it into (or out of) an agent.
Expected direction: A correct answer identifies whether the system reacts to the outcome of its own actions (loop) or applies a fixed transform once (pipeline), names the four elements concretely, and shows that adding a feedback loop over results — or removing it — is the pivot between agent and script.
Check your understanding
- What single property most distinguishes an agent from a plain script?
- The closed loop: an agent reacts to the results of its own actions and feeds them into the next decision, whereas a script runs a fixed sequence once without reacting to its own output.
- Why is a single LLM call not an agent?
- It maps a prompt to text and stops — no tools, no loop, no state — so it cannot act on the environment or respond to the result of acting; the agent is the loop, tools and control built around such calls.
- What bounds an agent's power, and why does that matter for security?
- Its action set (tools): an agent can only do what it has a tool for, so scoping tools narrowly is the primary way to limit reach.
References
- [1]Russell & Norvig — Artificial Intelligence: A Modern Approach (rational agents: sensors, actuators, environment)
- [2]Wooldridge — An Introduction to MultiAgent Systems
References point to public, well-known technical sources for further study.
Related articles
