Skip to content

Build1 publisher3 min readPublished

Agenthof rejects agent tool grants that name no tools when the config loads

Agenthof, an open-source governance layer for AI agents, now rejects any tool grant that names neither specific tools nor mode: all when its config loads. Its builder treats an empty allowlist as an error, since silent deny hides the mistake and silent allow-all grants tools nobody typed.

The Engineer · Build desk

Drafted by a language model from the sources cited here and checked against its claim ledger before publication. How we use AISend a correction

Illustration accompanying Agenthof rejects agent tool grants that name no tools when the config loads
Generated illustration

What happened

  • The load error cites the offending line number and prints both fixes: list the tools the grant may call, or write mode: all.
  • Roles open to everyone only through allowed_groups: ["*"], a role with no access floor is rejected, and executable allowlists follow the same rule.
  • The post's author traces the same fail-open default to empty CORS origin lists, Kubernetes pods with no NetworkPolicy, and firewalls with rules commented out.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • constraint A renamed key, dropped merge line or typo that leaves a tool grant empty now stops the config at load, so none of them can reach a running agent as full access.
  • cost Operators whose configs still use bare tool entries must rewrite each one as mode: all or a named tool list before the config will load.
  • decision Teams building agent allowlists have to pick among allow-all, silent deny and load-time rejection for an empty list; the post argues silent deny still leaves someone debugging a broken agent.
  • capability The widest grant becomes a visible line in the diff, mode: all or ["*"], so a reviewer can question full access before it ships.

The failure starts in the loader. A config file says allowedTools while the parser reads allowed_tools, so the field someone wrote with care is never read and the default applies instead [8]. If that default is allow-all, the agent holds every tool on the server. The post's author, who builds Agenthof, an Apache-2.0 governance layer for AI agents written in Go [1], lists three other routes to the same result: a refactor that renames a key, a merge that drops a line from a list, and a config skeleton copied with the allowlist left for later [8]. "Every one of these looks fine in review," the author wrote [13].

The author calls this privilege by omission. According to the post, the same default shows up well outside agent tooling: empty CORS origin lists that reflect any origin, Kubernetes pods with no NetworkPolicy selecting them, and firewalls whose rules have been commented out [7].

The post argues that deny-by-default, the obvious correction, still hides the mistake. "Silently denying everything hides the mistake (now you're debugging why the agent won't work). Silently allowing everything is a hole," the author wrote [9]. Agenthof rejects the empty grant outright. "Rejecting it at load surfaces the mistake immediately, while the person who made it is still looking at the file," the post says [15]. The project's constitution states the rule directly: a grant that names no tools is rejected at apply and is never widened to the maximum [12].

The first thing the rule removed was a shorthand. A bare "- my-mcp" entry under tools used to grant every tool that server exposed [3]. Full access now has to be written as resource: my-mcp with mode: all, or narrowed to named tools, such as tools: [get_invoice] on a billing server [4]. A bare entry fails at load with an error that cites the line number and prints both fixes [5]. Roles work the same way. A role opens to everyone only through allowed_groups: ["*"], a role with no access floor is rejected, and executable allowlists follow the same rule [6].

I think reject-at-load is the right tradeoff for agent tool grants. My context: a person applies grants at a terminal, and an agent quietly holding an extra tool is harder to notice than one failing on a missing tool. The author puts the asymmetry plainly: "A too-small grant is a bug report. A too-large grant is an incident you find out about later, from someone else" [10].

The post's claim that under deny-by-default "someone notices in about five minutes" [11] is an estimate about someone else's workload. It transfers only if the denied tool gets called soon after deploy. A tool an agent reaches for once a month stays denied, and unnoticed, until that call. A load-time rejection fires before any traffic arrives.

The rule covers the lists the post names: tool grants, roles and executables [6]. The post did not disclose whether the loader also rejects unknown keys. Rejecting unknown keys would catch a misspelled field anywhere else in the config [8].

What to watch

  • Whether Agenthof's loader also rejects unknown keys, closing the misspelled-field case outside tool, role and executable grants.
  • Whether other agent frameworks and MCP clients adopt load-time rejection for empty tool lists or keep missing lists resolving to every tool.
  • How Agenthof handles upgrades for existing configs that still carry bare tool entries.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories