The Neogen Brief
Agentic Automation

AI Agent Framework: Agent Authority Lives in Its Prose, Not Its Permissions

Our COO agent spent three hours asking permission for a decision the runtime had granted him weeks earlier. One stale sentence beat a live permission table.

Rehdhil Siyad
Rehdhil Siyad
Founder · Neogen Media
21 September 2026
11 min read
Heavy chrome vault gate standing open on a black plinth, a thin red rope stretched across the gap

In an AI agent framework, the agent's authority is whatever its instruction text says it is, not whatever the permission table grants. We learned this on 9 August 2026 when our COO agent spent three hours asking permission for a decision the runtime had already handed him weeks earlier. The gate said yes. One stale sentence in his identity file said no. The sentence won.

This is the full write-up of that incident: what we believed was wrong, what the seventeen-message thread actually contained, the three separate causes behind it, and the two files we changed. It is part of the build log for the Neogen AI OS, the four-agent mesh that runs our company, and it ends on the one-line rule we now apply to every agent we ship.

What did we believe was wrong when the COO agent kept asking permission?

We believed the approval gate was too tight. The founder was receiving direct messages from Taurus, our COO agent, asking him to approve changes inside a task-management platform that sits squarely in operations. The obvious reading was that the gate had been configured to route those actions to a human, and the fix would be a permissions change.

The founder's message that started the investigation was blunt, and it is worth quoting because it names the assumption exactly: the head of operations cannot make changes to a task-management app? That question presumes the restriction is real and lives in the gate. It did not. Taurus already held every permission he was asking for.

This matters because the gate was the one place everyone looked. Our approval gate is a database rule, not a prompt instruction, and we had spent weeks making it the single source of truth for what each agent may do. We wrote about that design in our post on approval as a database rule. So when an agent behaved as if it lacked a permission, the gate was where we went to check, and the gate said the permission was granted.

What was actually happening in those seventeen messages?

Seventeen messages passed over the agent bus between Taurus and JARVIS, our founder agent, in three hours, all about one platform: a naming standard for sections, a set of record IDs, which service to standardise, and whether a template existed. Five of JARVIS's replies came back as deliberate policy refusals. The thread ended as a decision memo on the founder's phone asking him to approve a naming convention.

Nothing in that thread was an error. Every message was well-formed, every refusal carried a reason, and every escalation followed the rules its sender had been given. That is what made it expensive rather than loud. There was no alert to fire, because from the runtime's point of view the system was working as designed. Only the founder's inbox registered the cost.

When we read the thread against the actual configuration, three separate causes surfaced, and only one of them was a plausible suspect beforehand.

Cause one: the platform was never in the gate at all

The task-management platform had never been registered with the approval gate. Taurus holds his own API key for it, and the platform's public-action catalogue answers him directly with every write action it exposes. He could have created the sections, set the members, and standardised the naming without asking anyone. There was no permission to seek, because there was no gate in the path.

Cause two: his identity file told him he could not

Rule 6 in Taurus's identity file read: you propose, you do not execute; changes to campaigns, CRM or workflows go through the approval gate, and the founder releases them with a code. That sentence had been true when it was written. By 9 August, the gate's self-service table already granted the COO agent every action the rule named: contact and opportunity updates in GoHighLevel, workflow create, activate and deactivate in n8n, pause, resume and budget changes on Meta, and the entire family of client-record actions. The permission was granted in the runtime and withheld in the prose.

Cause three: the escalation router had no test for whose decision it was

The poller that reads unresolved bus messages was prompted to report the blocker to the founder. Its only filter was whether the item was substantive. It had no test for whether the decision belonged to the sender. Every unresolved item that looked important became a direct message to the founder by construction, regardless of who owned it.

Why does an agent obey a stale sentence over a live permission table?

Because the sentence is what the agent reads on every turn, and the permission table is something it only meets when it tries an action. A language model reasons from its context. If the context says you do not execute, the model never reaches the point of calling the gate to discover that it could. The gate cannot correct a belief it is never consulted about.

There is a second reason, and it is the one that makes this failure systematic rather than occasional. Escalating is always the locally safe move. An agent that asks permission can never be blamed for acting wrongly, and the cost of asking lands on someone else. So when an agent's authority is only implied, it will be interpreted downward. Taurus's file said he reports up to JARVIS and never said what reporting means. He read it as asks permission, which is the reading that carries no risk for him.

The OWASP Top 10 for LLM applications lists Excessive Agency as risk LLM06:2025 and defines it as "the vulnerability that enables damaging actions to be performed in response to unexpected, ambiguous or manipulated outputs from an LLM." OWASP attributes it to excessive functionality, excessive permissions and excessive autonomy. That is the right framing for the outward risk. What we hit is its mirror image: insufficient agency, produced not by a permission the agent lacked but by a description of a permission it no longer lacked. The two failures have the same root. The declaration and the behaviour disagree, and nothing checks.

How did we diagnose it without an error to trace?

We stopped reading the gate and started reading what the agent had been told. The diagnostic step that found all three causes was the same one: put the agent's instruction file, the poller's prompt and the gate's self-service table side by side and look for sentences that contradicted the table. The gate was correct. The keys were correct. The access control list was correct. Every one of the three causes was a description of the system rather than the system.

The tell was cost, not error, and that is the signature worth memorising. When an agent behaves more timidly than its permissions allow, no monitor you own will fire. Refusals look like decisions. Escalations look like diligence. The only instrument that registers the fault is a human noticing they are being asked about things they should not be asked about, which is a slow and unreliable sensor.

Two things surfaced during the diagnosis that had nothing to do with the original complaint. The escalation poller was already dead: its schedule read 5,256,000 minutes, which is ten years, with a next run in 2036, while its display string still said every two minutes and its counter showed 866 completed runs. It had fired 866 times and would never fire again. The founder's direct messages would have stopped on their own, and so would JARVIS acknowledging any bus message at all. We reset it to every fifteen minutes, which is also cheaper: the bus dispatcher already wakes agents within thirty seconds of real work landing, so the poll is a safety net, and it had been running seven times more often than a safety net needs to.

What changed in the agent's instruction file?

Two edits, both to prose. Rule 6 now states what the gate actually grants, and a new paragraph states what reporting to JARVIS means and does not mean. The runtime did not change, because the runtime was never wrong. The text was rewritten to match it.

The reporting-line paragraph is the one we would not have thought to write before this incident. It says, explicitly, that JARVIS does not own delivery, so JARVIS cannot approve an operations decision on the founder's behalf, and that asking him converts a call Taurus owned into a delay and then into a message on the founder's phone. An org chart in prose is load-bearing infrastructure. If it is ambiguous, the ambiguity will be resolved by escalation every time.

If you are building agents that hold real permissions, this is the layer that decides how they behave day to day. Our AI agent development service covers the instruction files, the gate and the verification pass that keeps the two agreeing after the first week.

What changed in the escalation router?

The poller's prompt now asks whose decision this is before it asks whether the item is substantive. If the decision sits inside the sender's own domain, JARVIS replies on the bus that it is theirs and does not relay it. Only five categories reach the founder: money leaving the company, client-facing commitments, headcount or pay, irreversible or reputational actions, and genuine gate approvals. Everything else returns silent.

The old prompt asked an importance test. Everything important reached the founder, and most of what an operations agent does is important to operations. The new prompt asks a domain test. A naming convention for sections is important and is also entirely the COO's to decide, and the router now treats those as separate questions.

What did the same defect look like one layer down?

The same evening, JARVIS reported that the platform's section endpoints were unavailable to his key. On the narrow point he was right: two read routes returned not found. Everything around that narrow truth was wrong, and the shape of the error was identical to the identity-file bug, one layer down.

He described the credential as a reporting key, as though it were read-only. It exposed 68 actions, including creating sections, assigning members and building workflow templates. He could have created the sections he was reporting he could not see. The record IDs that had driven seventeen messages and two urgent escalations were never needed, because the write actions accept a name in place of an ID one line down their own schema. And the wrapper tool was missing verbs for two endpoints that worked fine, which is the second instance of that exact fault in one day.

In the identity-file case, prose withheld a permission the runtime had granted. Here, a missing dictionary entry withheld an endpoint the API was serving. In both cases the agent described its own capability from an artefact rather than from the system, and in both cases it described it as smaller than it was. Under-reporting is the default failure direction, because a tool that lacks a verb returns not found, and not found is indistinguishable from permission denied.

The operational rule that came out of it now sits in the tool's own docstring: when an agent says an endpoint is unavailable to this key, check whether the tool simply lacks the verb before believing it. And before reporting yourself blocked on an ID, read the action schema for a name-shaped twin.

Was the defect only in one agent?

No. Taurus looked like the problem because he was the one escalating. When we ran the same comparison across the other subordinate agents, both had the identical fault. Kiara's rule 6 said everything consequential goes through the gate while the gate had already granted her nine self-service action types. Neo's identity file said the CRM was read-only while contact and opportunity updates had been in his self-service set for as long as it existed.

That sweep also found 33 of Neo's skill files opening by telling him he was a different agent, and 129 skill files across all four agents still naming an approval route we had replaced. We covered those findings in our post on multi agent system failures, so here the point is narrower: when one agent behaves more timidly than its permissions allow, the others are not fine. They are quieter about it.

What does this mean for anyone building an AI agent framework?

Treat every sentence in an agent's instruction file that describes a permission as a claim that will drift. The permission table changes when someone edits it. The prose changes only when someone remembers it exists. We now check for that drift deliberately rather than waiting for a founder to notice his inbox.

  • Diff the prose against the table. For each agent, list every sentence that says can, cannot, must ask or goes through the gate, and check each one against what the runtime grants today. We do this whenever the self-service table changes.
  • State authority explicitly, never by implication. Reports to is not an instruction. Write what the reporting line means: who can approve what, and who cannot.
  • Route escalations by domain, not importance. The first question is whose decision this is. Importance is the second question and only applies to decisions that leave the sender's domain.
  • Check the dead paths as well as the live ones. The poller had been dead for weeks with a display string that said otherwise. A status readout that is derived from config rather than from the last actual run is a description, not a measurement.
  • Measure timidity as a cost. An agent that escalates what it owns will never trip an error budget. Count founder interruptions per agent per week and treat a rise as an incident.

There is one research result worth knowing here. Liu and colleagues, in Lost in the Middle (Transactions of the Association for Computational Linguistics, 2023), found that language models use information at the beginning and end of a long context far more reliably than information in the middle. In practice that means the sentence in an identity file that a model reads at the top of every turn will beat a permission it would only discover mid-task by calling a tool. The architecture of attention is on the side of the stale sentence.

The primitive: read what it was told, not what it was granted

A stated restriction the runtime stopped enforcing is worse than one it never had. A restriction that was never granted at least fails loudly when the agent tries the action. One that was lifted in the runtime and left standing in the text fails silently, every turn, with a refusal that reads as good judgement. It is the inverse of the defect in stated controls are not controls, and it fails the same way: the declaration and the behaviour disagree, and nobody checks.

So the rule we now apply, on every agent, before touching a single permission: when an agent behaves more timidly than its permissions allow, read what it was told, not what it was granted.

Frequently asked questions

Would a stronger model have ignored the stale rule?

No, and we would not want it to. An agent that overrides its own instruction file because it suspects the file is wrong is an agent that will override the instructions you meant. The fix is to keep the file true, not to train the agent to doubt it. The model did exactly what it was told. The telling was stale.

Why not delete the prose and let the gate be the only authority?

Because the gate only answers when it is asked, and the agent decides whether to ask from its context. With no prose at all, the agent has no idea what it owns and will still resolve the ambiguity by escalating. The prose has to exist. It just has to be generated from, or checked against, the same table the gate reads.

How do you catch this before a human notices their inbox?

Count escalations per agent per week, broken down by whether the item was inside the sender's own domain. A rising count of in-domain escalations is the signal. Nothing errors, so a log scan for failures will show a clean week while the agent is quietly handing its job back to a person.

Does this apply if your agents have no write permissions at all?

Less, but it still applies to the reporting layer. A read-only agent with a stale sentence saying it cannot see a source will report that source as unavailable and produce an incomplete answer that looks complete. The failure direction is the same: the agent describes its capability from text and under-reports it.

How long did the fix take once the cause was found?

The edits took an afternoon: two paragraphs in one identity file and one rewritten poller prompt. The diagnosis took longer, because the first pass read the gate configuration, which was correct, and the causes only appeared when we read the prose against it.

Want a system like this shipped for you?

We build agent meshes that hold real permissions and stay honest about them, and we document the failures along the way because the failures are where the design comes from. If you want the gate, the instruction files and the verification pass built for your own operations, talk to us and we will walk you through what it would look like for your team.

Rehdhil Siyad
Rehdhil SiyadFounder · Neogen Media

Founder and Director at Neogen Media. Writing field notes on AI automation, growth systems, and the integrated playbook we ship for Indian SMBs. Based in Kochi.

Follow on LinkedIn
Next Step

Want a system like this shipped for you?

If the playbook above maps to your stack and you'd rather we implement it than read about it, book a 30-minute strategy call. We'll map the priorities, tell you what's actually worth building, and leave you with a plan either way.

Book a Strategy Call
30 MINFREE AUDITNO DECKNO OBLIGATION
Or send us a WhatsApp
// What You Walk Away With
  • 01

    A map of every manual task worth automating

  • 02

    Ballpark ROI on your top 3 automation opportunities

  • 03

    Honest read on whether we are a fit — or who is

Usually responds within 24 hours