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). Itscurrent_version_idpoints at the version a dispatch runs by default. - Version — an immutable snapshot of the agent's code: a
path → contentfile map plus anentrypoint. 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
sha256digest 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
- Register an agent on the Operate → Agent Registry page (or
POST /api/v1/agent-registry/). - Add a version — paste your entrypoint code. The first version auto-promotes.
- 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.) - 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.
| Method | Path | Purpose |
|---|---|---|
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}/versions | Create an immutable version |
GET | /api/v1/agent-registry/{id}/versions | List 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:
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.