Intelligence

The Harness Kept Its Own List of What an Agent Could Call. Nothing Ever Checked It Against the Grant.

GitHub issue 803 against markmhendrickson/ateles, opened 7 September 2026, reports that a harness allowlist meant to derive from or hold parity with an agent's own canonical grant instead lives as an independently authored second copy, with zero of forty measured agents holding parity. This record independently cloned the repository's current default branch and the still open pull request 807 built on top of the issue, read the exact affected functions directly, and confirms the mechanism from the source itself rather than from the issue's own account of it.

Event analysed: . This analysis was published on 7 September 2026.

When an agent's authorized tools are recorded in one canonical place, agent_grant, and a harness separately decides what it will actually let that agent call from a different field, agent_definition.tool_allowlist, is the harness list ever derived from the grant, or proven equal to it, or is it simply a second, independently authored record of the same question?

It is a second, independently authored record, and this record independently confirmed that by cloning markmhendrickson/ateles directly rather than accepting the issue's own account of it. Issue 803, opened 7 September 2026, reports that a 2026 architecture ruling, referred to inside the repository as decision 42, requires a harness tool allowlist to be derived from the grant at load or held equal to it by a parity test, and that neither exists: agent_grant stores tool capabilities as op strings shaped tool colon server colon tool, parsed by GrantChecker in lib/daemon_runtime/grant_checker.py, while the harness reads a completely separate field, agent_definition.tool_allowlist, through AgentLoader in lib/daemon_runtime/agent_loader.py, in a different grammar, mcp double underscore server double underscore tool. This record cloned the repository's current default branch, commit 27101189c285c959c47dcb66c99669022dfe489a, and confirmed directly that no function anywhere in the codebase reads both fields and compares or derives one from the other, that validate_tool_allowlist.py in scripts/linters validates the harness field's own grammar with no reference to agent_grant at all, and that skill_runner.py's own dispatch path unconditionally appends a Neotoma wildcard tool entry to every restricted agent's own allowlist before a claude provider ever sees it, regardless of what either record names. Issue 803 reports a production measurement of zero of forty agents holding parity; this record could not independently reproduce that count, since it has no credentialed access to the swarm's live Neotoma instance, and confirms that pull request 807, the design only proposal built to make the parity test possible, states in its own verification table that it also could not reproduce the count, its own five attempts against the production endpoint each returning a 502.

An agent's authority to act should live in one place. Ateles, the swarm markmhendrickson operates, records it in agent_grant, a Neotoma entity whose capabilities array names, among other things, which tools an agent may call. Somewhere between that record and the moment a dispatched process actually runs, a second question gets answered: what will the harness invoking that process actually pass as its own permitted tool list. Issue 803, opened against markmhendrickson/ateles on 7 September 2026, reports that the second answer is not computed from the first at all.

What this record independently confirmed by cloning the repository directly, rather than by reading the issue's own account of it: the harness reads its tool list from agent_definition.tool_allowlist through AgentLoader, and the grant records tool capabilities separately, as op strings inside agent_grant.capabilities, read through GrantChecker. This record found no function on the current default branch that reads both and reconciles them, and no test anywhere in the repository whose name or content resembles a parity check between the two.

Two records, two loaders, two grammars

This record cloned markmhendrickson/ateles at its current default branch head, commit 27101189c285c959c47dcb66c99669022dfe489a, and read the two loaders directly. lib/daemon_runtime/grant_checker.py defines AgentGrant and its static _parse method, which normalizes a grant entity's capabilities array into a set of ops and, for any capability whose op begins with the literal prefix tool:, strips that prefix and stores the remainder, a string shaped server:tool, in a separate tool_grants map. lib/daemon_runtime/agent_loader.py defines a wholly separate dataclass, AgentDefinition, whose tool_allowlist field defaults to the literal string asterisk and whose own tools property parses that field, independently, into a list of tool names in the harness's own grammar, entries such as a bare Read, a scoped Bash(gh:*), or an MCP reference shaped mcp__<server>__<tool>. Nothing in either file imports the other. AgentDefinition does carry a field named agent_grant, which reads as though it might be the missing link, but this record confirmed it is not a reference to any specific grant entity at all: it is a two valued role string, service or operator, exposed only through the boolean shaped properties is_operator and is_service. The grant an agent actually holds is looked up separately, by matching its aauth_sub identity, through GrantChecker, a lookup path that never touches agent_definition at all.

The harness side's own grammar is not informal. scripts/linters/validate_tool_allowlist.py, wired into the repository's own lint pipeline, recognizes exactly four forms for a tool_allowlist entry, the wildcard asterisk, a bare CamelCase or snake_case tool name, an MCP reference, and a scoped Bash(...) call, and warns on anything else, having been written specifically because an earlier, undocumented bash: prefix was silently dropped by the CLI parser it feeds. This record read the linter directly and confirmed it validates only the shape of tool_allowlist itself. It carries no reference to agent_grant, no import of GrantChecker, and no comparison of any kind between the two records. A harness allowlist can be perfectly well formed under this linter's own rules and have no relationship whatsoever to what the grant that is supposed to authorize it actually names.

The wildcard a dispatcher adds on its own

This record separately read execution/daemons/apis/skill_runner.py, the module that builds each provider's own command line before a dispatch runs, and found a mechanism the issue names but which this record confirms directly rather than by description. For the claude provider, once an agent's own tools list is anything other than the bare wildcard, the code builds an allowed_list from that agent's own tool_allowlist and then, unconditionally, appends one further entry: if "mcp__mcpsrv_neotoma__*" not in allowed_list: allowed_list.append("mcp__mcpsrv_neotoma__*"). Every restricted agent dispatched through the claude provider receives full access to the Neotoma MCP server's entire tool surface, store, correct, delete_entity, merge_entities and register_schema among them, whether or not its own declared allowlist names any of them, and whether or not any grant of any kind authorizes it. This record confirmed the same file builds an entirely different command for the other two supported providers: codex receives a filesystem sandbox policy and optional network access flags, with no tool allowlist argument constructed at all, and cursor receives --force --trust --approve-mcps, a flag this record read as pre-approving every MCP server the session encounters rather than naming any subset of tools. The same agent, the same grant, dispatched to a different provider by whichever one has capacity at the time, can carry a materially different effective reach, and this record found nothing on the current default branch that measures or reports that difference.

This record also read execution/mcp/mcp_tool_grant_proxy/proxy.py directly. It exists, it is a real, documented stdio interceptor built to enforce agent_grant tool capabilities and parameter constraints against a downstream MCP server's calls, and its own docstring states plainly that it is permissive, allowing every call, whenever the agent it is checking has no grant that declares any tool capability at all. A repository wide search for any executable reference to it, outside its own directory, found none: no Python import, no JSON MCP configuration entry, no shell invocation anywhere in execution/daemons or execution/mcp/ateles constructs a dispatch that routes through it. The module that actually injects the live Neotoma MCP configuration into a claude dispatch, the same skill_runner.py read above, wires the raw mcpsrv_neotoma HTTP endpoint directly, with no proxy in front of it. This record separately checked the repository's own docs/architecture.md and docs/aauth.md, and found both describe the proxy as shipped and live, enforcing tool grants at runtime, a description this record's own direct check of the dispatch path does not support for the path it actually read.

What the still open design proposal itself confirms and could not confirm

This record separately fetched pull request 807, opened the same day as issue 803 and explicitly framed as design only, changing no grant, no allowlist and no dispatch code. Its own added file, docs/tool_grant_grammar.md, opens with a table of premises checked against the code rather than assumed, and this record read that table directly from the pull request's own branch. It confirms, independently of this record's own reading above, the unconditional Neotoma wildcard append, the provider specific command construction, and that the grant proxy carries zero executable references outside its own directory while still being named shipped in the repository's own architecture documentation. It also states plainly what it could not confirm: five attempts against the swarm's production Neotoma endpoint during that pass each returned a 502, so the issue's own headline count, thirty one grant entities with zero carrying any tool capability, and forty agents with a tool_allowlist, is carried forward from the original measurement rather than independently reverified by the pull request's own pass. This record's own access to markmhendrickson/ateles is limited to its public repository; it has no path to the swarm's own production Neotoma instance at all, and states the forty agent, zero parity count as issue reported evidence rather than as a count this record itself confirmed.

The proposal itself does not ship a fix. It registers a design decision, a normalized grammar mapping a grant capability shaped tool:<surface>:<operation> onto a harness entry in either direction, explicit rules for when a surface level wildcard is admissible and when a bare tool wildcard is refused outright, two reserved surfaces so a harness native tool with no MCP server behind it can still be named in a grant, and an explicit rule that a provider whose effective reach cannot be read back from its own command line reports as unknown rather than as passing or failing a parity test. As of this record, no grant has been amended, no parity test has been written, and no dispatch code has changed. The pull request's own target branch is itself another unmerged branch, registering a still open dependency on a prior, separately unmerged design decision.

What this record does not establish

This record does not claim the forty agent, zero parity count is currently, independently verified; it is carried here as the issue's own reported measurement, corroborated by the pull request's own inability to reverify it against a production endpoint that returned an error on every attempt during its own pass, and this record's access to the swarm's private Neotoma instance is nonexistent rather than merely unattempted. This record does not claim every agent's effective reach is wider than its own grant; it confirms directly that the mechanism which would widen it, the unconditional Neotoma wildcard append, applies to every restricted claude dispatch, and separately that thirty one of the grant entities the issue names carry zero tool capabilities of any kind, meaning a grant side comparison has nothing to compare against for those agents rather than a comparison that was made and found narrower. This record does not claim the codex or cursor providers are unsafe; it establishes only that their own effective tool reach is not read back from anything this record could introspect from the command each builds, which is the same conclusion pull request 807's own design table reaches independently. This record does not claim the grant enforcement proxy has never mediated a call in this codebase's history; it confirms only that the dispatch path this record read directly does not route through it, and that the repository's own architecture documentation describes it in terms this record's own reading of that dispatch path does not support.

The Authority Provenance ledger

Canonical grant. agent_grant entities, matched by aauth_sub, storing tool capabilities as op strings shaped tool colon server colon tool inside a capabilities array, parsed by GrantChecker._parse. Issue 803 reports zero of thirty one measured grant entities carry any such entry.

Harness representation. agent_definition.tool_allowlist, read through AgentLoader, in a distinct grammar validated separately by scripts/linters/validate_tool_allowlist.py, with no import of or reference to GrantChecker or agent_grant anywhere this record found.

Derivation. None found on the current default branch. agent_definition carries a field literally named agent_grant, confirmed directly by this record to be a two valued role string rather than a reference to any specific grant entity.

Provider representation. Confirmed directly from _provider_command: claude receives a constructed --allowed-tools flag, with an unconditional Neotoma wildcard append for any non wildcard agent; codex receives a filesystem sandbox policy with no tool flag; cursor receives --force --trust --approve-mcps.

Enforcement path. mcp_tool_grant_proxy exists, confirmed directly, and fails open by its own documented design whenever the calling agent's grant declares no tool capability. Confirmed directly to carry zero executable references outside its own directory; the live dispatch path this record read configures the Neotoma MCP server without it.

Observed runtime reach. Not independently observed by this record against a live dispatch. What this record confirmed directly is the command each provider's own code path constructs, which is a fact about what a dispatch would receive rather than a captured trace of one that ran.

Reported measurement. Zero of forty agents holding parity, issue reported, 7 September 2026. Not independently reproduced by this record or, on its own account, by pull request 807's own verification pass, both blocked from the production Neotoma endpoint.

Tracking state. Issue 803 open. Pull request 807 open, draft in substance though not flagged as a GitHub draft, design only, targeting another still open, unmerged branch, with an automated triage comment reporting pre implementation gates satisfied and a named reviewer assigned.

Where this sits in the pattern

Praxis Proxy's own extract_allowed_tools showed one parser's own fallback branch collapsing a malformed restriction into the same result as no restriction, inside a single authority bearing field. This record's own mechanism sits one level up: there is no single field and no single parser here at all. Two separately authored records exist for the same question, maintained by different code, in different grammars, and the gap this record confirms is not a fallback branch misfiring, it is the complete absence of any function that reads both and asks whether they agree. Replit's own fix for its database incident drew a hard boundary around what an agent could reach rather than trusting a convention that development and production stayed apart; this record's own mechanism is the boundary equivalent for authority itself, a canonical record and an independently maintained copy of what it is supposed to mean, with nothing keeping the second one honest.

Sources

This analysis interprets third-party reporting, research and announcements. Moona is not the original reporter of the underlying events.

[2]
docs(foundation): register decision 86, the grammar by which a grant names a tool
markmhendrickson/ateles (GitHub Pull Requests) · 7 September 2026 · Primary source
[3]
markmhendrickson/ateles repository, current default branch
markmhendrickson/ateles (GitHub, repository) · Primary source

Protocol evidence

This record does not assess these architectures. The connection runs through the Risk Registry requirement each one bears on, and these published authority architectures are what the evidence says about that requirement.

Protocol evidence related through AEW-038 An execution bearing authority representation is maintained independently of its own canonical grant, with no derivation or parity proof between them

  • Supports requirement

    Agent Control Standard (ACS)

    OWASP GenAI Security Project, originally Zenity

    Requirement The specification does not guarantee complete mediation of every consequential action a host can take

    ACS's own conformance document states directly that the specification does not guarantee complete mediation of every consequential action a host can take. Ateles's own mcp_tool_grant_proxy is direct, independently confirmed evidence for exactly that admission at the level of a single, real enforcement point: this record's own reading of the current default branch found the proxy real, documented and built specifically to mediate agent_grant tool capabilities, yet carrying zero executable references anywhere on the dispatch path skill_runner.py actually builds, while the repository's own architecture documentation describes it as shipped and live. A mediation point can exist, be correctly written, and still mediate nothing a live dispatch ever reaches, which is a sharper instance of ACS's own stated limitation than an unimplemented control would be.

    This record is the cited evidence for this relationship.

    View protocol evidence

  • Supports requirement

    Verifiable Attenuated Delegation for AI Agent Chains (draft-asor-wimse-agent-delegation-chain)

    Rafael Asor, Attenu

    Requirement Revision 01 defines a normative ABNF scope grammar: lowercase, period separated segments, with a wildcard permitted only as the complete final segment

    The draft's own normative ABNF gives a delegation token's scope grammar exact, bounded wildcard semantics, so a verifier can decide subsumption without inventing a rule for a shape the grammar leaves ambiguous. Ateles's own still open pull request 807 independently arrives at the identical need from the opposite direction, a system that already has two ungoverned grammars and no bijection between them: its own added proposal defines exactly which wildcard forms a grant capability may take, refuses a bare tool colon asterisk outright, and bounds a surface level wildcard to an enumerable domain, citing the same fail-open concern this record's own reading of Ateles's unconditional Neotoma wildcard append independently confirms in shipped code today. This is evidence for why a normative, bounded wildcard grammar matters as a general precondition for any parity claim between two authority representations, not only for one draft's own delegation tokens.

    This record is the cited evidence for this relationship.

    View protocol evidence

  • Supports requirement

    Verifiable Attenuated Delegation for AI Agent Chains (draft-asor-wimse-agent-delegation-chain)

    Rafael Asor, Attenu

    Requirement A verifier encountering an unrecognized constraint type must deny rather than treat it as unconstrained

    The draft's own verified rule requires a verifier to deny on an unrecognized constraint rather than read it as unconstrained. Pull request 807's own design proposal states the same discipline for a provider whose effective tool reach cannot be introspected from its own command line, codex and cursor among them confirmed directly by this record's own reading of skill_runner.py's per provider construction: such a provider must report as unknown, never as a passing parity result, because an unmeasurable surface defaulting to green is the identical failure this draft's own constraint rule already forbids at the level of one delegation token. Recorded as evidence for the same fail closed on unknown discipline operating at the level of an entire execution surface rather than one constraint field.

    This record is the cited evidence for this relationship.

    View protocol evidence

Related Intelligence

All Intelligence Records →