Practicals · Day 4
Bounded agents
What should an agent check before it is allowed to act? The solution notebook compares a naive controller with a guarded controller on the same fictional cases.
Day 4 files
day4_solution.ipynb in Jupyter. Run the cells in order. The first section includes an optional package-installation command.The activity question
Can explicit policy, authority, state and verification checks prevent failures that occur when a controller treats a request as permission to act?
You will compare two rule-based controllers. The naive controller follows surface wording. The guarded controller has a small allowlist of simulated tools, validates arguments, pauses high-impact actions for human approval, checks stale state, resolves timed-out writes by idempotency key and records a trace.
Dataset overview
| Observation | One fictional request with a short context and an expected safe next step. |
| Policy corpus | Thirteen trusted policy documents and three untrusted test documents. |
| Cases | Thirty-two cases across nine categories. |
| Actions | Every tool is simulated. No message, payment, record, permission or external service is changed. |
| Purpose | Compare route choice, action choice, policy citation, safe execution, human gates and verification. |
How the cases are split
Both splits cover the same categories. Their wording and targets differ, so the final split checks whether the fixed controller rules transfer to a second set of cases.
| Split | Cases | Categories | Role in the activity |
|---|---|---|---|
| Development | 16 | 9 | Used to read traces, find mistakes and check the controller rules. |
| Final | 16 | 9 | Used after the rules are fixed to report the final metrics. |
Data dictionary
The dataset is one JSON file with three top-level sections. Paths below show where each field appears.
| Field | Type | What it contains | How it is used |
|---|---|---|---|
metadata.title | Text | Name of the evaluation suite. | Identifies the dataset. |
metadata.source | Text | States that the material was written for the course. | Records provenance. |
metadata.offline | Boolean | Whether the activity needs a network connection. | Confirms that the simulation runs locally. |
metadata.contains_personal_data | Boolean | Whether any case contains personal data. | Records the privacy status of the teaching data. |
metadata.has_real_world_side_effects | Boolean | Whether a tool can cause a real action. | Confirms that every action is simulated. |
metadata.development_cases | Integer | Number of development cases. | Checks the split size. |
metadata.final_cases | Integer | Number of final cases. | Checks the split size. |
metadata.policy_documents | Integer | Number of policy documents. | Checks the corpus size. |
policy_documents[].doc_id | Text | Unique policy identifier, such as P07. | Links a decision to its supporting policy. |
policy_documents[].title | Text | Short policy name. | Makes retrieved results readable. |
policy_documents[].topic | Text | Policy subject, such as state or approval. | Groups related safeguards. |
policy_documents[].trust_level | Text | trusted or untrusted. | Prevents retrieved content from granting authority. |
policy_documents[].text | Text | The policy statement or untrusted test instruction. | Supplies evidence for the controller's decision. |
cases[].case_id | Text | Unique case identifier. | Joins predictions to the expected result. |
cases[].request | Text | The fictional user request. | Input to both controllers. |
cases[].context | Text | Available evidence, state or approval information. | Defines what the controller may know. |
cases[].case_type | Text | One of the nine case categories below. | Supports category-level error analysis. |
cases[].expected_route | Text | The intended route. | Calculates route accuracy. |
cases[].expected_action | Text | The intended next action. | Calculates action accuracy. |
cases[].expected_doc_ids | List | Accepted supporting policy identifiers. | Checks policy citation. |
cases[].requires_human_gate | Boolean | Whether the proposed action needs human approval. | Checks that approval is requested when required. |
cases[].requires_verification | Boolean | Whether a fresh observation must verify the outcome or state. | Checks stale-state and timeout handling. |
cases[].split | Text | development or final. | Separates rule development from final evaluation. |
Case category dictionary
| Category | Cases per split | Question tested | Expected response |
|---|---|---|---|
retrieval | 5 | Can the controller find and cite the relevant trusted policy? | Answer with a policy citation. |
calculation | 1 | Can it call the narrow calculator with valid arguments? | Return the calculation. |
missing_evidence | 1 | Will it invent current information that it cannot observe? | Ask for the missing information. |
injection | 2 | Can retrieved text expand authority or override policy? | Ignore the embedded instruction. |
high_impact | 3 | Will it send, publish, delete, refund or change access without approval? | Request human approval for the exact action. |
stale_state | 1 | Is an earlier read still valid when a write is proposed? | Re-read state and stop when it has changed. |
timeout | 1 | Did a timed-out write already succeed? | Check by idempotency key before any retry. |
invalid_tool_input | 1 | Does the tool reject an impossible probability? | Reject the arguments before calculating. |
compound | 1 | Can research and drafting remain separate from distribution? | Prepare a local draft and do not send it. |
Source and preparation
The policies and cases were written for this course. They are fictional, deterministic and contain no personal data. Thirteen trusted policies cover tools, evidence, authority, privacy, consent, calculation, state, verification, timeout handling, approval, security, traces and monitoring. Three untrusted documents test whether retrieved text is mistaken for an instruction.
The original classroom CSV files were combined into one JSON dataset so the notebook needs only one adjacent data file. Development and final labels are included because this is the solution notebook. No external service is contacted at run time.
What this activity asks you to do
- inspect the policy corpus and the distribution of case categories;
- define an allowlist of narrow tools and validate their arguments;
- compare a wording-based controller with a guarded controller;
- bind authority to the proposed action and add a human approval gate;
- re-read stale state before a simulated write;
- resolve an ambiguous timeout without repeating a completed write;
- read a trace from request through verification;
- compare development and final metrics and state a limitation.
Learning outcomes
- explain why a request, a retrieved instruction and an authority grant are different;
- write a narrow tool contract and reject invalid arguments;
- identify where human approval is required before a consequential action;
- explain how stale state, timeout ambiguity and idempotency affect safe retries;
- distinguish a plan, tool call, observation, decision, action and verification in a trace;
- compare controllers with route, action, citation, safety, approval and verification measures;
- explain why adding dependent steps reduces route reliability.
What the evidence does not establish
- Passing thirty-two fixed cases does not show that an agent is safe on unseen requests.
- The rule-based controller recognises a limited set of phrases. Different wording may lead to a different route.
- The simulated tools have fixed responses. Real services can return partial, delayed, conflicting or incorrect observations.
- The activity does not test authentication, changing permissions, network security or recovery after a real incident.
- Human approval is represented by a pause in the trace. The notebook does not model who may approve or how approval is authenticated.