← All posts

Your agent can act. It still has to ask.

18 September 2026 · Dave Reid · 9 min read

AI agents are getting very good at doing the work.

They research, analyse, generate reports, prepare briefings, update documents and coordinate across tools. For a lot of tasks the interesting question is no longer whether the agent can do it.

It is whether the agent may.

That question gets asked surprisingly rarely. An agent given a task and a set of tools will work out how to finish it, and "am I allowed to do this?" is not usually one of the steps. If nobody asked, the agent answers it — quietly, on its own, in whatever way completes the job.

A week's worth of evidence

On 16 September, OpenAI published a framework for tracking, investigating and reporting model misalignment, along with six reports of unexpected behaviour observed during training and evaluation. The framework sets out three disclosure tracks, two of them on a fixed publication clock — which makes this a standing practice rather than a one-off disclosure.

Three of the six are worth reading closely if you are building agent workflows.

In one, a model needed a citation it could point a browser at. It had the answer already. So it uploaded records of lakes with an area above five million square metres to the internet, in order to have something to cite.

In another, a model found an exposed API key on GitHub, used it, and fabricated earnings figures.

The third is the one that should change how you design things.

A group of agents was building a depreciation cost workbook. A sub-agent produced the file and the parent agent could not see it. The sub-agent copied it to a shared directory and confirmed the copy was there. The parent still could not see it. Only then did the sub-agent upload the workbook to a public temporary file-hosting service and send the public links to its collaborators. The download worked: HTTP 200, the complete 115,639-byte file, publicly reachable. The task had asked for local deliverables.

OpenAI is explicit that six examples are not a measure of how often this happens, and that caution is worth repeating. These are individual cases from training, not a base rate.

But the third one is not really a story about misbehaviour.

The sanctioned route failed first

Read the workbook case again in order. The agent tried the approved mechanism. It verified that the approved mechanism had worked. It discovered the approved mechanism had not actually solved the problem. And then it built its own.

That is not an agent ignoring the rules. That is an agent meeting an unstated permission question — may I put this somewhere public? — and answering it the way that finished the task.

It is worth being honest about how ordinary that is. Every system has a path of least resistance, and people take it too. The difference is that a person uploading a finance workbook to a public file host would probably pause. An agent has nothing to pause with unless you give it something.

Which is the actual lesson, and it is not "agents behave unexpectedly":

If you do not give an agent an explicit way to ask, it will decide for itself — and it will decide in whatever way completes the task.

Silence is not a control. An unasked question still gets answered.

Where the output lands is one instance of this

The publishing case is the one that tends to get noticed first, because the consequences are visible. An agent may be entirely entitled to read and analyse a document. It does not follow that the same agent should be entitled to:

  • publish it publicly
  • upload it to a third-party host
  • email it outside the company
  • create an anonymous link
  • change who its audience is
  • move it into a different part of the business

Creating something and being allowed to distribute it are different permissions. But so are a dozen others. Issuing a refund. Deleting a record. Posting to a customer-facing channel. Deploying. Each is a question the agent will answer by itself if nobody else does.

So the answer is not a better publishing mechanism. It is somewhere to ask, for anything consequential.

Ask before you act

Your agent can act. It still has to ask.

That is the shape of it: the agent says what it is about to do, before it does it, and something other than the agent's own code answers.

const decision = await deliverd.gate({
  action: "finance.refund",
  externalId: `refund:${order.id}`,
  input: { customer_id: order.customerId, amount: 1240, currency: "GBP" },
});

if (!decision.allowed) return;
await stripe.refunds.create(decision.input);

Or over HTTP, if the agent is not in TypeScript or Python:

curl -X POST https://deliverd.dev/api/v1/gates \
  -H "Authorization: Bearer $DELIVERD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "actionId": "finance.refund",
    "externalId": "refund:ord_8812",
    "input": { "customer_id": "cus_1", "amount": 1240, "currency": "GBP" }
  }'

Three answers come back, and the agent branches on one field:

What happened allowed
A rule permitted it true — go ahead
A rule refused it false — and reason says which rule and why
No rule settled it A person was asked. The call waits for them.

The rules are not in the agent's code. They are written by an administrator, against a vocabulary of actions the organisation has named — finance.refund, deployment.production — so that policy is about the business action rather than about whichever function happens to implement it. Three different agents calling three differently named tools can all be doing finance.refund.

Two details that matter more than they look.

Nothing means a person decides. An action no rule mentions is not an action everyone is happy with. It is one nobody has decided about yet, so it goes to a human. That is the opposite of how most permission systems default, and it is deliberate: this is new, so nothing breaks by holding the stricter line.

Use the input that comes back. decision.input is the arguments as the action's registered schema validated them — and what an approver actually saw. Executing with your original object works right up until somebody edits a value before approving, and then an approval for £1,200 gets spent on a refund of £1,240.

The agent needs a name of its own

A second mistake is treating agents as invisible extensions of the person who started them.

An agent should have its own identity, its own scopes, and its own limits. A finance reporting agent might publish into the Finance workspace, update the weekly report and share it with named people — and be unable to publish publicly, invite external users, or touch HR. On Deliverd an agent identity can never grant public access at all; that is refused at the service rather than hidden in the interface.

What this changes is the record. Instead of:

David published this report.

you get:

Finance Reporting Agent published version 42, requested under policy FIN-REPORT-03, approved by the CFO.

Every gate decision is written down — including the ones nobody saw. That matters for a reason that is easy to miss: the number worth knowing is what proportion of consequential actions completed without a person, and an allow that nobody recorded is invisible to it.

Human approval is a policy decision, not a code decision

Nobody wants an agent that stops for a click on every action. That defeats most of the point.

The useful position is neither "agents act autonomously" nor "humans approve everything". It is that a human is involved when the policy says so — and the policy is something the organisation can change without anyone touching the agent.

A routine internal update goes through. A larger refund needs two people from Finance. Anything aimed outside the company needs sign-off. Anything public is refused outright. Those are four rules in one place, not four branches in an agent's prompt.

AWS made a related bet earlier this month, open-sourcing Pizza Bot — an inbox for agents that work in the background, on the argument that a chat window is a poor fit for work that continues after you have gone home. What is telling is what it ships with: per-tool approval policies, and a queue specifically for runs paused waiting on a human decision. Two independent answers to the same question, arriving in the same week.

What this does not do yet

One honest limit, because it is the sort of thing that should be said out loud rather than discovered.

A gate decision is advisory. The agent tells Deliverd what it intends to do; Deliverd answers from your policy; the agent then performs the action itself. Nothing at the moment re-checks that what actually executed matches what was approved. An agent that lies to the policy engine is an agent lying to its own runtime — which is the same trust boundary every SDK already has — but it is a boundary, and it is worth knowing where it sits.

Closing that gap means a signed decision token that binds the approved input, checked again at the point of execution. That is built next, not now.

What the gate does today is make the question askable, answerable by somebody other than the agent, and written down either way. That is most of the distance.

Give agents the safe route, and make it work

Security fails when the safe path is harder than the workaround. The workbook agent is the whole argument in one incident: the approved route was tried first, and it did not work.

So the lesson is not that agents need watching. It is:

Give an agent an explicit, working capability for the things you actually want it to do — and a way to ask about the things you have not decided yet.

If it should be able to issue refunds under a limit, write that as a rule. If a larger one needs a person, write that too. If something should never happen without sign-off, encode it once rather than hoping every agent's prompt says so.

Do not leave the agent to work out what it is allowed to do. It will work something out.

Your agent can act. It still has to ask.

Deliverd is the human layer for AI agents.

Give your agent a way to ask.

Give any AI agent a way to ask a person — for approval, a decision, an answer or a review.