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

Lit office floors in City of London towers at night, illustrating what UK agent policy means for AI developers in London

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?

Each entry links to its source in the references.
DateBodyWhat it saidWhat to build
21 SepNCSCFive 0 to 4 dimensions for automated actions, and “Technology is behind the detection, but humans respond with actions.”A risk score per tool
30 SepBank of England FPCRecent test-environment incidents showed models taking unexpected actions under permissive safeguardsContainment and monitoring evidence
1 OctAI Security InstituteAutomated checks before a run that the monitor is on and internet access is offPre-run checks before every agent run
8 OctICOCall for evidence on agent identity, logging, transparency and automated decisionsAn agent register and decision records
12 OctUK governmentWork 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 controlRecords 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.

Diagram for AI developers in London: an agent registry with owner, purpose, tools and NCSC scores feeds a control policy set by the firm, the authorised run acts within its authority, a reviewer sees the evidence and can change the outcome, a decision record keeps what the agent was asked, its authority, data, tools and reviewer, reconstruction answers what happened and whether it could recur, and the client route covers Article 22C rights.
Register first. Record every decision. Keep a route back. Tap to open full size.

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?

OptionGood fitTrade-off
Identity provider with workload identitiesFirms with a mature identity teamStrong on identity, weak on purpose, lawful basis and risk scores
Agent management productsLarger estates of vendor and in-house agentsAnother system to integrate, and fields may not match UK GDPR needs
A register in your GRC toolFirms with an existing model inventoryUsually not checked at run time, so it drifts from reality
A small service, as aboveFirms starting with a few agentsYou 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

  1. 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/
  2. 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/
  3. 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
  4. 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
  5. 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
  6. 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
  7. Bank of England, "Financial Policy Committee Record, September 2026", 30 September 2026. https://www.bankofengland.co.uk/financial-policy-committee-record/2026/september-2026
  8. 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/
  9. 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
  10. 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