Skip to content

For agent authors

Seal is agent‑agnostic by design. The standalone CLI is the reference implementation for CI and local pin/verify workflows. The other half of the security contract, verifying a bundle immediately before loading any code from it, belongs to each agent.

This page summarises what an agent must do to integrate Seal natively. The normative source is SPEC.md §Implementation Notes; when in doubt, the prose spec wins.

For agent developers adding native support:

  1. Verify each project‑local bundle immediately before loading any code, prompt, hook, script, template, tool definition, or other loadable resource from that bundle.
  2. Apply policy to unverified or mismatched project‑local bundles.
  3. Unconditionally suppress all project‑external extensions in a sealed project.
  4. Expose pin and verify workflows so users can update the lockfile from inside the agent.

Why “immediately before load” and not just “at session start”

Section titled “Why “immediately before load” and not just “at session start””

An implementation MAY verify on session start to surface mismatches early, but session‑start verification alone is not sufficient. Bundles can be modified between session start and bundle load. To provide time‑of‑check / time‑of‑use protection, you MUST verify the bundle immediately before executing anything from it.

In practice this means: hashing happens in the load path, not just at boot.

For a sealed project, your verification set is the set of discovered project‑local bundles that the implementation can identify and load for that project.

Before loading any bundle in that set:

  1. Normalize it to its bundle key.
  2. Classify it against seal.json.
  3. Apply policy.

Crucially:

  • Don’t silently ignore an unmappable artifact. If your agent discovers a project‑local artifact it would load but cannot map to a bundle key under this spec, you MUST treat that artifact as unverified rather than excluding it from the set.
  • Don’t trust other agents’ entries. A repo’s seal.json may pin both Claude‑oriented and Codex‑oriented bundles. Your agent verifies only the project‑local bundles it itself can identify and load. Entries for other agents’ bundles do not affect your verification result.
  • Don’t re‑identify nested components separately. If you load an enclosing bundle, the bundle is the unit; nested components are covered by the bundle’s files and contentHash.

Unifying with the standalone tool’s verification set

Section titled “Unifying with the standalone tool’s verification set”

The standalone CLI builds its verification set from the lockfile plus discovery expansion. It does not model your agent’s native loading context. Native integrations are richer:

Source Used by standalone CLI Used by native agent
bundles keys in seal.json ✓ ✓
discovery patterns in seal.json ✓, including matched directory roots and regular-file roots ✓ (recommended)
Agent‑specific native discovery (e.g. registered plugin paths) ✗ ✓
Format‑specific heuristics ✗ (CI must be deterministic) ✓ at authoring time only

Your native verification set should be the union of these sources, with each member mapped to its bundle key and then classified against the lockfile.

In a sealed project, project‑external extensions (user‑level, home‑directory, organization‑level, global, admin, cache‑installed) MUST be unconditionally suppressed. policy does not override this.

Concretely:

  • If your agent normally loads skills from ~/.your-agent/skills/, suppress those when seal.json exists at the project root.
  • Document this behaviour clearly so users know what changes when they seal init.
  • Do not provide a flag to bypass it. The point of a sealed project is the isolation.

If you cannot suppress a project‑external extension (because of platform constraints or a host bug), the overall outcome is Blocked. The project’s seal cannot be honoured.

Use the same four overall outcomes the spec defines, Verified, Drift, Warning, Blocked, so users see consistent terminology across tools.

For agents that emit machine‑readable output, follow the standalone CLI’s JSON format so downstream tooling can consume both:

{
"status": "Blocked",
"verified": [...],
"unverified": [...],
"removed": [...],
"mismatch": [...]
}

You MAY include additional diagnostic metadata, but MUST preserve those five fields exactly.

Users need a way to:

  • Bootstrap seal.json from inside the agent (seal init equivalent).
  • Re‑pin a bundle after a legitimate update.
  • See the current verification status without leaving the agent.

You can implement these by shelling out to the seal binary (simple, reuses the canonical implementation), or by integrating the spec directly. Either way:

  • Honour the deterministic serialization rules. Two implementations writing the same lockfile state MUST produce byte‑identical files.
  • Never bypass the user confirmation when pinning. SPEC forbids -y / --force mechanisms.
Pitfall What goes wrong
Verifying once at session start Bundles modified mid‑session load unverified. Fix: hash at load time.
Re‑hashing only when timestamps change Filesystem timestamps are not part of integrity. Always recompute the hash.
Following symlinks during hash Symlinks and other non-regular files are unsupported in Seal v1. They abort pin and produce Mismatch during verify.
Treating Removed as an integrity failure Removed is presence drift, not executable risk. It alerts the user but does not by itself block loading.
Loading project‑external extensions in a sealed project They must be suppressed regardless of policy.
Allowing policy: "warn" to silence everything Project‑external extensions are still suppressed, the invalid‑lockfile fail‑closed rule still applies, and Mismatch still surfaces. warn only changes the loading decision for unverified/mismatched project‑local bundles.

Everything on this page maps to specific sections of the spec:

The spec repository is at github.com/SamyGhannad/seal-spec. If you have implementation questions or believe a behaviour is under‑specified, file an issue there.