zotfile agents

Package agent behavior, skills, requirements, and permissions into a portable .zot file.

A zotfile is an agent you can share like a file. It packages an agent's persona and standing instructions, reusable skills, requirements, and enforced tool permissions into one portable .zot artifact. The user runs it locally with their own model credentials, in their own workspace, using zot as the runtime.

Local runtime

The current release supports local directories, local .zot archives, and temporary execution from public GitHub agent-directory URLs. OCI registries, signing, installation, updates, bundled executable extensions, network permissions, and environment permissions are future work and are not implied by the commands documented here.

Create an agent

A source directory needs manifest.json and AGENT.md. Add skills when the agent has procedures that should be loaded only for relevant tasks.

layout
code-reviewer/
  manifest.json
  AGENT.md
  skills/
    review-change/
      SKILL.md
  assets/       # optional static files
  README.md     # optional human documentation
manifest.json
{
  "zotfile": 1,
  "name": "code-reviewer",
  "version": "0.1.0",
  "description": "Reviews a repository without modifying it.",
  "runtime": {
    "min_zot": "0.2.76"
  },
  "model": {
    "requires": ["tools", "reasoning"],
    "min_context": 64000,
    "preferred": []
  },
  "permissions": {
    "fs": {
      "read": ["${workspace}"],
      "write": []
    },
    "bash": {
      "mode": "none"
    }
  },
  "requirements": {
    "bin": ["git"],
    "os": ["darwin", "linux", "windows"]
  },
  "entry": {
    "greeting": "What should I review?",
    "default_prompt": null
  },
  "replace_system_prompt": false
}

Local names are flat and lowercase. They may contain letters, digits, dots, hyphens, and underscores. Registry-style namespace/agent names are not accepted by the local runtime yet. Versions should use semver, although semver is not currently validated.

Write the behavior

Put the agent's role, workflow, constraints, and output expectations in AGENT.md. By default it is appended to zot's normal system prompt, so the agent keeps zot's standard tool-use and safety guidance.

AGENT.md
# Code reviewer

Review the current repository without modifying it.

Prioritize correctness, security, regressions, and missing tests. Report
findings in severity order with file and line references. Stay grounded
in the code and do not invent failures.

Set replace_system_prompt to true only for a fully specialized agent that should replace zot's default system prompt rather than extend it. Capability and security claims belong in the manifest, not in agent-authored prose.

Bundle skills

Skills use the normal SKILL.md format under skills/<name>/SKILL.md. zot adds bundled skills to discovery while the agent runs. The model sees each skill's name and description, then loads the full body with the skill tool only when it applies.

skills/review-change/SKILL.md
---
name: review-change
description: Review the current Git diff for correctness and missing tests.
---

# Review change

1. Read the complete diff and every changed file.
2. Run focused tests when permitted.
3. Report actionable findings with file and line references.

See Skills for discovery rules and authoring guidance. Ordinary files under assets/ are included in the artifact, but are not automatically placed in model context or granted filesystem access.

Declare permissions

zotfile permissions are an enforced ceiling for the built-in file and bash tools. Empty or omitted filesystem scopes deny access. Keep declarations as narrow as the agent's job allows.

PermissionCurrent behavior
fs.readPaths the read tool may access.
fs.writePaths the write and edit tools may modify.
bash: noneReject every bash tool call. This is the default.
bash: askAllow bash after fresh consent on every agent launch.
bash: allowlistAllow only listed command names and simple pipelines.

Use ${workspace} for the run's working directory and ${agent_data} for persistent private storage at $ZOT_HOME/agents/<name>/data/. Relative permission paths resolve beneath the workspace. Canonical path checks prevent file tools from escaping a scope through symlinks.

manifest.json
{
  "permissions": {
    "fs": {
      "read": ["${workspace}", "${agent_data}"],
      "write": ["${agent_data}"]
    },
    "bash": {
      "mode": "allowlist",
      "allow": ["git", "go"]
    }
  }
}

Bash ask mode

In the current local runtime, ask means launch-time capability consent. It does not open a separate confirmation dialog for each bash call. Allowlist mode rejects substitution, redirection, backticks, newlines, and commands not present in allow.

Unsupported permissions

Non-empty permissions.net.allow and permissions.env.read declarations are rejected because the local runtime cannot enforce them yet. Bundled executable extensions are rejected for the same fail-closed reason.

Set requirements

Use runtime.min_zot for the minimum runtime, requirements.os for supported operating systems, and requirements.bin for programs that must already exist on PATH. zotfiles have no install or postinstall hooks.

Model requirements are provider-neutral. model.min_context sets the minimum context window. model.requires accepts tools and reasoning. vision is recognized but currently fails closed because vision support is not represented in the model catalog. Unknown capabilities and a non-empty model.min_tier are rejected.

zot keeps an explicitly selected or configured default model when it qualifies, then tries model.preferred, then another compatible active model. It stops with a clear error when no catalog model satisfies the requirements.

Test and package

shell
# Develop directly from the source directory
zot inspect ./code-reviewer
zot run ./code-reviewer
zot run ./code-reviewer "Review the authentication package"

# Create and validate the portable artifact
zot pack ./code-reviewer
zot verify ./code-reviewer.zot
zot inspect ./code-reviewer.zot
zot run ./code-reviewer.zot

# Run directly from a public GitHub repository
zot run https://github.com/patriceckhart/agents/zot-maintenance \
  --cwd /path/to/zot
CommandWhat it does
zot run <path> [prompt]Run a local source directory, .zot archive, or public GitHub agent-directory URL with normal zot flags after the reference.
zot pack [dir] [output]Validate and create a canonical zstd-compressed .zot archive, then print its SHA-256 digest.
zot inspect <path>Show identity, digest, permissions, and files without executing the agent.
zot verify <path>Validate the local artifact and print its digest. Publisher signatures are not implemented yet.

Packed archives have sorted entries, normalized tar metadata, and fixed timestamps. Symlinks are rejected. Extraction rejects absolute paths and parent traversal and limits the archive to 100 MiB compressed, 64 MiB per entry, and 256 MiB expanded. For a GitHub URL, zot downloads the public repository archive to a temporary directory and removes it when the command exits. The short github.com/owner/repo/path form uses the default branch; standard github.com/owner/repo/tree/ref/path URLs select a branch or tag.

Before an agent runs, zot prints its identity and expanded permissions and asks the user to approve them. Approval is cached for the exact artifact digest, except for bash: ask, which requests consent on every launch. Any artifact change creates a new digest and requires approval again.

Non-interactive runs refuse to bypass consent by default. Controlled automation can set ZOT_AGENT_CONSENT=1, but should do so only after independently inspecting and trusting the exact artifact.

Agent history is isolated under $ZOT_HOME/sessions/agents/<name>/, so packaged-agent sessions do not bleed into ordinary zot sessions or another agent's history. Normal session flags such as --continue, --resume, and --no-session still apply.