Externalize the hook routing table: derive from .agent-guard.yaml wraps: metadata #10
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally filed by @coilysiren on 2026-05-14T23:21:21Z - https://github.com/coilysiren/agent-guard/issues/13
Problem
agent-guard#10 ships the PreToolUse hook with two hardcoded routing tables baked into the Go binary: a coily-flavored one and an agent-guard-flavored one. This works for v0 but has two real problems:
coily ops <X>verb (or agent-guard grows a newagent-guard execMakefile target), the routing table doesn't update. The wrapper inventory and the hint inventory live in different files, and the discipline that keeps them in sync is human attention.cli-mcp,cli-web-docs,cli-web-ops) that wraps its own set of binaries cannot extend the table without forking agent-guard. The hook is generic in design but hardcoded in implementation.Proposal
Externalize the routing table. Source of truth: the existing
.agent-guard/agent-guard.yaml(or.coily/coily.yaml) that the consumer already maintains. Add awraps:field per command:The hook reads the discovered config at PreToolUse time, builds the routing table in memory (
token -> "use <guard> <verb> ..."), and uses it instead of the hardcoded map. The recovery hint composes the guard binary name (from the discovered marker filename) with the verb declared in the YAML.Why this is interesting
wraps: [npm, pnpm, yarn]; cli-web-ops can declarewraps: [terraform, helm]. Same hook binary, different tables.agent-guard lintdiscipline gets a third invariant: everywraps:entry's binary must not also be allowed bypermissions.allow(otherwise the hook hint is irrelevant), and every recovery-hint-eligible binary inpermissions.denyshould appear in somewraps:(otherwise the agent gets the generic deny).wraps:entry") which makes the trim-deny work mechanical, not manual.Open design questions
wraps:carry an optional hint-extra (the GraphQL-trap-style notes)? Or should the hook hardcode those token-specific extras separately?mywrapper foo" instead of "useagent-guard exec foo")? Yes - the guard name should come from the binary that wrote the YAML's lockdown, not from the marker filename.Acceptance
.agent-guard/agent-guard.yaml/.coily/coily.yamlcarry awraps:field per command (where applicable). Existing entries withoutwraps:continue to work (no implied wrapping).agent-guard hook pre-tool-usereads the config and routes from it. The hardcodedcoilyRoutes/agentGuardRoutesmaps are gone.wraps:blocks for its ops/pkg/docker/ssh/tailscale verbs.agent-guard lintenforces the two invariants above.Followups (out of scope here)
cli-mcp) can opt into this hook by declaring its ownwraps:.Notes