Documentation

Agent registry

v3.2.0 — register your own agent code, version it immutably, promote a current version, and dispatch a specific version to your local runner daemon. The server validates every file bundle; the daemon re-validates before it runs anything.

AuditTrail is a control plane — it orchestrates and governs agent runs but does not host or execute your code. The local runner daemon (see Local runner daemon) runs your agents on a machine you control. The agent registry is how you ship your own code to that daemon, safely.

A built-in template (quickstart / web-search) is materialised by the daemon from its own SDK-shipped scaffold — no code ever crosses the wire. A registered agent is your code: its immutable, validated version bundle is sent down the WebSocket, and the daemon re-validates and writes it into a per-dispatch scratch directory before spawning the entrypoint.

Concepts

  • Definition — a named, user-owned container (e.g. my-research-agent). Its current_version_id points at the version a dispatch runs by default.
  • Version — an immutable snapshot of the agent's code: a path → content file map plus an entrypoint. Versions are numbered monotonically per definition (v1, v2, …). No version is ever edited in place — a "new version" is always a new row with the next number. The first version a definition gets auto-promotes to current.
  • Checksum — a sha256 digest the server computes over a canonical serialization of the bundle. The client never supplies it; it's a stable, auditable fingerprint of exactly what will run.

Bundle validation (the safety core)

Every version create runs the same validator, and the daemon re-runs it before materialising anything. A bundle is rejected (HTTP 422) if any file path:

  • is empty / whitespace-only;
  • is absolute (/foo) or starts with a Windows drive (C:);
  • contains a backslash (\) — bundles are POSIX-relative;
  • contains a .. traversal segment;
  • is not already in canonical POSIX form (no ./, //, trailing slash).

Size caps (also 422 on violation): ≤ 256 KiB per file, ≤ 1 MiB total bundle, ≤ 32 files. The entrypoint must be one of the bundle's file keys and must end in .py.

Because the daemon re-validates with the identical rules, a compromised server still cannot push a traversal/absolute path past your machine. The daemon also writes only under the per-dispatch scratch dir and spawns the entrypoint argv-only (never a shell), so the prompt can never be interpreted as a command.

Workflow

  1. Register an agent on the Operate → Agent Registry page (or POST /api/v1/agent-registry/).
  2. Add a version — paste your entrypoint code. The first version auto-promotes.
  3. Allowlist it on Settings → Runner: add the dispatch reference agent:<definition_id> to your runner allowlist. (Just like built-in templates, an agent must be allowlisted before it can be dispatched.)
  4. Dispatch it from the dashboard — the server resolves the promoted (or a pinned) version, re-validates the bundle, and sends it to your connected daemon.

REST surface

All routes are user-scoped; cross-tenant access returns 404.

MethodPathPurpose
GET/api/v1/agent-registry/List your definitions
POST/api/v1/agent-registry/Create a definition
GET/api/v1/agent-registry/{id}Definition detail
DELETE/api/v1/agent-registry/{id}Delete a definition (+ versions)
POST/api/v1/agent-registry/{id}/versionsCreate an immutable version
GET/api/v1/agent-registry/{id}/versionsList versions
GET/api/v1/agent-registry/{id}/versions/{v}One version (+ files)
POST/api/v1/agent-registry/{id}/promote/{v}Set the current version

Dispatch a registered agent through the existing runner dispatch endpoint:

bash
POST /api/v1/runner/dispatch
{
  "template_id": "agent:<definition_id>",
  "prompt": "research the topic",
  "version": 2          // optional defaults to the promoted version
}

Daemon opt-out

A cautious operator can keep the daemon to SDK-shipped scaffolds only by setting allow_registry_runs = false under [options] in ~/.audittrail/daemon.toml. With it off, the daemon refuses any registered- agent dispatch (exit 126) and runs only built-in templates. It defaults to true; older config files without the key behave as true.