A vendor-neutral JSON protocol for defining agentic automations.
Metalflow codifies two composable, plain-JSON document kinds:
- Persona — a reusable agent definition: an identity, a scoped set of capabilities (tools, packs, skills), and a system prompt. Who does the work.
- Flow — a human-authored directed graph that orchestrates agent work node by node, with deterministic and LLM-driven branching. What happens, in what order, under what conditions.
They compose: a Flow's LLM-backed nodes (prompt, branch, sub_agent) name a
Persona by slug; a Persona names the tools, packs, and skills it may use. Both
are just JSON — hand-editable, diffable, storable in a file or a database.
The protocol is vendor-neutral: it fixes the document shapes, identifier
grammars, node/data schemas, state model, and the failure convention — but the
actual tools, packs, and skills a Persona references are named, not embedded, and
resolved by whatever runtime executes the document.
Why adopt this? Why a Metalflow-style protocol improves testability & reliability — the case for replacing monolithic per-agent Markdown with structured, schema-backed documents.
PROTOCOL.md The normative specification
schema/
metalflow.persona.schema.json JSON Schema (2020-12) for Persona documents
metalflow.flow.schema.json JSON Schema (2020-12) for Flow documents
metalflow.agent.schema.json JSON Schema (2020-12) — optional Agent bundle
examples/
personas/research-agent.json
flows/madrid-weather.json branch + conditional + error-rail
flows/linear-task-worker.json scheduled sub_agent → end
agents/ticket-triage.json bundle: personas + flows + run_conditions
docs/
WHY_METALFLOW_FOR_AGENT_ORCHESTRATION.md see "Why adopt this?" above
See docs/WHY_METALFLOW_FOR_AGENT_ORCHESTRATION.md for the rationale.
-
Persona and Flow are the core (see above).
-
Agent Definition is an optional bundle that packages one named agent — its
personas, itsflows, and itsrun_conditions— into a single self-contained file. Arun_conditionis a discriminated union:scheduled(with acronexpression) ortriggered(manual, no properties). See PROTOCOL.md §9.{ "name": "Ticket Triage Agent", "personas": [ /* Persona */ ], "flows": [ /* Flow */ ], "run_conditions": [ { "type": "scheduled", "cron": "*/15 * * * *" }, { "type": "triggered" } ] }
{
"spec_version": "2",
"id": "madrid-weather",
"name": "Madrid weather check",
"created_at": "2026-07-27T00:00:00Z",
"updated_at": "2026-07-27T00:00:00Z",
"enabled": false,
"flow": {
"nodes": [
{ "id": "entry", "node_type": "entry", "data": { "schedule_type": "manual" } },
{ "id": "get_temp", "node_type": "branch", "data": {
"query": "Temperature in Madrid right now, in °F?",
"persona": "weather-agent",
"outputs": [
{ "handle": "report_temp", "schema": { "type": "integer" } },
{ "handle": "error", "schema": { "type": "string" } }
]
} }
],
"edges": [ { "id": "e0", "source": "entry", "target": "get_temp" } ]
}
}{
"name": "Research Agent",
"description": "Explores codebases and answers questions without modifying files",
"tools": ["read_file", "grep", "load_skill"],
"packs": [],
"skills": ["explore-codebase"],
"system_prompt": "You are a research assistant. Working dir: {{cwd}} ..."
}The persona's slug is its filename stem (research-agent) — the value a Flow
node's persona field selects.
Any JSON Schema 2020-12 validator works. For example, with
ajv:
npx ajv-cli validate -s schema/metalflow.flow.schema.json -d "examples/flows/*.json" --spec=draft2020
npx ajv-cli validate -s schema/metalflow.persona.schema.json -d "examples/personas/*.json" --spec=draft2020
npx ajv-cli validate -s schema/metalflow.agent.schema.json -d "examples/agents/*.json" --spec=draft2020Every schema is self-contained — each validates on its own with no network
access and no other files loaded. The agent bundle embeds the persona and flow
schemas under its $defs, so it needs no -r references.
The Flow half of this protocol supersets the
metalcraft-flows Flow SPEC v2,
which is the reference Rust implementation of the flow graph (parse, validate,
walk). Metalflow adds the formal Persona definition — previously referenced
only by name — plus the identifier and skill-frontmatter conventions that bind
Personas, tools, packs, and skills together into one protocol.
Two independent axes (see PROTOCOL.md §6):
- Protocol version — this umbrella, currently
1. - Flow
spec_version— the flow-graph format, currently"2"(supersets"1").
MIT — see LICENSE.