Company OAsAll ProblemsOA CalendarInterview ExperiencesPremium
OAHelper

Built by students, for students - practice company-specific OAs, DSA sheets, and real interview experiences to land your dream role.

© 2026 OAHelper.in·Terms·Privacy·Refunds·Trust & Safety·Contact·
Ready to crack your next OA?

Practice company-specific questions trusted by thousands of students across India.

Start PracticingGo Premium
OA Practice·DSA·Placements

Disclaimer: OAHelper is an independent educational platform. We (oahelper.in) do not own the images or questions shown. Content is uploaded by users.

Module 06

Executable Constraints

  • Why Models Fail
  • A Minimal Workbench
  • Executable Constraints
  • Repo Memory and State
  • Initialization Scripts
  • Scope Contracts
On this page

This week

  • Why Models Fail
  • A Minimal Workbench
  • Executable Constraints
  • Repo Memory and State
  • Initialization Scripts
  • Scope Contracts

In plain words

A hostel notice saying 'maintain discipline' changes nothing, but 'gate closes at 9:30' works, because someone can check it. Agent instructions are the same. Write each rule as a small function that returns pass or fail on what the agent actually did, sort them into five buckets, and let a checker score every run instead of you reading the whole log.

How it flows

  1. 1Write rule→
  2. 2Attach a check→
  3. 3Agent runs→
  4. 4Trace saved→
  5. 5Checker scores→
  6. 6Read report

A tiny example

Python
RULES = [
    ("tests-green", "done", "block", lambda t: t["exit_code"] == 0),
    ("no-deploy-edit", "forbidden", "block", lambda t: "deploy.sh" not in t["edited"]),
]

for name, category, severity, check in RULES:
    ok = check(trace)
    print(name, severity, "PASS" if ok else "FAIL")

Notice each rule is just data plus a function, so adding a rule means adding one checkable line, never a paragraph of prose.


What you will learn

  • Why "be careful" is a useless instruction for an agent, and what to write instead.
  • Five buckets that cover almost every rule you will ever need.
  • How to turn each rule into a small Python function that gives a pass or fail.
  • How to keep the rule file small so the agent actually reads it.

The problem, simply

Think about your hostel mess notice board. "Maintain discipline." "Keep the mess clean." "Be considerate." Nobody follows any of it, and nobody can say who broke which rule, because there is nothing to check.

Now think about the one rule that actually works: "Entry closes at 9:30 PM." It works because there is a gate, a clock, and a warden. It can be checked.

Instructions to an AI agent behave the same way. Most teams write a file that says "test thoroughly", "ask if unsure", "do not break things". Three days later the agent ships code with zero tests, edits the release script it was never supposed to touch, and never asks anything, because it never knew where the line was.

See, the problem is not that the agent disobeyed. The problem is that nobody drew a line it could see. A rule with no check is a wish. A rule with a check is a test.

The idea

Split your instructions into two kinds. Aspirational rules are the mess notice board: nice words, no check. Operational rules are the 9:30 gate: each one names a small function that returns pass or fail.

Only operational rules belong in your rule file. If a line cannot be checked, either upgrade it into something checkable or delete it.

Five categories

Almost every rule fits into one of five buckets. If a rule does not fit, it is usually two rules pretending to be one. Force the split.

CategoryThe question it answersExample
StartupWhat must be true before work begins?The state file exists and is fresh
ForbiddenWhat must never happen?Never edit the release script
Definition of doneWhat proves the task is finished?Tests exit with code 0
UncertaintyWhat to do when unsure?Write a question note, do not guess
ApprovalWhat needs a human yes?Any new dependency, any write to production

The flow

  1. 1Rules file→
  2. 2Agent runs→
  3. 3Trace saved→
  4. 4Checker scores→
  5. 5Report for reviewer

Humans author the rule file in plain markdown, one rule per heading. The agent works and leaves behind a trace of what it did. A checker reads that trace, runs every rule's check function, and produces a report. The reviewer reads the report, not the whole transcript.

A worked example

Suppose Priya is building an agent that fixes bugs in her college project repo. She writes four rules.

Rule one, startup: a file called state.json must exist before any work starts. Rule two, forbidden: never touch deploy.sh. Rule three, definition of done: the test command must exit 0. Rule four, approval: adding a new pip package needs her explicit yes.

The agent runs. It reads two files, edits deploy.sh because a stale comment looked wrong, runs the tests which fail, and installs a package on its own. The checker scores it: startup passed, the other three failed. Three failures, each pointing at one line, instead of Priya reading four hundred lines of chat log at 1 AM.

Severity, so not everything is an emergency

Give each rule a severity: block, warn, or info. The checker reports all three. The runtime only refuses to continue on block.

Do this while writing the rule, not later. Teams tend to mark everything as block on day one, then quietly weaken things when a deadline hits. Choosing at write time forces you to actually think about which lines are real.

Warning

Warning: A rule marked block that gets overridden five times a week is not a rule. It is friction. Either fix the rule or downgrade it honestly.

Keep the file a map, not an encyclopedia

Here is the trap. Every incident adds a rule; no incident removes one. A year later your file is two thousand lines, the agent reads the first screen, runs out of attention, and acts on a fraction of what you told it.

The fix is not a shorter file. It is a layered one.

  1. 1Router file→
  2. 2Rules file→
  3. 3Topic doc→
  4. 4Agent acts

Keep the root file tiny, under about fifty lines: what the repo is, paths to the deeper files, and the few hard rules. The rule set lives in its own file, roughly one screen per category. Deep notes like testing or deployment sit in separate files the agent opens only when the task touches them.

Two small tests keep this honest. The agent should reach any rule in at most two hops from the root file, so the root must link paths, not describe things in prose. And the root must stay short enough that a reviewer rereads it on every pull request, which is the only thing stopping it from growing back.

A broken path in the root file is worse than a missing rule, so treat it as a startup failure.

Expiry, so dead rules die

Give each rule an expiry date; ninety days is a fine default. If a rule has not fired even once in that window, it comes up for review: justify it, weaken it to info, or delete it. One large study of automated code reviews found rule sets with expiry stayed around thirty rules, while sets without grew past eighty, most never firing.

IMPRemember: a rule nobody can check, and a rule nobody has ever triggered, are both noise. Noise is what makes the agent skip the rules that matter.

Rules versus runtime guardrails

You will hear the word guardrails in interviews. Guardrails are runtime checks a framework fires during a turn to stop a bad action. The OpenAI Agents SDK lets you register input and output guardrails, and LangGraph, a library for building agent workflows as graphs, has interrupts that pause a run mid-way and ask a human.

They are not competitors to your rule file. The guardrail catches the violation live; the rule file is the human-readable contract those guardrails implement, and it proves the runtime is checking the right things. You want both.

Tip

Tip: Keep the markdown as the source of truth and generate a JSON copy for the checker to read fast. Regenerate it in a pre-commit hook. Same idea as a package file and its lock file: humans review the readable one, machines load the fast one.

Build it

Python
"""A tiny rule checker. Rules are data; each check is a function."""

# A run trace: what the agent actually did. Normally your workbench writes this.
TRACE = {
    "state_file_present": True,
    "files_edited": ["src/parser.py", "deploy.sh"],
    "test_exit_code": 1,
    "packages_added": ["requests"],
    "approvals": [],
}

# --- one check function per rule -------------------------------------------

def check_state_file(trace):
    return trace["state_file_present"], "state file missing before work started"

def check_forbidden_paths(trace):
    banned = {"deploy.sh", "scripts/release.sh"}
    hits = [f for f in trace["files_edited"] if f in banned]
    return not hits, "edited forbidden file(s): " + ", ".join(hits)

def check_tests_pass(trace):
    return trace["test_exit_code"] == 0, "tests exited with %d" % trace["test_exit_code"]

def check_new_deps_approved(trace):
    missing = [p for p in trace["packages_added"] if p not in trace["approvals"]]
    return not missing, "unapproved package(s): " + ", ".join(missing)

# --- the rule set: name, category, severity, and the check to run ----------

RULES = [
    ("state-fresh",    "startup",   "block", check_state_file),
    ("no-deploy-edit", "forbidden", "block", check_forbidden_paths),
    ("tests-green",    "done",      "block", check_tests_pass),
    ("deps-approved",  "approval",  "warn",  check_new_deps_approved),
]

def run_checks(rules, trace):
    report = []
    for name, category, severity, check in rules:
        ok, why = check(trace)
        report.append({"rule": name, "category": category,
                       "severity": severity, "passed": ok,
                       "reason": "" if ok else why})
    return report

if __name__ == "__main__":
    report = run_checks(RULES, TRACE)
    blocked = 0
    for row in report:
        mark = "PASS" if row["passed"] else "FAIL"
        print("[%s] %-14s %-10s %s" % (mark, row["rule"], row["severity"], row["reason"]))
        if not row["passed"] and row["severity"] == "block":
            blocked += 1
    print("\n%d of %d rules passed." % (sum(r["passed"] for r in report), len(report)))
    print("Run is %s." % ("REFUSED (block-level failure)" if blocked else "allowed"))

Look at two things. Every failing line names the broken rule and the reason, with no log reading. And the unapproved package is only warn, so it appears in the report without refusing the run, while the forbidden edit and failing tests do refuse it.

Change TRACE to a clean run and watch the verdict flip to allowed.

Where you will see this

  • Coding agents like Claude Code, Codex and Cursor read a project instruction file at session start and quote it back at you when they refuse to do something.
  • CI pipelines that re-run the same checks on every pull request, so rules cannot silently drift after the agent's session.
  • Customer support bots with hard rules like "never promise a refund amount" and "escalate to a human on any legal word".
  • Payment and ordering assistants, where "no transaction without an explicit confirmation step" is a block-level rule, not a suggestion.
  • Internal company agents that must never read certain databases, enforced as a forbidden rule plus a runtime guardrail.

Common mistakes

  • Writing rules you cannot check. "Write clean code" cannot be scored, so it silently does nothing while making the file longer and the real rules easier to miss.
  • Marking everything as block. When half the runs get refused, people start overriding by reflex, and then the override means nothing.
  • Commenting out stale rules instead of deleting them. The file is the source of truth, not a diary of last quarter. Dead rules cost reading attention forever.
  • One giant instruction file. Past a certain size the agent reads the top and ignores the rest, so your most important rule may be the one it never reaches.
  • Rules with no owner and no expiry. Nobody removes them, so the useful rules get buried under rules that have never once fired.

If they ask in an interview

Q: How do you make sure an AI agent follows your project's rules?

A: I split instructions into aspirational and operational. Only operational rules go in the file, and each names a check function that returns pass or fail against the run trace. A checker scores every run, and the same checks run again in CI so nothing drifts.

Q: What is the difference between guardrails and a rule file?

A: Guardrails are runtime enforcement, like input and output checks in an agent SDK or an interrupt that pauses a graph and asks a human. The rule file is the human-readable contract those guardrails implement. You need both: the runtime catches a violation as it happens, the rule file lets a reviewer verify the runtime is checking the right things.

Q: Your instruction file has grown to two thousand lines. What do you do?

A: Layer it. A root file under about fifty lines holding only pointers and the hard rules, one rule-set file organised by category, and deep topic files the agent opens only when needed. Then add severity and expiry so rules that never fire get reviewed out.

Try these

  1. Take the code above and add a fifth rule in the uncertainty category, something like "if the agent was unsure, it must have written a question note". Add the field to the trace and the check function.
  2. Add an expires_at date to each rule and print a warning for any rule that is past its date. Use the standard datetime module.
  3. Group the printed report by category instead of listing rules flat, and print a per-category pass count.
  4. Find any real project instruction file, yours or an open-source one, and count how many lines are operational versus aspirational. Rewrite the operational ones into the five categories.

Words, simply

WordMeaning in simple words
Operational ruleA rule a program can actually check and score
Aspirational ruleA nice sentence with no check behind it, like "be careful"
Definition of doneObjective proof the task finished, such as tests exiting 0
Block severityBreaking this stops the run; only a human can override it
TraceThe record of what the agent actually did during a run
GuardrailA runtime check that stops a bad action while it is happening
InterruptA pause in the middle of an agent run to ask a human
Rule expiryA date after which an unused rule must be justified or deleted

Quick recap

  • A rule without a check is a wish; write rules as small functions that return pass or fail.
  • Five categories cover almost everything: startup, forbidden, definition of done, uncertainty, approval.
  • Keep the file layered, tag severity honestly, and let unused rules expire, otherwise the agent stops reading.

Check what you learned

1 / 7. What is the difference between an aspirational rule and an operational rule?
1/7
PreviousA Minimal WorkbenchNextRepo Memory and State

On this page