Agent-First Data v0.22: What the Four Languages Actually Share
v0.22 redraws the four-language line. Skill admin and stream redirection shipped in all four SDKs but only Rust ever used them — dead parity weight that could rot silently, and did: `afdata skill install` was dropping the references/ files next to SKILL.md. v0.22 fixes the installer to bundle the whole skill as first-class assets, then removes skill admin and stream redirection from the Go, Python, and TypeScript SDKs. The four languages now synchronize on exactly the convention plus the CLI helpers — the shared contract, and nothing else.
The pitch has always been the same in four languages. But that promise had
quietly grown fuzzy. Two capabilities — skill admin (install a spore’s
SKILL.md into an agent’s skills directory) and stream redirection (fd-level
--stdout-file / --stderr-file) — shipped in all four SDKs: Rust, Go, Python,
and TypeScript, each with a full test suite.
Nobody outside Rust ever called them. Every spore CLI is Rust; the Go, Python, and TypeScript copies were parity for parity’s sake — hundreds of lines each, maintained, tested on every run, and free to rot unnoticed.
It’s a breaking release; AFDATA is still pre-1.0 and carries no compatibility layer.
Dead parity rots
And it did rot. afdata skill install writes a skill into ~/.codex/skills,
~/.claude/skills, and the rest — except it was writing only SKILL.md, and
silently dropping the references/ files sitting right next to it, even though
SKILL.md points the agent straight at them. The installer’s spec knew about a
single embedded file; the whole idea of a skill directory had never reached
it. No amount of reinstalling could fix an install that the installer didn’t
know was incomplete.
That’s the tell. A capability with no real consumer isn’t free — it’s a place for bugs to hide until the one caller that does exist trips over them.
The fix: a skill is a directory
v0.22 teaches the Rust installer what a skill actually is. Alongside SKILL.md,
a SkillSpec now carries its bundled assets — the references/ tree, or
any file a skill ships:
SkillSpec {
name: "agent-first-data",
source: SKILL_SOURCE,
assets: &[
SkillAsset { path: "references/rules.md", contents: RULES },
SkillAsset { path: "references/registry.json", contents: REGISTRY },
// ...
],
// ...
}
Install writes the whole tree, atomically and inside the skill directory (an
asset path can’t escape it). status now folds the assets into its currency
check — a SKILL.md-only install reports not current, so a plain reinstall
repairs it instead of leaving you to guess. uninstall removes them and their
now-empty directories. A packaging smoke test installs to a scratch directory
and asserts every file in the skill landed, so the installer can’t quietly lose
a reference again.
The trim: Rust-only means Rust-only
Then the honest part. Skill admin and stream redirection are gone from the Go, Python, and TypeScript SDKs. They live only in the Rust crate now — where the spore CLIs that actually use them live too.
So the same in four languages means exactly what it should: the naming
convention, structure-preserving output and redaction, the protocol builders
and reader, and the CLI helpers that emit them. That shared contract is
identical across Rust, Go, Python, and TypeScript. The Rust crate additionally
carries the tools it alone needs — skill admin, stream redirection, tracing, and
clap-aware help — and those are not part of the cross-language promise. The line
is now stated plainly in the README, in the spec, and enforced by
spec/api-surface.json.
The three non-Rust SDKs got about three thousand lines lighter, their test suites faster, and one whole class of drift — a Rust feature landing while its Go/Python/TS twins fall behind — designed out of existence.
The shape now
Four languages, one contract you can point at. The convention and the helpers that carry it are identical everywhere; the spore-authoring tooling lives where the spores are. A skill installs as the directory it is. Less surface, fewer places to rot, and a four-language promise that means what it says.