An agent is not a model with a personality. It is a loop around a model, context, tools, state and policies. Every extra capability increases the need for boundaries.
Work through the path
Open a card when you need it. Marking a lesson complete is optional and stays only in this browser.
1See the agent as a bounded loop
A typical agent loop repeatedly selects context, asks the model for the next action, validates a tool call, executes it and checks whether the task is complete.
Set a maximum number of turns, token budget, wall-clock deadline and allowed tools. Emit a trace for each model call and tool result.
If the task can be completed by one deterministic function, do not wrap it in an agent loop just because the interface is conversational.
Try it
Write the termination conditions for one proposed agent: turns, time, tokens, tools and human approval points.
for (var turn = 0; turn < 8; turn++)
{
var decision = await model.DecideAsync(state);
if (decision.Done) return decision.Answer;
var call = policy.Validate(decision.ToolCall);
state.Add(await tools.ExecuteAsync(call));
}
throw new TimeoutException("Agent budget exhausted");2Understand MCP hosts, clients and servers
MCP standardizes a connection between an AI application and external data, prompts or tools; the host still controls the user experience and policy.
Think of the host as the AI application, the client as its connector and the server as the component exposing resources, prompts or tools. The protocol does not make a server trustworthy by itself.
Review the tool description, input schema, transport and authorization before enabling it. Treat remote servers differently from a local read-only server.
Try it
Draw one MCP connection and mark where user approval, credentials and external side effects occur.
Host application
└─ MCP client
└─ MCP server
├─ resources
├─ prompts
└─ tools3Make permissions narrower than capabilities
Tool schemas describe what a call looks like; authorization decides whether this caller can perform it on this resource now.
Use separate read and write tools, resource-level authorization, allow-lists and explicit confirmation for destructive actions. Pass the user identity into the policy layer rather than asking the model to infer it.
Log the decision and outcome without storing secrets or unnecessary data.
Try it
Take one tool definition and write the denied cases: wrong user, wrong resource, malformed input, expired approval and repeated request.
policy.allow({
actor: currentUser,
tool: "delete_order",
resource: orderId,
requiresConfirmation: true
});4Choose memory by purpose and retention
Conversation history, user preferences, retrieved documents and durable business state are different data categories with different retention rules.
Store only what the product needs. A vector index is not automatically memory, and a chat transcript is not automatically a reliable source of truth.
Give users and operators a way to inspect, correct, delete or expire stored AI context when the data policy requires it.
Try it
Classify one proposed memory item as transient, user preference, retrieved evidence or system-of-record data.
Context layers: 1. Current request 2. Short conversation summary 3. Retrieved approved documents 4. Durable business state from the system of record Never let layer 2 overwrite layer 4.
5Evaluate workflows, not just final prose
An agent can produce a convincing final answer after taking the wrong actions, so evaluation must include tool selection, arguments, permissions, retries and side effects.
Create traces with expected tool calls and forbidden calls. Test timeouts, malformed tool results, prompt injection and partial failures.
Keep a human approval step for high-impact actions until the workflow has enough evidence and the business owner accepts the risk.
Try it
Replay a sanitized trace with a fake tool server and assert that unsafe calls are rejected before execution.
Expected trace: 1. read_order(orderId) 2. validate_policy(actor, orderId) 3. draft_email() 4. ask_for_approval() Forbidden: - delete_order without approval - export_customer_data
6What is an agent harness?
A beginner-friendly map of the system around a model: context, tools, permissions, execution, feedback and verification.
Harness is a useful developer term, not a universally standardized product category. In this path, use it for the system around a model that turns a response into a bounded workflow: it supplies context, exposes tools, enforces permissions, executes actions, feeds results back and helps verify the outcome.
Do not confuse the harness with the model. The model generates text or tool-call decisions; the harness decides what context and tools exist and whether an action can run. An orchestrator coordinates one or more workers, while a gateway routes model traffic. One product may contain more than one of these layers, so inspect the actual controls.
Coding CLIs and IDE agents are user-facing surfaces built on a harness. A good harness makes the request-to-diff-to-test path visible, keeps the repository boundary clear and lets a human stop or review the loop.
Try it
Take one agent you use and label its model, context source, tools, permission prompts, execution environment and verification step. If you cannot name one, treat it as an operational risk to investigate.
User request -> context: repo map, instructions, selected files -> model: plan or tool call -> policy: allow, deny or ask -> tool: read, edit, shell, test, MCP -> result: diff, output, errors -> verification: tests + human review Model = generates decisions Harness = supplies and controls the loop Orchestrator = coordinates workers Gateway = routes model traffic
No lesson matches that phrase.
Related tools
Turn the concept into a working example with the browser-based tools.