AI Strategy & ROI · BraivIQ AI Engineering Playbook
AI Developers In London: Turning October's UK Agent Policy Into An Agent Register And Decision Records
For AI developers in London, the UK's October 2026 statements on AI agents point to two things worth building now. The first is an agent register that gives every agent an owner, a purpose, its tools and a risk score for each tool. The second is a tamper-evident decision record that can answer the questions the ICO listed on 8 October: which agent acted, under what authority, what it accessed and whether any human involvement was meaningful. This playbook reads the ICO call for evidence, the NCSC's five risk dimensions and the government's 12 October announcement, then turns them into tested Python.
Published · Updated · 15 min read · By BraivIQ Engineering
Key takeaways
- The ICO opened a call for evidence on agentic AI on 8 October 2026, closing on 20 November. It asks about registering agents with an owner and purpose, tamper-evident logs and how firms reconstruct an agent's decisions.
- The NCSC's 21 September blog scores automated actions from 0 to 4 on potency, scope, criticality, rollout confidence and recoverability. Scoring each tool an agent can use gives you a defensible way to decide where a person must approve.
- On 12 October the government said it must be able to establish quickly what an agent was asked to do, what it accessed, why it acted and whether the same failure could occur elsewhere. A decision record should answer exactly those questions.
- A person in the loop is not automatically meaningful. The ICO notes that human involvement at one stage does not take a decision outside the UK GDPR automated decision rules.
- None of these documents creates a new obligation for firms today, but each one describes evidence you would want to have if a supervisor asked.
20 Nov 2026 - Closing date of the ICO's call for evidence on agentic AI, opened on 8 October 2026 · 5 - NCSC risk dimensions for automated actions, each scored from 0 to 4 (21 September 2026) · 4 - Questions the government says it must answer quickly after an agent incident (12 October 2026) · 22A to 22D - UK GDPR articles on automated decision-making, in force since 5 February 2026
Here is the short version for AI developers in London. Give every agent its own identity in a register, with a named owner, a purpose, a lawful basis, the tools it may use and a risk score for each tool. Check that register before every tool call. Write a decision record for everything the agent does that affects a person or a record, chained so that edits show, and make sure it says who reviewed the output and whether that review could have changed the result. Those two components answer most of what UK bodies asked about agents in the last four weeks.
Both samples are standard library Python, tested on 3.14.4 and 3.11.14 with mypy 2.4.0 in strict mode. They are engineering examples, not legal advice, and the policy that maps risk scores to controls is ours, not the NCSC's.
What did UK bodies say about AI agents between 21 September and 12 October?
| Date | Body | What it said | What to build |
|---|---|---|---|
| 21 Sep | NCSC | Five 0 to 4 dimensions for automated actions, and “Technology is behind the detection, but humans respond with actions.” | A risk score per tool |
| 30 Sep | Bank of England FPC | Recent test-environment incidents showed models taking unexpected actions under permissive safeguards | Containment and monitoring evidence |
| 1 Oct | AI Security Institute | Automated checks before a run that the monitor is on and internet access is off | Pre-run checks before every agent run |
| 8 Oct | ICO | Call for evidence on agent identity, logging, transparency and automated decisions | An agent register and decision records |
| 12 Oct | UK government | Work with the NCSC and AISI on how agent incidents are handled, and a possible role for the Cyber Security and Resilience Bill on loss of control | Records that answer incident questions quickly |
The ICO call is the most specific. It describes an agent as a system based on large language models with access to tools, memory and an environment, and some level of autonomy. It asks whether firms “identify or register an agent first” and “associate it with an owner and purpose”, and it seeks evidence on “structured logging measures that record AI agent identity alongside agent actions” with “tamper-evident records”. On automated decisions it lists what a firm should be able to reconstruct: which agent was involved, what authority it was operating under, what systems or data it accessed, and whether any human involvement was meaningful.
The government's announcement and the AI minister Kanishka Narayan's speech on 12 October framed the same need from the incident side. The speech said the government “must be able to establish quickly what an agent was asked to do, what it accessed, why it acted as it did and whether the same failure could occur elsewhere.” If your records cannot answer those four questions for your own agents, that is the gap to close.
What should AI developers in London build in response?
Two components that sit outside the agent. The register is checked before any tool runs and turns each tool's risk score into a required control. The decision record is written after each consequential step and can be replayed to answer the reconstruction questions. Between them sits the person who reviews the agent's output, and the record notes whether that person saw the evidence and could change the outcome.
How do you register an agent with an owner, purpose and risk score?
Each tool grant carries an NCSC-style score. The NCSC defines potency 3 as “Changes data or system state via APIs (Easier to guardrail than code)” and potency 4 as “Executes code or makes direct system/runtime changes”. Our example policy maps scores to four controls: run, run with monitoring, approve each action, or do not automate. Registration fails if any tool lands in the last group, and authorise() runs before every call.
agent_registry.py"""An agent registry shaped by the ICO's agentic AI call for evidence (8 October 2026) and the NCSC's
five risk dimensions for automated actions (21 September 2026).
Each agent is registered with an owner, a purpose, a lawful basis, its tools and the authority it acts
under. Each tool grant carries an NCSC-style score. The mapping from scores to controls at the bottom is
our example policy, not an NCSC rule: the NCSC blog does not combine the five scores into one rating.
Standard library only. Tested on Python 3.14.4 and 3.11.14 with mypy --strict.
"""
from __future__ import annotations
from dataclasses import dataclass, replace
from datetime import date
from typing import Literal
Control = Literal["run", "run_with_monitoring", "approve_each_action", "do_not_automate"]
# NCSC, "One does not simply defend agentically", 21 September 2026: Potency levels, quoted.
POTENCY = {
0: "AI provided data and then outputs explainable advice to a human",
1: "AI provides non-explainable advice to a human",
2: "Autonomously collects data using read-only privileges across APIs and web search",
3: "Changes data or system state via APIs (Easier to guardrail than code)",
4: "Executes code or makes direct system/runtime changes",
}
@dataclass(frozen=True)
class NcscScore:
"""0 to 4 on each NCSC dimension. Higher means riskier, including a higher (weaker) rollout score."""
potency: int
scope: int
criticality: int
rollout_confidence: int
recoverability: int
def __post_init__(self) -> None:
for name, value in vars(self).items():
if not 0 <= value <= 4:
raise ValueError(f"{name} must be 0-4, got {value}")
def required_control(s: NcscScore) -> Control:
"""Example policy only. Tune it with your risk and compliance teams."""
if s.criticality == 4 and s.recoverability == 4 and s.potency >= 3:
return "do_not_automate"
if max(s.potency, s.criticality, s.recoverability, s.rollout_confidence) >= 3:
return "approve_each_action"
if s.potency <= 1:
return "run"
return "run_with_monitoring"
@dataclass(frozen=True)
class ToolGrant:
tool: str
access: Literal["read", "write"]
score: NcscScore
@dataclass(frozen=True)
class AgentRecord:
agent_id: str # the agent's own non-human identity
owner: str # a named person
purpose: str
lawful_basis: str
data_categories: tuple[str, ...]
tools: tuple[ToolGrant, ...]
delegated_by: str # whose authority the agent acts under
authority_expires: date
related_agents: tuple[str, ...] = ()
class AgentRegistry:
def __init__(self) -> None:
self._agents: dict[str, AgentRecord] = {}
def register(self, record: AgentRecord) -> dict[str, Control]:
if not record.owner or not record.purpose or not record.lawful_basis:
raise ValueError(f"{record.agent_id}: owner, purpose and lawful basis are required")
controls = {g.tool: required_control(g.score) for g in record.tools}
blocked = sorted(t for t, c in controls.items() if c == "do_not_automate")
if blocked:
raise PermissionError(f"{record.agent_id}: remove {', '.join(blocked)} or keep them manual")
self._agents[record.agent_id] = record
return controls
def authorise(self, agent_id: str, tool: str, today: date) -> Control:
"""Runtime check before every tool call: unknown agent, expired authority or ungranted tool fails."""
record = self._agents.get(agent_id)
if record is None:
raise PermissionError(f"{agent_id} is not registered")
if today > record.authority_expires:
raise PermissionError(f"{agent_id}: delegated authority expired on {record.authority_expires}")
grant = next((g for g in record.tools if g.tool == tool), None)
if grant is None:
raise PermissionError(f"{agent_id} has no grant for {tool}")
return required_control(grant.score)
if __name__ == "__main__":
registry = AgentRegistry()
kyc_agent = AgentRecord(
agent_id="agent:kyc-file-prep-01",
owner="Head of Client Onboarding",
purpose="Prepare onboarding files: check documents are present, legible, in date and consistent",
lawful_basis="Legal obligation (Money Laundering Regulations 2017), customer due diligence",
data_categories=("identity documents", "proof of address", "screening results"),
tools=(
ToolGrant("read_documents", "read", NcscScore(2, 0, 2, 1, 0)),
ToolGrant("draft_document_request", "read", NcscScore(0, 0, 1, 1, 0)),
ToolGrant("send_document_request", "write", NcscScore(3, 0, 1, 2, 4)),
),
delegated_by="Onboarding team (process owner)",
authority_expires=date(2027, 3, 31),
)
for tool, control in registry.register(kyc_agent).items():
print(f"{tool:<24} {control}")
risky = replace(kyc_agent, agent_id="agent:kyc-closer-01",
tools=kyc_agent.tools + (ToolGrant("close_account", "write", NcscScore(3, 1, 4, 2, 4)),))
try:
registry.register(risky)
except PermissionError as exc:
print("refused:", exc)
print("authorise send:", registry.authorise("agent:kyc-file-prep-01", "send_document_request", date(2026, 10, 15)))
for agent, tool in [("agent:kyc-file-prep-01", "close_account"), ("agent:unknown", "read_documents")]:
try:
registry.authorise(agent, tool, date(2026, 10, 15))
except PermissionError as exc:
print("refused:", exc)
print("potency 3 means:", POTENCY[3])Tested on Python 3.14.4 and 3.11.14 with mypy 2.4.0 --strict. The score-to-control mapping is an example policy.
The onboarding agent registers with three tools. Reading documents runs with monitoring, drafting a request runs, and sending a request to a client needs approval each time because recoverability scores 4: a message to a client cannot be unsent. A second agent that adds close_account is refused at registration. At run time, an ungranted tool and an unregistered agent are both refused.
How do you keep a decision record the ICO could ask to see?
Each record stores what the agent was asked to do, whose authority it acted under, references to the data it accessed, the tools it used, its output, the reviewer, whether the reviewer saw the evidence and could change the outcome, how long the review took, the outcome, and how the person affected can make representations. Records are chained by hash, and verify() recomputes the chain.
decision_record.py"""Tamper-evident decision records that can answer the ICO's reconstruction questions: which agent was
involved, what authority it was operating under, what systems or data it accessed, and whether any human
involvement was meaningful (ICO agentic AI call for evidence, Theme 4, 8 October 2026).
Records are append-only JSON lines, each chained to the previous record's hash. verify() recomputes the
chain so an edited or deleted record is detected. The 'meaningful review' check is an illustrative
heuristic, not a legal test.
Standard library only. Tested on Python 3.14.4 and 3.11.14 with mypy --strict.
"""
from __future__ import annotations
import hashlib
import json
from dataclasses import asdict, dataclass
from pathlib import Path
GENESIS = "0" * 64
@dataclass(frozen=True)
class DecisionRecord:
decision_id: str
agent_id: str
asked_to: str # the task the agent was given
authority: str # whose delegated authority it acted under
data_accessed: tuple[str, ...] # system and record references, not the data itself
tools_used: tuple[str, ...]
agent_output: str
reviewer: str | None
reviewer_could_change_outcome: bool
evidence_shown_to_reviewer: bool
review_seconds: int
outcome: str
subject_informed: bool # UK GDPR Art 22C safeguards, where the decision is about a person
representation_route: str # how the person can make representations, get human intervention and contest
def meaningful_review(r: DecisionRecord, minimum_seconds: int = 30) -> bool:
"""Illustrative only: a named reviewer, with power to change the outcome, who saw the evidence."""
return (r.reviewer is not None and r.reviewer_could_change_outcome
and r.evidence_shown_to_reviewer and r.review_seconds >= minimum_seconds)
def _hash(body: dict[str, object]) -> str:
return hashlib.sha256(json.dumps(body, sort_keys=True).encode()).hexdigest()
def append(log: Path, record: DecisionRecord) -> str:
lines = log.read_text().splitlines() if log.exists() else []
prev = json.loads(lines[-1])["hash"] if lines else GENESIS
body: dict[str, object] = {"record": asdict(record), "prev": prev}
digest = _hash(body)
with log.open("a", encoding="utf-8") as fh:
fh.write(json.dumps({**body, "hash": digest}) + "\n")
return digest
def verify(log: Path) -> list[str]:
problems: list[str] = []
prev = GENESIS
for n, line in enumerate(log.read_text().splitlines(), start=1):
entry = json.loads(line)
body = {"record": entry["record"], "prev": entry["prev"]}
if entry["prev"] != prev:
problems.append(f"line {n}: chain broken (record removed or reordered)")
if _hash(body) != entry["hash"]:
problems.append(f"line {n}: content changed after it was written")
prev = entry["hash"]
return problems
def reconstruct(log: Path, decision_id: str) -> str:
for line in log.read_text().splitlines():
r = json.loads(line)["record"]
if r["decision_id"] == decision_id:
rec = DecisionRecord(**{**r, "data_accessed": tuple(r["data_accessed"]),
"tools_used": tuple(r["tools_used"])})
return (f"{decision_id}: agent {rec.agent_id} was asked to {rec.asked_to}, under the authority of "
f"{rec.authority}. It accessed {', '.join(rec.data_accessed)} using "
f"{', '.join(rec.tools_used)}. Reviewer: {rec.reviewer}. "
f"Meaningful review: {meaningful_review(rec)}. Outcome: {rec.outcome}.")
raise LookupError(decision_id)
if __name__ == "__main__":
log = Path("decisions.jsonl")
log.unlink(missing_ok=True)
def kyc_check(decision_id: str, client: str, data: tuple[str, ...], output: str,
evidence_shown: bool, seconds: int, outcome: str) -> DecisionRecord:
return DecisionRecord(
decision_id=decision_id, agent_id="agent:kyc-file-prep-01",
asked_to=f"check the onboarding file for client {client}",
authority="Onboarding team (process owner)", data_accessed=data,
tools_used=("read_documents", "draft_document_request"), agent_output=output,
reviewer="a.khan", reviewer_could_change_outcome=True, evidence_shown_to_reviewer=evidence_shown,
review_seconds=seconds, outcome=outcome, subject_informed=True,
representation_route="Client services team, by email or phone")
append(log, kyc_check("D-0001", "C-1042", ("dms://onboarding/C-1042/passport", "crm://clients/C-1042"),
"Proof of address older than 3 months", True, 95, "request new proof of address"))
append(log, kyc_check("D-0002", "C-1043", ("dms://onboarding/C-1043/passport",),
"File complete", False, 4, "file marked complete"))
print(reconstruct(log, "D-0001"))
print(reconstruct(log, "D-0002"))
print("verify clean log:", verify(log) or "ok")
lines = log.read_text().splitlines()
log.write_text(lines[0].replace("95", "300") + "\n" + lines[1] + "\n") # someone edits a record
print("verify after edit:", verify(log))Tested on Python 3.14.4 and 3.11.14 with mypy 2.4.0 --strict. The meaningful review test is illustrative, not a legal test.
Two records go in. D-0001 had a 95-second review with the evidence shown, and reconstructs as meaningful. D-0002 was marked complete after a 4-second review without the evidence, and reconstructs as not meaningful, even though a named person clicked approve. When one record is edited after the event, verify() reports that line 1 changed. The ICO makes the same point in words: human involvement at one stage of a workflow does not by itself take a decision outside the automated decision provisions.
What breaks in production?
- **Shared service accounts.** If three agents use one credential, the register cannot say which acted. Give each agent its own identity, as the NCSC recommended in August. Our restricted network walkthrough shows the pre-run checks that go with it.
- **Scores nobody revisits.** A tool scored when it only read data keeps its score after someone adds a write option. Re-score on every change to a tool's schema.
- **Personal data in the log.** Store references to records, not the records. The sample logs dms:// and crm:// paths for this reason.
- **Review timings that reward speed.** If teams are measured on throughput, review times fall towards zero. Report the share of reviews that meet your own meaningful test.
- **Records that cannot be found.** A chain is useless if nobody can search it during an incident. Index by agent, client and date, and rehearse an incident query.
What are the alternatives to building your own register?
| Option | Good fit | Trade-off |
|---|---|---|
| Identity provider with workload identities | Firms with a mature identity team | Strong on identity, weak on purpose, lawful basis and risk scores |
| Agent management products | Larger estates of vendor and in-house agents | Another system to integrate, and fields may not match UK GDPR needs |
| A register in your GRC tool | Firms with an existing model inventory | Usually not checked at run time, so it drifts from reality |
| A small service, as above | Firms starting with a few agents | You own it, and must keep it current |
Most firms will end with a mix. The key test is whether the register is consulted before each tool call. If it is only a spreadsheet for audits, it will not stop anything.
What should a firm do before the ICO call closes on 20 November?
List every agent you run, including vendor agents, and give each one an owner. Score each tool on the five NCSC dimensions with your risk team. Then pick one agent that makes decisions about people, such as an onboarding check, and add decision records. You will learn more about your gaps in a week of records than in a month of policy drafting, and you may have something useful to say in a response to the ICO.
Our earlier playbook on AI guardrails UK regulators expect covers the September statements, and our blog looked at onboarding checks for e-money firms. As an AI Agency UK team based in London, we build these records into every client onboarding file agent, and you can see one working on your own process in a 14-day Proof Run.
Frequently asked questions
What is the ICO call for evidence on agentic AI?
It is a consultation opened on 8 October 2026 that asks organisations how they handle data protection for AI agents, covering security, transparency, accountability, automated decision-making, fairness and lawfulness. It closes on 20 November 2026. It is a request for evidence, not new guidance or rules.
What are the NCSC's five risk dimensions for agentic AI?
In a blog on 21 September 2026 the NCSC described scoring automated actions from 0 to 4 on potency, scope, criticality, rollout confidence and recoverability. Potency runs from explainable advice to a human at 0 up to executing code or making direct system changes at 4.
Does a human approving an agent's output take it outside UK GDPR automated decision rules?
Not automatically. Articles 22A to 22D apply where there is no meaningful human involvement, and the ICO notes that a person involved at one stage of a workflow does not settle the question. What matters is whether the reviewer had the evidence and the power to change the outcome, and actually used them.
Do these October 2026 statements create new obligations?
Not by themselves. The ICO is gathering evidence, the NCSC blog is guidance and the government is exploring changes to the Cyber Security and Resilience Bill. Existing duties under UK GDPR, operational resilience rules and the Senior Managers regime still apply, and these documents show how those duties are being read for agents.
References
- Information Commissioner's Office, "The ICO's call for evidence on agentic AI", 8 October 2026. https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/artificial-intelligence/the-ico-s-call-for-evidence-on-agentic-ai/
- Information Commissioner's Office, "ICO secures changes from leading AI developers as scrutiny extends to AI agents", 8 October 2026. https://ico.org.uk/about-the-ico/media-centre/news-and-blogs/2026/10/ico-secures-changes-from-leading-ai-developers-as-scrutiny-extends-to-ai-agents/
- National Cyber Security Centre, "One does not simply defend agentically", 21 September 2026. https://www.ncsc.gov.uk/blogs/one-does-not-simply-defend-agentically
- GOV.UK, "Britain steps up national defences against growing AI risks", 12 October 2026. https://www.gov.uk/government/news/britain-steps-up-national-defences-against-growing-ai-risks
- GOV.UK, "Building a safer, more secure Britain in the age of AI (speech)", 12 October 2026. https://www.gov.uk/government/speeches/building-a-safer-more-secure-britain-in-the-age-of-ai
- UK AI Security Institute, "Building a more secure environment for evaluating dangerous capabilities", 1 October 2026. https://www.aisi.gov.uk/blog/building-a-more-secure-environment-for-evaluating-dangerous-capabilities
- Bank of England, "Financial Policy Committee Record, September 2026", 30 September 2026. https://www.bankofengland.co.uk/financial-policy-committee-record/2026/september-2026
- Information Commissioner's Office, "ICO welcomes transition to new Information Commission", 30 September 2026. https://ico.org.uk/about-the-ico/media-centre/news-and-blogs/2026/09/ico-welcomes-transition-to-new-information-commission-and-marks-new-chapter-with-manchester-head-office-opening/
- National Cyber Security Centre, "Managing the cyber risk of agentic AI", 20 August 2026. https://www.ncsc.gov.uk/blogs/managing-the-cyber-risk-of-agentic-ai
- legislation.gov.uk, "UK GDPR Article 22C: safeguards for automated decision-making", In force from 5 February 2026. https://www.legislation.gov.uk/eur/2016/679/article/22C