19 Years in Penang, Malaysia +6010-276 0878 [email protected]

Software Challenges & Security

AI Agent Access Control: Engineering the Management Layer for Your AI Workforce

By Ts. Lukas J. Tan · October 22, 2026

Summary

AI agent access control is the set of identity, permission, approval and audit mechanisms that decides what an AI agent may read and what it may change. It also decides which actions must pass through a person before they take effect. This matters because once an agent can call tools that write, send or pay, an integration stops being only a feature. Every integration you add becomes a grant of authority.

The executive version of this argument asks who manages an AI employee. This article answers the same question from the engineering side. If an agent is going to work inside your business systems, its “manager” cannot be a slide in a policy deck. The manager has to exist in the architecture: a separate identity for the agent, a gateway that every tool call must pass through, a policy layer that separates reading from acting, a queue where consequential actions wait for a named person, and a log that can explain afterwards who decided what.

Maple Software Creation has built business software since 2007. Much of what follows is an old lesson applied to a new kind of worker. When the team behind this company grew to approximately forty people, coordination became a system in its own right. Agents do not remove that system. They move it into code.

This article is for developers, solution architects and technical leads who are about to connect agents to real systems, such as a CRM, an inbox, an ERP or a billing platform, and who want the design to hold up after the demo.

In short:

  • Treat every agent as a non-human principal with its own credentials. Never run it on a shared service account or a borrowed user session.
  • Route every tool call through one enforcement point, and classify tools by consequence: read, draft, write and act.
  • Make drafting the default and sending the exception. Anything that is hard to reverse or affects people directly needs human approval.
  • Limit how far an automated mistake can spread with batch caps, idempotency keys, rate limits and a kill switch you have actually tested.
  • Log decisions, not just events, so you can still trace responsibility when something goes wrong.

The Problem in Technical Terms

Most of the excitement about AI employees is about capability: the agent can summarise, classify, draft, query and coordinate. For an engineer, a more useful frame is authorisation. A language model on its own produces text. It becomes an agent when you give it tools, and a tool is simply a function with side effects that the model can choose to call. So the question that matters is not what the model knows. It is what the runtime will let it do.

Access Is Not the Same as Authority

Conventional applications often blur two ideas. A user who can open a screen can usually press the buttons on it, so read access and write access arrive together. Agentic systems pull these apart, and they should. Here are four tools a typical SME agent might be given against the same customer system:

  1. Read a customer record.
  2. Prepare an email draft to that customer.
  3. Update the customer record.
  4. Send the email, or start a refund.

All four can be built with the same SDK, the same database connection and an afternoon of work. Technically they look like neighbouring features. Operationally they are completely different roles. The first two change nothing until a person acts. The last two change the state of the business, and once a message is sent or a payment is made there may be no clean undo. An access control model for agents has to encode this difference explicitly, because the model will not reliably infer it from a tool description.

Permission Creep Happens One Pull Request at a Time

The most common failure is not a dramatic design error. It is drift. A team ships an agent that writes weekly reports. A month later someone connects it to the CRM so it can pull figures directly. Then it gets permission to tag records, because tagging by hand was tedious. Then it is allowed to trigger the follow-up workflow, because the tags were already there. Each change passes code review on its own merits. Nobody ever approved “an agent that can modify customer data and start workflows at night”, yet that is what now exists.

This is a management problem in engineering form. In a human organisation, a growing list of responsibilities eventually makes someone ask what this person's job actually is. In a codebase, that question only gets asked if the architecture forces it. One way is to require every new tool to declare its consequence tier and its owner before it can be registered.

Speed Changes the Failure Mode

Human workflows are full of pauses that nobody designed on purpose: the working day ends, the manager reviews the batch on Monday, a colleague notices something odd. These pauses are inefficient, but they catch errors. An agent running on a schedule or reading from a queue removes them. If the logic is sound, that is a gain. If the logic contains a wrong assumption, the agent applies it to every record it touches before anyone looks.

A single bad update is a support ticket. The same bad update applied across a table overnight is an incident. That is why throughput limits and batch caps belong in agent architecture as core controls, not afterthoughts.

Natural Language Inputs Are Ambiguous by Nature

Traditional integrations exchange structured data. Agents read messages written by people, and people are not precise. Suppose a customer replies to a proposal with: “It’s fine. We can talk about it another time.” A pipeline could classify this as postponed, update the opportunity stage, schedule a follow-up and send a polite acknowledgement within seconds, and every step would be technically correct. Someone who knows the account might read the same line as hesitation or quiet disappointment, and decide to call instead.

No classifier settles this reliably. Pretending otherwise produces systems that are confidently wrong in exactly the situations where relationships are at stake. The engineering answer is not to forbid agents from handling communication. It is to design for uncertainty: detect when an input is ambiguous or sensitive, reduce the agent's authority in that case, and hand the decision to someone with context.

The Data Problem Underneath

Every agent needs context, and context means data. The convenient approach is to give the agent broad read access and let it find what it needs, but that convenience has a cost. A field that looks routine to a developer may be personally significant to the customer it describes. And two datasets that can be joined should not automatically be joined for every purpose. Assembling context is therefore a data protection decision, even when it is only a few lines of retrieval code.

A Reference Architecture for Governed Agents

The architecture below is deliberately vendor-neutral. It does not depend on a particular model provider or agent framework, and you can build it in stages. Its purpose is to turn the “manager” of an AI agent into a concrete component instead of an assumption.

1. A Separate Identity for Every Agent

Each agent should authenticate as itself, with its own credentials, its own scoped tokens and its own entry in your identity store. It should never run on a developer's personal API key, a shared admin account or the session of whoever happened to start it.

A separate identity gives you three things straight away. Downstream logs show which actions came from the agent. You can revoke or rotate its credentials without affecting anyone else. And you can apply least privilege at the infrastructure level, so that if the application-level policy fails, the database or API will still refuse operations the agent was never meant to perform.

2. A Single Tool Gateway

The agent should not hold direct connections to your systems. Every tool call should go through one gateway that acts as the policy enforcement point. The model proposes a call, and the gateway decides whether it runs, runs in a reduced form, waits for approval or is refused.

Centralising enforcement is what keeps governance maintainable. If tool calls can reach your systems by several routes, each route needs its own checks, and sooner or later one will be forgotten.

3. Consequence Tiers for Tools

Classify tools by what happens if they are called wrongly, not by which system they touch. A simple four-tier scheme works for most business applications:

  • Tier 0, Read: retrieves information. The main risk is data exposure.
  • Tier 1, Draft: produces something a person will review, such as an email draft or a proposed record change. Nothing outside the system happens yet.
  • Tier 2, Write: changes internal state in a way that can be reversed, such as updating a field with its history kept.
  • Tier 3, Act: has external or hard-to-reverse effects, such as sending messages, moving money, deleting data, changing access rights or making decisions that affect a person's circumstances.

The default control comes from the tier, not from the developer's confidence in the prompt.

4. A Policy Layer Separate From the Prompt

Instructions in the system prompt guide the model. They are not security controls. A model can misread them, and content it retrieves can try to override them. Rules about what the agent may do must therefore live in code or configuration that the gateway evaluates outside the model. That evaluation uses structured facts: which agent, which tool, which tier, which records, how many, at what time and on whose behalf.

5. A Human Approval Queue

Tier 3 actions, and Tier 2 actions above a set threshold, should create a pending request instead of taking effect. The request waits in a queue with enough context for a named owner to approve, edit or reject it. The gateway then executes the approved request with the original parameters, so what the person approved is exactly what runs.

6. A Decision Log

Ordinary application logs record that something happened. Agent systems also need to record why it happened and on whose authority. For every tool call, log the agent identity, the proposed action, the policy result, the rule that produced it, any human approver and the outcome. This is how you answer the question that always comes after an incident: who decided this?

7. A Kill Switch That Has Been Tested

Every agent needs a way to stop immediately, at the gateway, without a deployment. Ideally there are two levels. The first suspends Tier 2 and Tier 3 actions while reading and drafting continue. The second suspends the agent entirely. Assume that a kill switch never exercised in a test environment does not work.

Implementation Details

The snippets below are Python-style pseudo-code. They show structure rather than any particular library, and they leave out the error handling a production system would need.

Declaring Tools With Explicit Contracts

Tool registration is the right place to force the questions that permission creep tends to skip. If a tool cannot be registered without a tier, an owner and a reversibility flag, every expansion of the agent's authority shows up in review.

@tool(
    name='crm.update_contact_stage',
    tier=Tier.WRITE,
    owner='sales-ops',            # who answers for this capability
    reversible=True,              # history retained, can be rolled back
    touches_personal_data=True,
    max_records_per_run=25,
)
def update_contact_stage(contact_id: str, stage: Stage, reason: str):
    ...

The owner field is not decoration. It names the team that sets the boundaries of this capability and receives its escalations. If nobody is willing to be named, that tells you something: the capability is probably not ready to be automated.

Evaluating Policy at the Gateway

The gateway receives a proposed call from the agent runtime and returns a decision. Limiting the result to a small set of outcomes keeps behaviour predictable and testable.

def evaluate(call, agent, ctx):
    tool = registry[call.tool_name]

    if agent.suspended or kill_switch.active(agent.id, tool.tier):
        return Decision.DENY('agent suspended')

    if tool.name not in agent.allowed_tools:
        return Decision.DENY('tool not granted to this agent')

    if tool.tier == Tier.READ:
        return Decision.ALLOW(fields=minimise(tool, ctx.purpose))

    if tool.tier == Tier.DRAFT:
        return Decision.ALLOW()

    if tool.tier == Tier.WRITE:
        if ctx.batch_size > tool.max_records_per_run:
            return Decision.REQUIRE_APPROVAL('batch exceeds limit')
        return Decision.ALLOW()

    # Tier.ACT: external or hard to reverse
    return Decision.REQUIRE_APPROVAL(approver=tool.owner)

Notice what is missing. The decision does not ask the model whether it is confident, and it does not read the system prompt. A model's confidence score can help with routing, as discussed below, but it should never be the only thing between a proposal and an irreversible action.

Draft by Default, Send by Exception

For outbound communication, the simplest pattern that lasts is to give the agent a drafting tool and keep the sending tool behind approval. The agent can do almost all of the useful work: reading the thread, gathering relevant history and writing a reply. The step that represents the organisation to the outside world stays with a person.

def handle_inbound(message):
    context = assemble_context(message, purpose='customer_reply')
    draft = agent.run('compose_reply', message=message, context=context)

    request = approvals.create(
        action='email.send',
        params={'to': message.sender, 'body': draft.body},
        owner='customer-service',
        evidence={'thread': message.thread_id, 'signals': draft.signals},
    )
    return request.id   # nothing has been sent yet

Over time a team may decide that certain narrow categories, such as confirming receipt of a document, can be sent automatically. Make that decision explicitly for each category, record it in policy and keep it reversible. Do not get there by quietly giving the agent a general permission to send.

Routing Ambiguity and Sensitivity to People

Take the customer who wrote “It’s fine. We can talk about it another time.” The aim is not to build a perfect emotion detector. It is to recognise when misreading would be costly and lower the agent's authority in that case. Useful signals include:

  • short replies that break an established pattern in a long relationship
  • messages on accounts with open complaints
  • mentions of cancellation or legal matters
  • any message the agent cannot classify with certainty
def route(message, classification, account):
    sensitive = (
        account.has_open_complaint
        or account.value_tier == 'key'
        or classification.label in {'cancel', 'dispute', 'legal'}
        or classification.uncertain
        or departs_from_pattern(message, account.history)
    )
    if sensitive:
        return Route.HUMAN_REVIEW      # agent may draft, may not act
    return Route.STANDARD

This router will produce false positives, and that is acceptable. A message a person reviews unnecessarily costs a minute. A misjudged reply to a valued customer can cost the relationship. Set your thresholds to reflect that imbalance.

Minimising What the Agent Sees

Tie context to a purpose. Instead of passing whole records into the prompt, define which fields each task needs and pass only those. This limits exposure if outputs are logged or leaked. It reduces the chance that irrelevant personal details shape a response. It also makes it easier to explain later what information the agent relied on.

PURPOSE_FIELDS = {
    'customer_reply': ['first_name', 'open_tickets', 'last_order_status'],
    'sales_summary':  ['company', 'stage', 'last_contact_date'],
}

def assemble_context(message, purpose):
    record = crm.get(message.sender)
    return project(record, PURPOSE_FIELDS[purpose])

Joins across systems deserve the same discipline. If an agent can combine support history with payment data, ask whether the task really needs that combination. The answer should be a reviewed setting, not a side effect of broad credentials.

Bounding the Blast Radius

Agents work quickly and repeatedly, so controls that limit how far a mistake spreads matter as much as controls that prevent it. Three patterns are worth building early:

  • Batch caps. Each tool declares the maximum number of records a single run may change. A run that exceeds it becomes an approval request.
  • Idempotency keys. Agents retry and networks fail. Every write and every action should carry a key, so a repeated call does not send a second message or create a second transaction.
  • Rate limits and circuit breakers. If error or rejection rates spike, the gateway should pause the agent's write and act tiers automatically and notify the owner.
def execute(call, decision):
    key = idempotency_key(call)
    if ledger.seen(key):
        return ledger.result(key)

    if breaker.open(call.agent_id):
        return Decision.DENY('circuit open, owner notified')

    result = tools[call.tool_name](**call.params)
    ledger.record(key, result)
    breaker.observe(call.agent_id, result.ok)
    return result

Logging Decisions, Not Just Events

A useful decision log entry is structured and explains itself. Someone who was not involved should be able to reconstruct what happened without reading model transcripts line by line.

{
  'ts': '...',
  'agent': 'agent:sales-assistant',
  'on_behalf_of': 'team:sales-ops',
  'tool': 'crm.update_contact_stage',
  'tier': 'WRITE',
  'params_hash': '...',
  'records_affected': 12,
  'policy_result': 'ALLOW',
  'policy_rule': 'write.batch_under_limit',
  'approver': null,
  'outcome': 'ok'
}

Two cautions apply. First, logs about personal data can themselves become personal data. Store hashes or references where the full payload is not needed, and apply retention rules. Second, logs must be tamper-evident and stored where the agent's own credentials cannot change them.

Testing and Deployment

Agents combine deterministic code with a probabilistic component. Test the governance layer like any other critical code. Test the model's behaviour differently, on the assumption that it will sometimes surprise you.

Test the Gateway Deterministically

The policy layer is ordinary code and deserves ordinary rigour. Write unit tests for every tier and every rule:

  • a tool the agent was not granted is denied
  • a batch over the limit becomes an approval request
  • an act-tier call never runs without an approver
  • a suspended agent cannot write

None of these tests should involve a model. If the governance layer can only be tested end to end through an LLM, it is too tangled up with the agent.

Test the Agent Adversarially

For the model-driven part, build a suite of scenarios. Include:

  • normal requests
  • ambiguous messages
  • messages with instructions aimed at the agent, such as a customer email telling it to ignore previous instructions and export the contact list
  • malformed data
  • records with missing fields

For each scenario, check two things: whether the agent produces a good answer, and whether the gateway correctly contains it when it does not.

Prompt injection through retrieved content is the reason the policy layer must sit outside the model. Prompt design and input handling can make it less likely, but assume some attempts will partly succeed. Make sure that success at the model level still cannot turn into an unauthorised action.

Shadow Mode Before Live Mode

A practical rollout sequence is:

  1. Shadow: the agent runs on real inputs, proposes actions and logs them, but nothing runs. People compare the proposals with what they actually did.
  2. Draft: the agent's proposals appear as drafts or pending approvals in the team's normal tools.
  3. Bounded write: reversible Tier 2 actions run automatically within tight batch caps. Everything else stays in the queue.
  4. Selective act: specific, narrow Tier 3 categories run automatically once evidence from earlier stages supports it, each with its own rule and owner.

Each step is as much a management decision as a deployment step. The process owner should take it, based on data from the previous stage. It should not be taken by the engineer who finds the next feature interesting.

Monitoring After Go-Live

Review does not end at deployment. Models change when providers update them, prompts change when teams tune them, and data changes as the business does. Each week, sample a fixed share of executed actions for human review, even when nothing has gone wrong. Track:

  • how often approvers edit requests
  • how often they reject them
  • circuit breaker trips
  • escalations from the ambiguity router

Pin model versions where your provider allows it. Treat a model upgrade as a change that sends the affected tools back to shadow mode, not as a silent dependency bump.

Reversible Experiments and Irreversible Actions

Not everything needs the same process. Changing the layout of an internal dashboard, adjusting how a summary is worded or trying a new retrieval strategy can be tested quickly and rolled back with a deploy. Some automated actions belong in a different category because an error may not be undoable. These include sending personal information outside the organisation, changing a person's account status and moving money. Proportionate governance lets the first category move fast precisely so that attention is free for the second.

Pitfalls and Engineering Trade-offs

Approval Fatigue

If everything needs approval, approvers stop reading and start clicking. An approval queue that is always full is a control in name only. Keep approvals for actions where human judgement adds something. Show approvers a clear summary with the relevant evidence, and track how often requests are edited or rejected. A queue where nothing is ever changed may be ready for automation. A queue where many requests are changed is telling you the agent is not ready.

Over-Engineering for a Small Team

Many Malaysian SMEs have neither a governance department nor a dedicated platform team, and they should not need one to use agents responsibly. A minimal version of this architecture is achievable: one gateway module, a tool registry with tiers and owners, a single approval table and a structured log. That is a modest amount of code. The harder requirement is clarity about who owns each process, and that comes from a conversation, not a framework.

Latency and User Experience

Approval steps add delay, and some workflows are valued precisely because they are fast. The trade-off is real. Resolve it by being specific about which steps need a person, not by removing the person everywhere. Often the agent can do the slow parts in advance, so the human step becomes a quick confirmation rather than a task.

Mistaking Volume for Value

Agents are very good at producing output: summaries, reports, notifications, tickets and tags. It is tempting to measure success by how much they produce. But output that nobody reads, or that people must check line by line, is a cost, not a benefit. Where you can, measure outcomes instead: decisions supported, errors caught, time returned to people and approvals that needed no edits. If volume rises without a matching outcome, investigate.

Automating a Process That Should Not Exist

Before you wire an agent into a workflow, ask why the workflow exists. Many business processes were designed around an earlier organisational structure: reports requested years ago, hand-offs between departments that have since merged, approvals for risks that no longer apply. Automating these makes them faster without making them useful. Often the better engineering change is to delete a step, not to give it to an agent.

The people behind MSC learned this first-hand. As the business grew to approximately forty people, more and more effort went into coordination rather than creation. When the team later became considerably smaller, it had to ask which processes created value and which had survived only because they were familiar. Agents make that question more urgent, because they will run a poor process tirelessly and at scale.

Prompt Rules Drifting From Gateway Rules

Teams often describe permissions twice: once in the system prompt so the model behaves sensibly, and once in the gateway so it cannot misbehave. Over time the two drift apart. Generate the prompt's description of available tools and limits from the same registry the gateway uses. That keeps what the agent is told consistent with what it is allowed to do.

Shared Credentials During Prototyping

Prototypes often run on an engineer's own token because it is quick. Then the prototype becomes the product, and the agent keeps acting with a person's full authority. Give the agent its own identity from the very first version, even if its permissions start broad. Narrowing them later is then a configuration change, not a rewrite.

Mapping Responsibility Into the System

For accountability purposes, an AI agent is not an employee. It carries no professional responsibility, cannot be held to account and does not grasp the moral weight of an outcome. When it sends a message, the organisation has sent that message. When it changes a record, the organisation has changed it. Handing a task to software does not hand over accountability for the consequences.

The architecture should therefore make the human chain of responsibility explicit. For every agent, record three roles alongside its configuration:

  • Process owner: the person or team who answers for what the agent does in a given business process.
  • Boundary owner: the person who decides which tools and tiers the agent holds, and approves changes to them.
  • Escalation path: where requests go when the agent is uncertain, when policy requires approval or when the circuit breaker trips.

In a small company these may be the same person. What matters is that they are named. This is also why AI agent governance cannot sit with engineers alone. Developers understand what a tool can do and how it can fail. Business owners understand which customers are sensitive, which processes carry legal or relationship risk and which outcomes are unacceptable. A workflow can be technically sound and still be commercially inappropriate or inconsistent with the organisation's obligations. It takes both perspectives to catch that.

Personal Data and the Malaysian Context

For teams building in Malaysia, the proposed Artificial Intelligence and Personal Data Protection Framework is worth reading. The draft deals with the responsible processing of personal information through AI systems. It recognises the importance of security, organisational oversight, risk assessment and controls throughout the AI lifecycle. Because it is still a proposal under discussion, this article does not try to map specific obligations. The patterns described here do fit those themes naturally:

  • Security: separate identities and least privilege.
  • Oversight: decision logs and named owners.
  • Risk assessment: consequence tiers that keep controls proportionate.
  • Lifecycle controls: staged rollout and monitoring.

Practitioners who build and run these systems can add something useful to that discussion: evidence of which controls small teams can actually implement and which add friction without reducing risk. SMEs will ignore governance they cannot implement, and governance that is too vague leaves them guessing. Engineers are well placed to help find the workable middle.

Frequently Asked Questions

What is AI agent access control?

It is the combination of identity, permissions, policy checks, human approvals and audit logging that decides what an AI agent can read, change or do in your systems. It is enforced outside the model, not through prompt instructions.

Why are system prompt instructions not enough to control an AI agent?

Prompts guide behaviour but do not enforce it. A model can misread instructions, and retrieved content can try to override them. Permissions must be checked in code, at a gateway the model cannot bypass.

Which agent actions should require human approval?

Actions that are hard to reverse or directly affect people. Examples are sending external messages, moving money, deleting data, changing access rights and decisions about a person's circumstances. Reversible internal writes above a batch limit are also good candidates.

Does a small business need a governance team to run AI agents?

No. A small team can build the essentials: a tool gateway, a registry of tools with consequence tiers and owners, an approval queue and a structured decision log. The harder part is agreeing who owns each process.

How do I stop an AI agent from repeating the same mistake across many records?

Set batch caps for each tool and use idempotency keys for every write. Add circuit breakers that pause write and act permissions when errors rise, and keep a tested kill switch at the gateway.

Is AI governance a barrier to moving fast?

Not when it is proportionate. Clear tiers let reversible, low-risk work move quickly and save careful review for actions that can affect people, finances or trust.

Conclusion

Building agents gets easier every month, and connecting one to a real system can take an afternoon. The scarce skill is no longer making an agent capable. It is deciding, deliberately and visibly, how much authority it should hold and who answers for what it does.

For engineers, that decision takes a concrete form:

  • a separate identity for the agent
  • a single gateway for every tool call
  • tools classified by consequence
  • a policy layer outside the prompt
  • a queue where people approve what matters
  • limits on how far a mistake can spread
  • a log that explains every decision

None of this stops an organisation from moving quickly. It is what lets the organisation keep moving quickly after its first incident, because the system was designed to contain one.

Intelligence in a model is not the same as judgement in an organisation. Being able to delegate work does not remove the responsibility to govern it. The day an agent joins your systems is a good day to decide, in code, who its manager is.

If you are planning agents for your own business systems and want to work through identities, tiers and approval flows against your actual processes, a Discovery Session with the MSC team is a practical place to start.

See how this plays out for a real client

Twelve detailed, quantified problem-to-outcome case studies across industries in Malaysia.