Documentation

The Universal Agent Format

Every adapter reads its platform into the same document and writes the same document back out. The document is JSON validated with a published JSON Schema (run nomad schema to write it), with Markdown for long form content such as instructions, persona and memory.

Package layout

A .nomad file is a ZIP archive you can open with any unzip tool and read as plain Markdown. It holds only what the agent has: a typical agent is about eight files.

nomad.json         id, name, model, policy, provenance, file hashes, signature
AGENTS.md          instructions, one ## section each
SOUL.md            persona
MEMORY.md          memory entries as bullets under their kind
memory/<slug>.md   long entries such as documents and daily logs
skills/<name>/     SKILL.md and its files
routines/<id>.json schedule ("0 7 * * *", "every 2h"), prompt, paused state
tools.json         MCP servers, with ${VAR} where a secret goes
files/...          knowledge files, only when asked for

nomad.json lists the SHA-256 of every file, so any change is caught. When the package is signed, an Ed25519 signature covers nomad.json and through it every file. Local absolute paths are never written; provenance is kept as platform:relative/path. Nomad still reads the older .agentpack layout.

Interchange archives

Nomad also reads and writes .jetpack archives, the flat layout used by other agent portability tools: jetpack.json, AGENTS.md, SOUL.md, MEMORY.md, memory/, routines/, skills/ and files/. Import them anywhere a package is accepted, or export with nomad export <agent> --format jetpack. Parts the layout cannot hold, such as MCP tools, travel in an x-nomad manifest key that other readers ignore. These archives carry no integrity hashes and cannot be signed, so Nomad says so when it reads one.

Identity

Every agent has a permanent ULID. Nomad writes it into the destination as a hidden marker (for example <!-- nomad:begin agent=01J... -->) and also keeps a local mapping of every location it has written to, so reading the agent back on any platform recognises it instead of creating a duplicate. nomad duplicate creates a copy with a new identity on purpose.

Memory

Memory is a list of entries, never one blob. Each entry has a kind (profile, preference, fact, project, instruction, note, summary, daily log, document), a scope (user, agent, project), optional title, date and tags, and where it came from. Nomad never invents memory and never merges unrelated entries. When a destination stores memory differently it writes the closest form and the report says what changed, for example Hermes keeps entries in MEMORY.md separated by § and drops titles.

A static export cannot reproduce a platform's internal retrieval or ranking. Nomad moves the content, not the search index.

Skills, tools and integrations

Skills follow the Agent Skills layout (SKILL.md with frontmatter, plus files). Claude Code slash commands and Codex custom prompts are kept as manually invoked skills and converted into each other. Tools are MCP server definitions. A tool definition does not mean the destination can run it, so the report lists the setup steps. Secret values are never packaged by default; they become references such as { "secretRef": "GITHUB_TOKEN" }.

Workflows

Routines keep their trigger (cron expression, interval, one time or event), timezone, prompt and attached skills. sourceEnabled records whether the routine was active where it came from. Imported routines always have enabled: false; you switch them on at the destination after reviewing them.

Permissions

A policy has a mode (ask, auto, read-only) and rules with a capability (read, write, file, shell, network, browser, computer, schedule, tool, integration), an effect (allow, ask, deny) and an optional pattern. Adapters translate rules into the native system when there is one, and Nomad compares the destination policy before and after every migration. Anything broader needs explicit approval, and restrictions the destination cannot enforce are listed.

Extensions and versions

Platform specific data goes into namespaced extension fields such as x-openclaw or x-claude-code. Unknown extensions never make a valid package fail. The current schema version is 1.0; newer readers upgrade older documents, and a package from a newer version is refused with a clear message instead of being half read.