Skip to content
WIP

This guide is a work in progress. Barry is also a work in progress.

Bound fields

A bound is the object that restricts a session. It takes away tools, write access, file paths, shell commands, network destinations, and nodes from what the session’s traits grant, and it never grants anything. This page lists every key the bound schema accepts. For how patterns match, how Barry enforces each rule, and how bounds merge, see Bounds.

You write the same object in several places:

  • identity.yaml, bound:: an inline bound that applies to every session the identity starts.
  • identity.yaml, bounds:: a list of named bounds, each a one-name mapping whose fields sit beside description and optional. The mapping key is the name, so the entry has no name field. See the builtin bounds in Barry’s identity.yaml.
  • bag.yaml, top-level bounds:: a map from bound name to a definition with a description and a bound: object.
  • bag.yaml, a trait’s bound:: an inline bound that the trait carries.
  • Named bounds: a bound with its name at the same level as its rules. barry bound list shows every named bound and what it restricts.

The schema is BoundSchema in sdk/src/bounds/types.ts. It rejects unknown keys at every level, so a misspelled key fails instead of denying nothing. Every key is optional, and a bound with no rules restricts nothing.

Every key bound accepts, with its type. Each key has its own section under Fields.

name: string
description: string
nodes: object
allow: list of strings
deny: list of strings
nativeTools: map of harness ID to list of strings
deniedTools: list of strings
deniedAccess: list of strings
files: object
deny: list of strings
allowOnly: list of strings
bash: object
deny: list of strings
denyPrograms: list of strings
network: object
actions: list of strings
domains: list of strings
allowDomains: list of strings
enforce: string
  • Type: string
  • Required: no

The bound’s name, at least one character. A named bound carries it, and sessions, traits, and identities select the bound by it. Merging drops it, so it never restricts anything. An entry under bounds: in identity.yaml takes its name from the mapping key and rejects this field.

name: no-secrets
  • Type: string
  • Required: no

What the bound restricts, in a sentence. barry bound list prints it. Merging drops it. An entry under bounds: in identity.yaml requires it, and a bag.yaml bound definition takes it beside bound: instead.

description: "Denies writes, Bash, and recognized network writes"
  • Type: object
  • Required: no

Which installations may run the work: this one, as local or by its installation ID, and the workers it invited. Barry refuses a tool call on a node that deny names, or on a node missing from allow when allow is present. See Distributed nodes.

nodes:
allow: [local]
  • Type: list of strings
  • Required: no

The only nodes that may run the work. Each entry is a non-empty node ID. An empty list permits no node. Merging intersects this list with the other sources’ lists.

nodes:
allow: [local]
  • Type: list of strings
  • Required: no

Nodes that may not run the work. Each entry is a non-empty node ID. Merging unions this list with the other sources’ lists, and deny wins over allow.

nodes:
deny: [build-box]
  • Type: map of harness ID to list of strings
  • Required: no

The agent harness’s own tools to take back. Each key is a harness ID, and each list names tools as the harness names them. Barry rejects a name the harness does not offer. It applies only to native tools, never to the tools Barry serves. See enforcement coverage.

nativeTools:
claude-code: [WebFetch, WebSearch]
  • Type: list of strings
  • Required: no

Tools to remove. Each entry is a namespace or a tool name, matched without regard to case, and a match removes the tool from the session’s tool list. Some names also take back a category of native tools, such as Bash for the native shell.

deniedTools: [Bash, Write, Edit]
  • Type: list of strings
  • Required: no

Write access to remove. write removes every write tool. A namespace or a tool name, matched exactly, removes the write tools it names. Read tools stay. write also takes back the native shell and native file writes.

deniedAccess: [write]
  • Type: object
  • Required: no

Path restrictions, checked on the path fields of Barry’s file tools. A non-empty deny or any allowOnly removes Barry’s Bash, and either key takes back the native shell, file reads, and file writes. See patterns.

files:
deny: ["*.env", "~/.ssh/**"]
  • Type: list of strings
  • Required: no

Path patterns to deny. Barry checks both the path as written and its absolute form, and refuses a path that matches any pattern. Merging unions the lists.

files:
deny: ["*.env", "*.pem"]
  • Type: list of strings
  • Required: no

The only paths the session may reach. Barry refuses every path that matches none of the patterns, and deny wins when a path matches both. Each entry starts with /, ~/, a drive letter, or \\, or equals ~; the schema rejects relative paths. An empty list permits no path, and merging intersects the lists.

files:
allowOnly: ["~/repos/vantage/**"]
  • Type: object
  • Required: no

Shell command restrictions, checked on Barry’s Bash tool. A non-empty list in either key takes back the native shell.

bash:
denyPrograms: [git, gh]
  • Type: list of strings
  • Required: no

Deprecated. Barry refuses a command that contains any entry as a substring, which misses git -C and matches legit. Use denyPrograms instead.

bash:
deny: ["rm -rf"]
  • Type: list of strings
  • Required: no

Programs to deny, as program or program:subcommand. Barry matches every command in the line, through wrappers such as env, sudo, and sh -c, and refuses a command it cannot parse.

bash:
denyPrograms: [git, "gh:pr:create"]
  • Type: object
  • Required: no

Network restrictions. Any rule in it takes back the native shell and native network tools. Barry rejects a network object that sets allowDomains without enforce: sandbox.

network:
actions: [write]
  • Type: list of strings
  • Required: no
  • Values: all, write, read, git:push, git:fetch, http:write, http:read, ssh:write, ssh:read, dns

Network operations to deny. A parent tag denies its children, so write covers git:push, http:write, and ssh:write. The schema rejects an unknown tag. See network actions.

network:
actions: ["git:push"]
  • Type: list of strings
  • Required: no

Destination hosts to deny. An entry matches the host and every subdomain. Barry reads URLs from Bash commands and from WebFetch, and misses URLs built at runtime.

network:
domains: ["*.internal.example.com"]
  • Type: list of strings
  • Required: no

The only hosts the egress sandbox lets through. It requires enforce: sandbox. Under the sandbox, an absent list means no egress except to localhost, and a host in domains stays denied. Merging intersects the lists.

network:
enforce: sandbox
allowDomains: [registry.npmjs.org]
  • Type: string
  • Required: no
  • Values: guard, sandbox

The enforcement level. An absent value means guard: Barry checks tool calls and shell commands. sandbox adds the agent runtime’s egress proxy, and a hosted session that cannot get the sandbox refuses to start. sandbox wins when bounds merge. See enforcement levels.

network:
enforce: sandbox

Barry’s builtin readonly bound: no shell, no write tools, and no recognized network writes.

name: readonly
description: "Denies supported write tools, Bash, and recognized network writes"
deniedTools: [Bash, Write, Edit]
deniedAccess: [write]
network:
actions: [write]

Denies every recognized network operation, and asks for the egress sandbox with an empty allowlist.

name: sandboxed-offline
description: "Requests proxy enforcement on supported harnesses"
network:
actions: [all]
enforce: sandbox
allowDomains: []

Confines file tools to one repository and denies its secret files, even inside it.

name: vantage-only
description: "File tools reach only the vantage repository, never its secrets"
files:
allowOnly: ["~/repos/vantage/**"]
deny: ["*.env", ".env.*", "*.pem", "*.key"]