Modes
allowdenyapproval_required— see Approval-required tool calls
Skills
Askills: block sits beside tools: in a role and governs which
agent skills the role may reach, keyed by skill name:
mode— the same three values as a tool:allow,deny,approval_required.constraintswork too; see pinning a skill’s content.via— which levels the rule governs:instructions(skill:<name>),resource(skill.resource:<name>),script(skill.script:<name>). It defaults to all three. Narrowing it is how you allow reading without running: a level the rule does not list is unlisted, and so denied.- Closed-world. An unlisted skill denies regardless of
default_policy. A skill library is a directory — dropping a folder into it adds a capability with no code change and no review — sodefault_policy: { mode: allow }never grants a skill. - The engagement gate. Closed-world applies only once some role (after
inherits:) lists at least one skill. An emptyskills: {}does not engage it — to mean “no skills for this role”, list the skills and set them tomode: deny. An agent whose policy never mentions skills is not skill-gated: activations are decided as the ordinary tool calls they are (load_skill,read_file, …) undertools:anddefault_policy. That is why adding the feature changed nothing for existing agents — and the first place to look when a skill you expected to be denied is allowed. skillsmerge throughinherits:by name, liketools.
skill:x under tools:) is rejected at load;
the skill: / skill.resource: / skill.script: namespace is reserved for this
block.
The generated starter policy
On an agent’s first registration, Hexgate generates a starter policy from its manifest, including askills: block for every skill it discovered:
Only Google ADK discovery enumerates a skill’s files. deepagents discovery reads
frontmatter only, so Hexgate cannot tell whether a deepagents skill ships
scripts: every deepagents skill lands in the first row and is allowed for every
role, the generated YAML says so in a comment, and you should review it. Its
scripts run through
execute, which is gated on its own terms on the top-level
agent only: a sub-agent reached through task runs its own execute ungated,
and the starter policy allows task for admin. See the
deepagents limitations.
It is generated once. Re-registering the agent never overwrites the policy,
so a skill added later is not in it. If the policy already has a skills: block,
that new skill is unlisted and denied until you add it; if the agent had no skills
at first registration, there is no block, and the new skill is not gated at all
until you write one. In a project
that uses policy modules, a new agent starts deny-all instead and no starter is
generated.
Applying a policy in code
create_agent(...) stays close to LangChain; policy enforcement is applied after
agent creation with enforce_policy(...), which accepts either a Pydantic
AgentPolicy or a YAML file path:
Per-role policies
Agents that need per-role behaviour ship apolicies/ directory (one file per
role, with inheritance) instead of a single policy.yaml. A legacy single-file
policy.yaml is treated as the default role — no migration needed. See
Request context + roles for the
multi-file shape and inheritance rules.