The agent format
A UAP agent is one YAML document — agent.uap.yaml — plus the files it references. Together they form a bundle: plain, committable, secret-free.
This page tours every component. The normative specification (grammar, canonical form, digests, adapter contract) lives in SPEC.md, with a machine-readable JSON Schema.
The document
From the smallest valid agent to every component in one document — the spec's Appendix A example — annotated section by section:
uap: 1 agent: name: Docs Helper description: Answers questions about the docs/ folder.instructions: - name: core content: text: | You are the docs helper. Answer using the docs/ folder. Cite file paths. If unsure, say so.
Only uap and agent are required — with these two fields this is already a valid, installable bundle.
Any content-bearing field takes content: { text: ... } inline or content: { file: uap/... } pointing at a sidecar file — exactly one of the two.
Instructions
The agent's standing guidance — what harnesses variously call the system prompt, CLAUDE.md, AGENTS.md, or rules. UAP models it as an ordered list of blocks with an activation mode, so one schema covers single-file harnesses and rules-directory harnesses alike:
instructions:
- name: core # always active (default)
content: { file: uap/instructions.md }
- name: frontend-rules # attached when matching files are touched
description: Conventions for the web app
activation: auto
paths: ["apps/web/**"]
content: { file: uap/rules/frontend.md }
- name: release-checklist # only when explicitly invoked
activation: manual
content: { file: uap/rules/release.md }always · auto (with paths globs or a routing description) · manual — these map 1:1 onto Cursor's four rule types, and fold into a managed region of CLAUDE.md/AGENTS.md elsewhere with their scope preserved for a lossless round-trip.
Commands
Reusable prompts invoked by name (slash commands):
commands:
- name: triage
description: Triage an incoming bug report
arguments_hint: "<issue-url>"
content: { file: uap/commands/triage.md }Bodies may use $ARGUMENTS (everything after the command) and $1–$9 (positional). Adapters translate to their harness's substitution syntax or report the command emulated.
Subagents
Named delegates the main agent can hand tasks to:
subagents:
- name: reviewer
description: Deep code reviewer for risky diffs # the routing signal
model: { id: claude-opus-4-8 }
tools: [read, grep, glob] # neutral tool names
content: { file: uap/agents/reviewer.md }tools uses harness-neutral names (read, bash, web_fetch, …); adapters map them to native tool names where the harness supports an allowlist.
Skills
References to skill packages — a directory with a SKILL.md plus supporting files, per the cross-harness Agent Skills convention:
skills:
- source: ./uap/skills/lint-fixer # local, in-bundle
- source: registry:acme/summarize@^2.0 # registry (pinned range)
- source: github:owner/repo/skills#main # git hostsMCP servers
The agent's tool connections. Transports: stdio, http, and legacy sse:
mcp_servers:
- name: filesystem
transport: stdio
command: npx
args: ["-y", "@modelcontextprotocol/server-filesystem", "."]
- name: search
transport: http
url: https://search.example.com/mcp
headers:
Authorization: "Bearer ${SEARCH_TOKEN}" # placeholder, never a valueSecrets — declared, never valued
Bundles are designed to be committed, so secret values are banned by the spec. Credentials appear only as ${NAME} placeholders, declared under secrets and resolved at install time (environment → local secrets file → prompt). The validator scans for real-looking credentials and fails the bundle if it finds any.
secrets:
- name: SEARCH_TOKEN
description: API token for the search MCP
used_by: [mcp_servers/search]Hooks, setup, permissions, env, files
The remaining components round out the agent's runtime shape:
hooks: # lifecycle commands
- event: pre_tool_use
matcher: bash
run: { command: "./uap/hooks/guard.sh" }
setup: # one-time bootstrap (never auto-run)
commands:
- pnpm install
permissions: # tool rules: deny > ask > allow
allow: [{ tool: bash, match: "pnpm *" }]
deny: [{ tool: bash, match: "rm -rf *" }]
env: # non-secret environment
NODE_ENV: development
files: # verbatim extras
- source: uap/files/ONBOARDING.md
target: ONBOARDING.mdFormat guarantees
- Canonical form — fixed key order and emission rules mean two semantically equal documents are byte-identical.
- Round-trip law — for every component an adapter declares native,
pack(unpack(D)) ≡ D, verified by digest in the conformance suite. - Forward compatibility — unknown fields are preserved, never rejected;
x-*keys and a namespacedextensionsblock carry harness-specific data.
See the full worked example — examples/showcase — an engineering agent using every component, then check where each piece lands per harness.