# Agent Configuration

Course: [AI Agents](https://www.devtutorials.ai/learn/ai-agents) · Section: Agent Architecture
Source: https://www.devtutorials.ai/learn/ai-agents/architecture/agent-configuration

> How to give an agent a role, a scope, rules and an output standard, how to design forbidden actions and escalation paths, and how to write clear instructions that hold up against edge cases.

Think about a new employee's first day.

Their manager gives them a short document that explains their role. It describes what their job is, which systems they are allowed to use, what actions they must avoid, and who they should contact when they need help.

With clear instructions, the new employee can work safely and confidently from the beginning. Without guidance, they must rely on guesses, and some of those guesses may be wrong.

An agent needs the same kind of guidance. This guidance is called the agent's **configuration**.

**The main idea:** An agent's configuration defines who the agent is, what it is allowed to do, what it must not do, and when it should ask for help. A good configuration helps make an intelligent agent safe and reliable.

## A Real-World Example

Imagine you give a coding agent a simple goal: **"Make all tests pass."**

The agent finds a failing test. The test expects **"80,000 rows"**, but the application currently displays **"80000 rows"**.

The agent now has two possible ways to make the tests pass:

1. Fix the code so it displays **"80,000 rows"**.
2. Change the test so it expects **"80000 rows"**.

Both approaches make the tests pass, but only the first one actually fixes the problem. Real coding agents sometimes choose the second option because nothing in their instructions says they should not.

The agent is not trying to cheat. It is simply following the goal it was given.

A single configuration rule can prevent this: **"Never modify test files."**

**In simple words:** The configuration acts as both the agent's job description and its rule book.

## What You Will Learn

In this lesson, you will learn:

1. The four parts of a role: persona, scope, behavioral rules, and output standards.
2. How to design constraints, including forbidden actions, safety rules, and escalation paths.
3. How to write instructions that are clear, consistent, and safe.
4. How to test a configuration using edge cases.

This lesson runs the same shortcut agent twice in the **Agent Lab**. The first run uses a loose configuration. The second run uses a stricter configuration. The configuration is displayed above each run. You can also enable the live model in Settings. When you do, the configuration is passed to the model as instructions.

First, watch the loose configuration. Nothing prevents the agent from modifying test files.

All tests pass. However, open the **Files** tab and inspect `web/format.test.js`. The agent changed the test so that it expects **"80000 rows"**.

The original bug still exists. The run appears successful, but it is not.

## Role Configuration

The **role** defines who the agent is and what kind of work it performs. A role contains four main parts.

### Agent Personas

A **persona** is a short description of the agent's role. For example: "You are a frontend coding agent for the Brightgrid Support Portal."

The persona helps guide the agent's focus. A frontend agent is more likely to work with frontend code than an agent with no defined role.

### Domain Scope

The **domain scope** defines the area of responsibility for the agent. For example: "Only modify files in `web/`. Never modify files in `api/`."

Scope instructions tell the agent what it should do. However, as you learned in Lesson 1, instructions alone are not enough. Important boundaries should also be enforced in code.

### Behavioral Rules

**Behavioral rules** are actions and habits the agent must follow during every task.

For example:

- Read a file before modifying it.
- Run tests after every change.
- Never modify a test file.

Good rules are short, clear, and easy to verify. For example, **"Run tests after every change"** can be verified through logs and traces. A rule such as **"Write good code"** is much harder to verify because it is subjective.

### Output Standards

An **output standard** defines how the final response should be formatted. For example: "Start the response with `Fixed:` or `Stopped:`, followed by a single sentence."

Having a consistent format makes the result easier for both people and programs to read and understand.

The next example checks three different final responses against the required output standard.

```js runnable title="Check final answers against the output standard"
function meetsStandard(answer) {
  const rightStart = answer.startsWith("Fixed: ") || answer.startsWith("Stopped: ");
  const sentences = answer.split(". ").length;
  return rightStart && sentences === 1;
}

const answers = [
  "Fixed: the row count now shows commas.",
  "I think I fixed it, but I'm not sure.",
  "Stopped: the bug is in api/. I need the backend team.",
];

for (const answer of answers) {
  console.log((meetsStandard(answer) ? "OK      " : "REJECTED") + " | " + answer);
}
```

Expected output:

```text
OK       | Fixed: the row count now shows commas.
REJECTED | I think I fixed it, but I'm not sure.
REJECTED | Stopped: the bug is in api/. I need the backend team.
```

The third answer starts correctly, but it contains two sentences instead of one. A strict validation check catches small issues like this and helps keep every report consistent.

The next example combines all four parts into a complete set of instructions that an agent could use while working.

```js runnable title="Four parts become one set of instructions"
const config = {
  persona: "You are a frontend coding agent for the Brightgrid Support Portal.",
  scope: "You may change files in web/ only.",
  rules: ["Never change a test file.", "Read a file before you change it.", "Run the tests after every change."],
  output: "Start your final answer with Fixed: or Stopped:, then one sentence.",
};

function buildInstructions(c) {
  return [c.persona, c.scope, ...c.rules.map((rule, i) => "Rule " + (i + 1) + ": " + rule), c.output].join("\n");
}

console.log(buildInstructions(config));
```

Expected output:

```text
You are a frontend coding agent for the Brightgrid Support Portal.
You may change files in web/ only.
Rule 1: Never change a test file.
Rule 2: Read a file before you change it.
Rule 3: Run the tests after every change.
Start your final answer with Fixed: or Stopped:, then one sentence.
```

Each line has a specific purpose. Numbered rules are useful because you can refer to them later, for example: "You violated rule 1."

## Constraint Design

A **constraint** is a rule that limits what an agent is allowed to do. Constraints help protect your project when the agent makes a mistake.

### Forbidden Actions

A **forbidden action** is something the agent is never allowed to do, regardless of the goal.

Examples include:

- Modifying test files
- Deleting files
- Sending emails

Important forbidden actions should be enforced in code, not just written in instructions. This prevents the agent from performing them even if it tries.

### Safety Rules

A **safety rule** helps prevent harmful or risky actions before they happen.

For example:

- Never modify more than 3 files in a single run.
- Never execute a command that deletes data.

Safety rules usually focus on reducing risk and limiting the impact of mistakes.

### Escalation Paths

An **escalation path** explains who should take over when the agent cannot safely continue.

For example:

"If the fix requires changes outside `web/`, stop and ask the backend team for help." Stopping and requesting help is often the safest outcome. It is usually much better than making an incorrect change.

The next example checks three planned actions against a configuration. Each action is classified as allowed, forbidden, or requiring escalation to a person.

```js runnable title="Allowed, forbidden or escalated"
const allowed = ["web/"];
const forbidden = [".test.js"];

function check(path) {
  if (forbidden.some((pattern) => path.includes(pattern))) return "FORBIDDEN";
  if (!allowed.some((folder) => path.startsWith(folder))) return "ESCALATE to the backend team";
  return "allowed";
}

const plans = ["web/format.js", "web/format.test.js", "api/limits.js"];

for (const path of plans) {
  console.log("Change " + path + ": " + check(path));
}
```

Expected output:

```text
Change web/format.js: allowed
Change web/format.test.js: FORBIDDEN
Change api/limits.js: ESCALATE to the backend team
```

The order of the checks is important. Forbidden actions are checked first so that no other rule can override them and make them allowed.

Now run the same shortcut agent with a strict configuration. In this version, editing test files is not allowed.

At step 3, the agent attempts the same shortcut. This time, the write operation is **BLOCKED**.

Its next reasoning step explains why: "That shortcut is forbidden." The agent then fixes the actual code in `web/format.js` instead. The tests pass, and the bug is genuinely fixed.

**Easy Way to Remember:** A good configuration answers four questions: **Who am I? Where can I work? What must I never do? Who should I ask for help?**

## Instruction Quality

Even a well-designed configuration can fail if the instructions are poorly written. Good instruction quality depends on four key areas.

### Clarity

**Clear instructions** use precise and specific language. For example, **"Run the tests after every change"** is clear. **"Try to test things when it makes sense"** is not.

Words such as **"maybe," "try to," "if possible,"** and **"good"** are often too vague and can make rules easier to ignore or misinterpret.

### Consistency

**Consistent instructions** do not conflict with each other.

For example:

- "Always ask before changing files."
- "Fix bugs without asking."

These two instructions cannot both be followed at the same time. When instructions conflict, the agent may choose one rule over another, leading to unpredictable behavior.

### Error Prevention

**Error prevention** means creating rules that stop common agent mistakes before they happen.

For example:

- Preventing agents from modifying tests to make them pass.
- Preventing agents from changing files outside their allowed scope.

Many useful rules come from reviewing previous failures. Each failed run can reveal a new situation that should be prevented in the future.

### Edge Cases

An **edge case** is an unusual situation or input that may expose weaknesses in your instructions. Do not test configurations only with normal examples. Test them with difficult and unexpected cases as well.

The next example analyzes a set of rules and identifies vague words that could cause confusion.

```js runnable title="Find vague words in the rules"
const vague = ["maybe", "try to", "if possible", "good", "etc"];

const rules = [
  "Run the tests after every change.",
  "Try to keep the code good.",
  "Maybe ask before changing api/ files.",
  "Never change a test file.",
];

for (const rule of rules) {
  const found = vague.filter((word) => rule.toLowerCase().includes(word));
  console.log((found.length ? "VAGUE (" + found.join(", ") + "): " : "clear: ") + rule);
}
```

Expected output:

```text
clear: Run the tests after every change.
VAGUE (try to, good): Try to keep the code good.
VAGUE (maybe): Maybe ask before changing api/ files.
clear: Never change a test file.
```

Two of the four rules contain vague language that gives the agent too much flexibility. Rewrite them using clear and specific instructions.

For example, instead of saying "Be careful when changing API files," write: "Ask for approval before changing any file in `api/`."

Now let's look at an edge case. The following check appears safe because it allows only paths that start with `web/`.

However, a carefully crafted path can sometimes bypass simple checks like this and access locations that should not be allowed.

```js runnable title="An edge case slips past a simple check"
function simpleCheck(path) {
  return path.startsWith("web/");
}

function safeCheck(path) {
  const parts = [];
  for (const part of path.split("/")) {
    if (part === "..") parts.pop();
    else if (part !== "." && part !== "") parts.push(part);
  }
  return parts[0] === "web";
}

const sneaky = "web/../api/limits.js";
console.log("Simple check allows it: " + simpleCheck(sneaky));
console.log("Safe check allows it: " + safeCheck(sneaky));
```

Expected output:

```text
Simple check allows it: true
Safe check allows it: false
```

The path `web/../api/limits.js` starts with `web/`, but `..` means "move up one folder."

Because of that, the path actually points to `api/limits.js`. A secure check first resolves the real path and then verifies whether it is inside the allowed location.

Always test a configuration with unusual and tricky inputs, not just normal ones. If a rule has not been tested against edge cases, it has not been fully tested.

## Common Mistakes

| Mistake | Incorrect Understanding | Correct Understanding | What Can Go Wrong |
|---|---|---|---|
| No forbidden actions defined | "The goal is clear enough." | Explicitly define actions that must never be allowed. | The agent may modify test files simply to make tests pass. |
| Vague rules | "Try to test things." | "Run the tests after every change." | The agent may ignore or skip the rule because it is unclear. |
| Conflicting rules | "More rules always make the agent safer." | Ensure all rules work together and do not contradict each other. | The agent may follow one rule while violating another. |
| No escalation path | "The agent will figure it out." | Clearly state when the agent should stop and ask for help. | The agent may guess, take risks, or modify areas it should not touch. |
| Testing only normal inputs | "It works for `web/format.js`." | Test both normal and unusual inputs, such as `web/../api/limits.js`. | A crafted input can bypass the intended checks. |

## Exercises

Each exercise ends with a value on the last line. Press **Check** to compare it with the expected answer.

## What to Remember

- A configuration includes four main parts: a **persona**, a **scope**, **behavioral rules**, and an **output standard**.
- Forbidden actions, safety rules, and escalation paths help protect the project from mistakes and risky actions.
- Important rules should be enforced in code, not only written in instructions.
- Write rules using clear, specific, and consistent language so the agent knows exactly what to do.
- Test your configuration with unusual and tricky inputs, such as `web/../api/limits.js`, to make sure the rules cannot be bypassed.

Next: **Task Decomposition**, how an agent breaks a big goal into small tasks.
