canonical — AgentTeamsModule¶
Durable exploded on-disk canonical agent format (durable-canonical-agent-format plan §5.5).
Source:
agentteams/canonical.py
Expands the Canonical Agent Interface (CAI) dict produced by interop.export_to_cai into a
human-editable directory form, and reads it back losslessly.
Public Constants¶
TEAM_FILE_NAME("team.cai.json"): the format's identity marker;detect_frameworkrecognition of a canonical directory keys on its presence (Phase F).DEFAULT_CANONICAL_SUBDIR(".agentteams/canonical"): default location convention under a project root, reusing the established.agentteams/control-directory convention (.agentteams/brief.jsonis the existing precedent).
Public Types¶
CanonicalMaterializeResult¶
Summary of a materialization run.
Fields:
written: paths (relative to the output dir) written — or planned, under dry-run.dry_run: whether the run was simulated.
Property:
success:True(validation errors raise before any write).
Public Functions¶
materialize_canonical(cai, out_dir, *, dry_run=False)¶
Writes the exploded directory form:
team.cai.json— project-level data:schema_version,created_at, source metadata (source_framework,source_dir),instructions_binding,mcp_servers,framework_extensions, and any other top-level keys the CAI dict carries (forward-compatible pass-through). Agents, skills and references are NOT duplicated here — they explode to files.agents/<slug>.md— YAML front matter (slug,name,description,source_path,capabilitieswith the canonical tool-scope vocabulary,handoffs, optionalraw_front_matter) plus the body markdown; a captured invariant-core fenced span is appended to the body (same convention asinterop.import_from_cai).skills/<slug>/SKILL.mdplus co-located files, written verbatim (byte-faithful, so captured front matter survives unchanged).references/**— non-agent reference content from the CAIreferenceslist, restored at its recordedrel_path.
All writes go through atomicio._atomic_write_text; dry_run=True collects the planned writes
with zero filesystem side effects (not even mkdir). Raises ValueError when the CAI dict fails
schema validation (_validate_cai, checked before any write) or contains other malformed input
(missing/invalid agents, unsafe slugs, escaping reference paths) so bad input never half-writes.
load_canonical(dir_path)¶
The inverse: reads the exploded directory back into exactly the shape interop.export_to_cai
emits. team.cai.json supplies project-level fields; agents are reassembled from
agents/*.md (the invariant-core span re-lifted with the same capture helper so the export
shape is reproduced exactly); skills from skills/*/SKILL.md; references from the
references/ tree when present. Agents and skills are sorted by slug. Raises
FileNotFoundError when team.cai.json is absent, and ValueError when the reassembled CAI
dict fails schema validation (_validate_cai, called after reassembly).
Serialization Contract¶
Front matter is Markdown + YAML deliberately: it diffs and hand-edits far better than JSON and
matches every framework's file style except Goose. Every string value is emitted as a JSON
double-quoted scalar (a strict YAML subset), so loading needs no PyYAML — a test-only
dependency. load_canonical prefers yaml.safe_load when importable (hand-edit tolerance) and
falls back to a built-in parser covering exactly the subset this module emits.
Slugs are restricted to [A-Za-z0-9][A-Za-z0-9._-]* and reference paths refuse absolute paths
or .. segments, keeping materialization traversal-proof.
Round-trip guarantee¶
load_canonical(materialize_canonical(export_to_cai(src))) reproduces the export dict exactly
for every supported source framework (verified for copilot-vscode including all handoffs, and
for claude including skills and invariant-core spans).
See also¶
multi_sync— the pinned-sync orchestrator that consumes this canonical hub.