Pattern Syntaxes

Three consolidated pattern syntaxes are used throughout the framework. Each has one implementation shared across all contexts.

Glob Patterns (matchPattern)

Real glob matching via picomatch, extended with #tag selectors and (specifier) grammar.

Syntax:

Pattern Matches Example
* Anything * matches all tool names
exact Exact string file-read matches only file-read
prefix-* Glob wildcard file-* matches file-read, file-read-all
{a,b} Brace expansion {file-read,file-write} matches exactly those two
[abc]* Character class file-[rw]* matches file-read, file-write
? Single character file? matches files, filed
#tag Tag selector #meta-internal matches tools with that tag

Specifier grammar (appended to any pattern):

pattern(key=value,key2=value2,$deny,$policy=allow)

Keys starting with $ are meta directives ($deny, $policy=allow). Other keys are argument constraints checked at call time. Brace expansion works inside specifier values: op={finish,fail}.

Used by:

  • allowed-tools — agent tool filtering
  • trust.rules — trust policy rules
  • trust store — pattern-based trust decisions
  • roles — identity matching (e.g., *@mycompany.com)
  • Arg constraint values in specifiers
  • Profile route matching (transport middleware routes: config for email, slack, webhook)

Path Expressions (pathGet / pathSet / pathQuery / pathRemove / pathKeys)

Unified path access with three auto-detected tiers. One syntax, multiple operations.

Syntax:

Tier Grammar Detection Example
Simple a.b.c No [, no $ prefix config.model.region
Indexed a[0].b or a.0.b Has [ or numeric segment args.items[0].name
JSONPath $.a[?(@.x)] Starts with $ or contains ?( $.paths[?(@.external)]

Simple and indexed tiers use a lightweight parser (no library). JSONPath tier delegates to jsonpath-plus.

Operations:

Function Returns Use case
pathGet(obj, expr) Single value or undefined Read a property
pathQuery(obj, expr) Array of all matches Multi-match (filters, wildcards)
pathSet(obj, expr, value) void (mutates) Write a property, creating intermediates
pathRemove(obj, expr) void (mutates) Delete matched paths
pathKeys(obj, exprs) Set<string> of top-level keys Resolve expressions to key names

Used by:

  • :context[path] directive — read from ctx
  • :config[path] directive — read from ctx.locals.config
  • ctx.manager.get(path) / ctx.manager.set(path, value) — programmatic access
  • ${path} — string interpolation resolves via pathGet(ctx, path) (e.g., ${config.workspace}, ${config.paths[0]})
  • Session capture paths (e.g., "locals.agent.trace", "args.items.0")
  • Session key resolution (e.g., "nonlocals.gateway.id")
  • roles key — identity extraction
  • trust key — per-user trust file partitioning
  • CLI --arg a.b.c=v / --config / --local / --global
  • Environment variable overrides (AGENT_APPS_CONFIG_MODEL__REGION)
  • $private / $public / $dynamic / $static — key-name lists (bare keys or JSONPath)
  • $remove — delete expressions
  • $order — array element ordering (JSONPath keys)
  • $merge — sub-key policies (e.g., "$.mcp.headers": "deep")

$-Prefix Convention (MetaKey / isMetaKey)

All $-prefixed keys are structural/meta — never user data, never tool invocations. The $ prefix cannot collide with tool names ([a-z0-9-] only). The MetaKey type (\$${string}`) and isMetaKey()` guard formalize this convention.

Known $-keys by domain:

Domain Keys
Cascade annotations $inherit, $private, $public, $local, $global, $dynamic, $static, $merge, $order, $remove, $self, $hook
Session capture $all, $args, $result, $agent
Args $context (generic: any $key in args maps to invoke options)
Phase sentinels $pre-configure, $configure, $post-configure, $pre-execute, $execute, $post-execute

Unknown $-keys in metadata trigger a warning from extractAnnotations — this catches typos like $pubic without breaking extensibility.

Ask AI