Skip to content

WACP: Taxonomy

  1. Purpose & Design
  2. Registry Model
  3. Envelope Type Registry
  4. Checkpoint Type Registry
  5. Signal Type Registry
  6. Role Registry
  7. Workflow Registry
  8. Taxonomy Validation

The taxonomy is the extensibility layer of WACP. Where PROTOCOL.md defines the coordination primitives — workspaces, envelopes, signals, checkpoints, tasks, trails — the taxonomy defines how those primitives are specialized for a given domain.

The protocol declares that envelopes have a type field. The taxonomy declares which types exist, who can send them, and who can receive them. The protocol declares that roles have permissions. The taxonomy declares which roles exist and what permissions they carry. The protocol declares that workflows have pipelines. The taxonomy declares which workflows are registered and validates their references before execution.

The taxonomy is a registry — a structured catalog of types, roles, and workflows that the protocol enforces at runtime. Nothing unregistered can be used. Nothing registered can be undefined.

The protocol is stable. It defines coordination mechanics that do not change when the domain changes. Workspaces isolate agents whether those agents are writing code, synthesizing research, or managing releases.

The taxonomy is variable. A software development application registers roles like implementer and code_reviewer. A research synthesis application registers roles like source_monitor and synthesis_coordinator. Both applications use the same protocol. They use different taxonomies.

Separating the two allows:

  • The protocol to remain domain-agnostic. It never mentions code, research, or any specific domain.
  • Applications to declare their extensions explicitly. No magic strings, no implicit conventions — every extension is registered and validated.
  • The runtime to enforce completeness. At startup, the runtime loads the taxonomy and verifies that every reference in every workflow resolves to a registered type. Missing registrations are caught before work begins, not mid-run.

The taxonomy inherits the protocol’s principles (PROTOCOL.md §2) and adds three of its own:

Principle T1: Registration before use. Every type, role, and workflow must be registered in the taxonomy before it can appear in a protocol interaction. The runtime rejects unregistered references at startup. This is fail-fast by design — taxonomy errors are configuration errors, caught before any agent is spawned.

Principle T2: Base types are protocol-defined; extensions are application-defined. The protocol defines a minimal set of base types (three envelope types, two checkpoint types, nine signal types, three base roles). These exist in every taxonomy. Applications add domain-specific extensions on top. Extensions never modify base types — they add to the registry, not alter it.

Principle T3: The taxonomy is declarative. A taxonomy is a YAML document, not code. It describes what exists — types, roles, permissions, workflows. It does not describe behavior. Behavior lives in the protocol (how envelopes are validated) and in the application (how agents produce artifacts). The taxonomy sits between them: a contract that both sides reference.


A taxonomy is a single YAML document that declares all types, roles, and workflows available to a protocol instance. The document has a fixed top-level structure:

taxonomy:
id: string # unique identifier for this taxonomy
name: string # human-readable name
extends: string # optional: id of the base taxonomy this builds on
version: string # semantic version
envelope_types: # §3 — registered envelope types
- ...
checkpoint_types: # §4 — registered checkpoint types
- ...
signal_types: # §5 — registered signal types
- ...
roles: # §6 — registered roles (base and derived)
- ...
workflows: # §7 — registered workflows
- ...

Each section is a registry — an ordered list of type definitions. Sections 3 through 7 of this document define the schema and rules for each registry.

The protocol ships with a base taxonomy that every application inherits. The base taxonomy contains exactly the types and roles defined in PROTOCOL.md:

  • Envelope types: directive, feedback, query
  • Checkpoint types: artifact, observation
  • Signal types: ready, started, blocked, checkpoint, complete, failed, integrate, acknowledged, escalation
  • Roles: coordinator, worker, observer
  • Workflows: (none — workflows are always application-defined)

The base taxonomy is implicit. It does not need to be declared in an application’s taxonomy document — it is always loaded by the runtime before any application taxonomy is applied. An application taxonomy extends the base; it never replaces it.

Note on reviewer. The original design included reviewer as a fourth base role. On closer examination, a reviewer is a worker with a different checkpoint type (review instead of artifact), read access to another workspace, and a different envelope type (report instead of query). These are permission overrides, not a different capability level. reviewer is the canonical derived role — defined through inheritance (§6.3), not as a base role. The report envelope type and review checkpoint type are registered alongside the reviewer derived role, not in the base taxonomy.

An application taxonomy declares the domain-specific extensions required by a particular use of the protocol. It uses the extends field to reference the base taxonomy:

taxonomy:
id: mada-swarm-taxonomy-v0.1
name: "mada-swarm taxonomy"
extends: wacp-base-taxonomy-v0.1
version: "0.1.0"
envelope_types:
- id: spec
# ... (defined in §3)
roles:
- name: implementer
extends: worker
# ... (defined in §6)
workflows:
- id: work-then-evaluate
# ... (defined in §7)

An application taxonomy may:

  • Add new envelope types, checkpoint types, roles, and workflows
  • Register derived roles that extend base roles with modified permissions

An application taxonomy may not:

  • Remove or modify base types
  • Remove or modify base roles
  • Redefine a base type’s permissions or semantics
  • Extend another application’s taxonomy (only the base taxonomy is extensible)

This constraint is deliberate. The base types are the protocol’s shared vocabulary. If an application could redefine directive to mean something other than what PROTOCOL.md specifies, cross-application reasoning would break. Extensions add to the vocabulary; they never rewrite it.

Base types use short, unqualified names: directive, worker, artifact.

Application-defined types are not namespaced — they use short names like the base types. Name collisions between an application type and a base type are rejected at registration. The runtime enforces uniqueness across the merged taxonomy (base + application).

This means an application cannot register an envelope type called directive (already exists in base) but can register spec, research_brief, or any name not already taken.

The rationale: namespacing adds syntactic overhead to every protocol interaction (every envelope, every checkpoint, every role reference) for a problem that rarely occurs in practice. The simpler rule — names must be unique — is sufficient and keeps the protocol clean.

To register a type, role, or workflow means to declare it in the taxonomy with all required fields. Registration creates a contract:

  • The runtime guarantees that the registered name is valid for use in protocol interactions (envelopes, checkpoints, role assignments, workflow pipelines).
  • The application guarantees that agents assigned to registered roles will behave according to the role’s declared permissions and checkpoint types.

Registration is not instantiation. Registering a role called implementer does not create an agent — it declares that workspaces may be assigned the implementer role, and that agents in those workspaces will have the permissions the role specifies. Actual workspace creation happens at runtime, governed by the coordinator and the workflow.

The runtime validates the complete taxonomy (base + application) at startup, before any workspace is created or any directive is processed. Validation checks:

  1. Completeness — every name referenced in a workflow pipeline, permission matrix entry, or role definition resolves to a registered type or role.
  2. Uniqueness — no two registrations in the merged taxonomy share the same name.
  3. Inheritance validity — every derived role references a base role that exists, and does not grant permissions that exceed the base role’s ceiling (PROTOCOL.md §4.3).
  4. Permission matrix consistency — every (sender_role, envelope_type) → receiver_roles entry references registered roles and envelope types.
  5. Workflow integrity — every stage in a workflow pipeline references a registered role, and every conditional field references a valid checkpoint or envelope property.

If any check fails, the runtime refuses to start. The error message identifies the specific registration that failed and the rule it violated. This is fail-fast (Principle T1) — the cost of catching a bad taxonomy at startup is near zero; the cost of catching it mid-run is a failed workflow and wasted agent computation.

Detailed validation rules for each registry are specified in their respective sections (§3–§7) and summarized in §8.


An envelope type determines the semantics of a message passed between workspaces. The type governs three things:

  1. Who can send it — which roles are permitted to create envelopes of this type
  2. Who can receive it — which roles are eligible to receive envelopes of this type
  3. What it means — a human-readable description of the message’s intent and expected use

The protocol enforces rules 1 and 2 through the permission matrix (PROTOCOL.md §4.4). Rule 3 is documentation — it guides application developers and agent prompt design but is not enforced mechanically.

The base taxonomy defines three envelope types. These are always present and cannot be modified.

envelope_types:
- id: directive
description: >
A structured instruction from the coordinator to a worker.
Carries the task to be performed: a spec, research brief, analysis request,
editorial instruction, or any domain-specific assignment.
senders: [coordinator]
receivers: [worker]
- id: feedback
description: >
A response from the coordinator to a worker, typically following
a checkpoint or in response to a query. Carries guidance, corrections,
approval, or rejection.
senders: [coordinator]
receivers: [worker]
- id: query
description: >
A request for clarification or input from a worker to the coordinator.
The worker is blocked or uncertain and needs guidance to proceed.
senders: [worker]
receivers: [coordinator]

These three types cover the fundamental communication patterns defined in PROTOCOL.md §5.5: command (directive, feedback) and query-response (query, feedback). The evaluation chain pattern (directive → report) uses the report envelope type registered alongside the reviewer derived role (§6.3).

3.3 Registering Application Envelope Types

Section titled “3.3 Registering Application Envelope Types”

Applications register new envelope types to represent domain-specific message semantics. Each registration must specify:

envelope_types:
- id: string # unique name, must not collide with base types
description: string # what this message type means and when to use it
senders: list[string] # roles permitted to send (must be registered roles)
receivers: list[string] # roles permitted to receive (must be registered roles)
payload_schema: # optional: structural constraints on the payload
format: string # expected payload format (markdown, json, yaml, etc.)
required_fields: list # fields that must be present in the payload

Example — mada-swarm registering a spec envelope type:

envelope_types:
- id: spec
description: >
A software specification delivered to an implementer. Contains requirements,
constraints, and acceptance criteria for a unit of code to be produced.
senders: [coordinator]
receivers: [implementer]
payload_schema:
format: markdown
required_fields: [title, requirements]
  1. The id must be unique across the merged taxonomy (base + application). An application cannot register directive — it already exists.

  2. The senders and receivers lists must reference registered roles. If implementer appears in receivers, it must be registered in the roles section (§6) of the same taxonomy. The runtime validates this at startup.

  3. Derived roles inherit their base role’s envelope permissions. If implementer extends worker, and worker can receive directive, then implementer can also receive directive — unless the derived role explicitly removes that permission. Application envelope types must declare their own sender/receiver lists independently; they do not inherit from base envelope types.

  4. The payload_schema is optional but recommended. When present, the runtime validates envelope payloads against the schema before delivery. When absent, any payload is accepted. The schema is advisory for v0.1 — implementations may choose strict or lenient enforcement.

  5. Base types cannot appear in senders or receivers for application types unless the base role genuinely participates. An application should not add coordinator as a receiver of a domain-specific type unless the coordinator is the intended recipient. This is a design guideline, not a runtime enforcement — the permission matrix is the enforcement layer.

Each registered envelope type implicitly extends the permission matrix (PROTOCOL.md §4.4). The base matrix is:

Sender → Envelope TypeEligible Receivers
Coordinator → directiveWorker
Coordinator → feedbackWorker
Worker → queryCoordinator

When an application registers a new envelope type, its senders and receivers add rows to this matrix. For the spec example above:

Sender → Envelope TypeEligible Receivers
Coordinator → specImplementer

The runtime merges the base matrix with all application-registered rows. At envelope validation time (PROTOCOL.md §5.1, Rule 2), the merged matrix is consulted. If no row matches the (sender_role, envelope_type, receiver_role) triple, the envelope is rejected.

At startup, for each registered envelope type:

CheckRule
Unique idNo collision with base or other application types
Valid sendersEvery role in senders is registered
Valid receiversEvery role in receivers is registered
Non-empty participantsAt least one sender and one receiver
Schema consistencyIf payload_schema is present, required_fields is a list of strings

A checkpoint type declares the nature of the work snapshot an agent has produced. Where the envelope type governs communication between agents, the checkpoint type governs what an agent records as its output.

The type determines:

  1. Which roles can create it — a worker creates artifact checkpoints, an observer creates observation checkpoints. The protocol enforces this (PROTOCOL.md §7.2, Rule 3). Derived roles may register additional types (e.g., a reviewer produces review checkpoints).
  2. What it represents — production of work, something observed, or domain-specific output.
  3. How it is treated during integration — the coordinator reads checkpoint types to decide what to merge, what to attach as evidence, and what to archive.

The base taxonomy defines two checkpoint types. These are always present and cannot be modified.

checkpoint_types:
- id: artifact
description: >
The agent produced something — code, a report, a dataset, a plan,
a document, or any tangible output. This is the primary deliverable
of a worker's task.
producers: [worker]
integration: merge
- id: observation
description: >
The agent recorded something it noticed without producing an artifact.
Informational — may inform the coordinator's future decisions but
carries no actionable output.
producers: [worker, observer]
integration: archive

Additional checkpoint types — review, decision, and domain-specific types — are registered alongside derived roles or in application taxonomies. For example, the reviewer derived role (§6.3) registers review (integration: attach) and the decision type may be registered by applications where agents make choices that affect downstream work.

The integration field declares how the coordinator treats the checkpoint during workspace integration (PROTOCOL.md §7.4):

Integration modeMeaning
mergeArtifacts are merged into the parent workspace. This is the primary deliverable.
attachCheckpoint is linked to the integration record as supporting evidence. Not merged.
archiveCheckpoint is preserved in the trail but not referenced during integration.

4.3 Registering Application Checkpoint Types

Section titled “4.3 Registering Application Checkpoint Types”

Applications register new checkpoint types to represent domain-specific work products. Each registration must specify:

checkpoint_types:
- id: string # unique name, must not collide with base types
description: string # what this checkpoint represents
producers: list[string] # roles permitted to create this type (must be registered)
integration: enum # merge | attach | archive
payload_schema: # optional: structural constraints on the payload
required_fields: list # fields that must be present

Example — mada-swarm registering an implementation checkpoint type:

checkpoint_types:
- id: implementation
description: >
A code implementation produced by an implementer in response to a spec.
Contains source files, tests, and a summary of the approach taken.
producers: [implementer]
integration: merge
payload_schema:
required_fields: [files_changed, approach_summary]

Example — a research application registering an extraction checkpoint type:

checkpoint_types:
- id: extraction
description: >
Structured data extracted from a research paper — key findings,
methodology, novel claims, and citation references.
producers: [extraction_worker]
integration: merge
payload_schema:
required_fields: [source_paper, findings, methodology]
  1. The id must be unique across the merged taxonomy. An application cannot register artifact — it already exists.

  2. The producers list must reference registered roles. If implementer appears in producers, it must be registered in the roles section (§6).

  3. Derived roles inherit their base role’s checkpoint permissions. If implementer extends worker, and worker can produce artifact, then implementer can also produce artifact — unless explicitly removed. Application checkpoint types declare their own producer lists independently.

  4. The integration mode must be one of the three defined values. merge, attach, or archive. No other modes exist in v0.1.

  5. A role’s checkpoint permissions must be consistent with the role registry. The role registry (§6) declares which checkpoint types a role may produce. The checkpoint type registry declares which roles may produce it. These must agree. If they conflict, validation fails. The authoritative source is the checkpoint type registry — it is the definition; the role registry is the cross-reference.

4.5 Relationship Between Checkpoint Types and Envelope Types

Section titled “4.5 Relationship Between Checkpoint Types and Envelope Types”

Checkpoint types and envelope types are independent registries. However, they participate in a natural flow:

envelope(directive) → agent works → checkpoint(artifact)

The coordinator sends a directive (envelope type). The worker produces an artifact (checkpoint type). When applications register evaluation roles and types, the flow extends — e.g., a reviewer evaluates the artifact and sends a report (both registered as derived types). The types are different registries but the protocol’s patterns (PROTOCOL.md §5.5) connect them into coherent workflows.

Applications are encouraged to name their types in ways that make this flow readable. A spec envelope type leading to an implementation checkpoint type leading to a code_review report type tells a clear story.

At startup, for each registered checkpoint type:

CheckRule
Unique idNo collision with base or other application types
Valid producersEvery role in producers is registered
Non-empty producersAt least one producer role
Valid integration modeMust be merge, attach, or archive
Cross-registry consistencyProducers agree with role registry’s checkpoint permissions
Schema consistencyIf payload_schema is present, required_fields is a list of strings

A signal type declares a lifecycle or coordination event that an agent can emit. Signals are the lightweight counterpart to envelopes — they carry state, not content (PROTOCOL.md §3.4). The type determines:

  1. What happened — the semantic meaning of the event (started, blocked, completed, etc.)
  2. Who can emit it — which roles are permitted to emit this signal type
  3. Whether a reason is required — some signals demand explanation (blocked, failed, escalation)

The base taxonomy defines nine signal types organized into three categories. These are always present and cannot be modified.

Track workspace state transitions (PROTOCOL.md §6.1).

signal_types:
- id: ready
category: lifecycle
description: >
Workspace initialized, agent is waiting for input.
Emitted once after workspace creation.
emitters: [coordinator, worker, observer]
reason_required: false
- id: started
category: lifecycle
description: >
Agent has begun working. Emitted when the agent receives its first
envelope, or when resuming from blocked state.
emitters: [coordinator, worker, observer]
reason_required: false
- id: complete
category: lifecycle
description: >
Agent considers its work finished. The workspace transitions
toward integration or closure.
emitters: [coordinator, worker, observer]
reason_required: false
- id: failed
category: lifecycle
description: >
Unrecoverable error. The workspace transitions to terminal failed
state. The trail is preserved for diagnosis. May be emitted by an
agent (unrecoverable error), the coordinator (abort), or the
protocol (timeout).
emitters: [coordinator, worker, observer, protocol]
reason_required: true

Facilitate interaction between workspaces without requiring a full envelope exchange.

signal_types:
- id: blocked
category: coordination
description: >
Agent cannot continue. Carries a reason explaining the blockage.
The coordinator decides how to respond — send feedback, reassign,
or abort.
emitters: [worker, observer]
reason_required: true
- id: checkpoint
category: coordination
description: >
A new checkpoint is available for reading. The ref field carries
the checkpoint id.
emitters: [worker, observer]
reason_required: false
- id: integrate
category: coordination
description: >
Merge operation initiated by the coordinator. Recorded as an audit
marker in the global trail.
emitters: [coordinator]
reason_required: false
- id: acknowledged
category: coordination
description: >
Envelope received by target workspace. Emitted automatically by the
protocol, not by agents. Means "delivered", not "understood" or
"acting on."
emitters: [protocol]
reason_required: false

Bridges the agent layer and the human layer.

signal_types:
- id: escalation
category: escalation
description: >
Agent needs human input to proceed. Propagates upward through the
workspace tree and additionally activates the human highway
(PROTOCOL.md §9). The emitting agent's workflow pauses until a
human responds or the escalation times out.
emitters: [worker, observer]
reason_required: true

Unlike envelope types and checkpoint types, signal types are not extensible by applications. The nine base signal types are the complete set.

Rationale:

Signals are the protocol’s nervous system. They drive the workspace state machine (PROTOCOL.md §6), trigger integration decisions, and activate the human highway. The runtime must understand every signal type to maintain protocol correctness — an unrecognized signal would leave the state machine in an undefined state.

Envelope types and checkpoint types are safe to extend because the protocol treats their type field as data — it validates permissions but does not alter its own behavior based on the specific type. Signals are different: the protocol’s behavior changes depending on whether it receives blocked, complete, or escalation. Adding new signal types would require changes to the protocol’s state machine logic, not just to the taxonomy.

If a domain needs to communicate nuance beyond the nine signal types, the mechanism is:

  • Use the reason field to carry domain-specific context (free text)
  • Use the ref field to reference a checkpoint with structured detail
  • Use an envelope for rich, typed communication

Signals say what happened. Envelopes and checkpoints say what it means.

The acknowledged signal has a unique emitter: protocol. This is not a role — it is the runtime itself. The protocol automatically emits acknowledged when an envelope is delivered (PROTOCOL.md §5.1, Rule 3). No agent action is required.

No application-defined role may use protocol as a name. It is reserved.

SignalCategoryReason requiredEmittersState machine effect
readylifecyclenocoordinator, worker, observerno state change (declaration while in idle)
startedlifecyclenocoordinator, worker, observertriggers blocked → active (§6.2); idle → active is auto-triggered by first envelope, not by this signal
completelifecyclenocoordinator, worker, observerworkspace enters integrating
failedlifecycleyescoordinator, worker, observer, protocolworkspace enters failed (terminal)
blockedcoordinationyesworker, observerworkspace enters blocked
checkpointcoordinationnoworker, observerno state change
integratecoordinationnocoordinatoraudit marker only
acknowledgedcoordinationnoprotocolno state change
escalationescalationyesworker, observerhighway activated (paired with blocked signal for state transition — §9.2.4)

Derived roles inherit their base role’s signal emission permissions. A reviewer derived from worker can emit all signals that worker can emit.

Note on the conflicted state. The workspace state conflicted (PROTOCOL.md §6.1) is not triggered by a signal. It is a coordinator-driven transition that occurs during integration when a conflict is detected. The protocol records conflict_detected and conflict_resolved trail events (PROTOCOL.md §11.2) rather than signals, because conflict detection is a coordinator action — not an agent emission. This is consistent with other integration transitions (integrating → closed, integrating → failed) which are also coordinator-driven, not signal-driven.


A role is a named set of permissions that governs what an agent operating within a workspace can do. The role determines:

  1. What envelope types the agent can send and receive — which rows in the permission matrix apply
  2. What checkpoint types the agent can produce — which work products it is authorized to create
  3. What signal types the agent can emit — which lifecycle and coordination events it can declare
  4. What it can see — read access to other workspaces (own, assigned, all, or none)
  5. What it can modify — write access scope (own workspace files, or nothing)

Roles are assigned at workspace creation and cannot change during a workspace’s lifetime (PROTOCOL.md §4.1). An agent does not choose its role — the coordinator assigns it.

The base taxonomy defines three roles. These are always present and cannot be modified. Their full permission specifications are defined in PROTOCOL.md §4.2; the taxonomy formalizes them as structured registrations.

roles:
- name: coordinator
type: base
description: >
The root agent. Exactly one per protocol instance. Sees across all
workspaces, modifies none directly. Governs the overall task through
directives and feedback.
can_send: [directive, feedback]
can_receive: [query]
can_produce: []
can_emit: [ready, started, complete, failed, integrate]
visibility: all
authority: none
special:
- create_workspaces
- destroy_workspaces
- perform_integration
- read_global_trail
- name: worker
type: base
description: >
The producing agent. Receives directives, produces artifacts within
its workspace. Operates within the boundaries of its workspace with
no visibility beyond what the coordinator has explicitly granted.
can_send: [query]
can_receive: [directive, feedback]
can_produce: [artifact, observation]
can_emit: [ready, started, blocked, checkpoint, complete, failed, escalation]
visibility: own
authority: own
special: []
- name: observer
type: base
description: >
The monitoring agent. Read-only access to designated workspaces and
the trail. Produces no artifacts, modifies nothing. Purpose is passive:
logging, metrics, dashboards, or bridging to external systems.
can_send: []
can_receive: []
can_produce: [observation]
can_emit: [ready, started, complete, failed, escalation]
visibility: designated
authority: none
special: []
FieldTypeMeaning
can_sendlist[envelope_type]Envelope types this role may create and send
can_receivelist[envelope_type]Envelope types this role may receive
can_producelist[checkpoint_type]Checkpoint types this role may create
can_emitlist[signal_type]Signal types this role may emit
visibilityenumRead access scope: all, own, assigned, designated, none
authorityenumWrite access scope: own, none
speciallist[string]Protocol-level capabilities beyond messaging

Visibility modes:

ModeMeaning
allCan read any workspace in the tree (coordinator only)
ownCan read only its own workspace
assignedCan read workspaces explicitly assigned at creation (reviewer reads worker’s workspace)
designatedCan read workspaces listed in workspace creation config (observer)
noneCannot read any workspace

Special capabilities:

CapabilityMeaningAvailable to
create_workspacesCan create child workspacescoordinator
destroy_workspacesCan abort child workspacescoordinator
perform_integrationCan merge workspace artifacts into parentcoordinator
read_global_trailCan read the system-wide trail, not just localcoordinator

These capabilities are structural — they cannot be granted to derived roles through inheritance. A worker derivative cannot gain create_workspaces. This is enforced at validation (see §6.5).

Applications register derived roles to specialize base roles for domain-specific purposes. A derived role extends exactly one base role using single-level inheritance (PROTOCOL.md §4.3).

roles:
- name: string # unique name, must not collide with base roles
type: derived
extends: string # the base role this derives from
description: string # what this role does in the application's domain
add: # permissions granted beyond the base role
can_send: list # additional envelope types this role can send
can_receive: list # additional envelope types this role can receive
can_produce: list # additional checkpoint types this role can produce
can_emit: list # additional signal types this role can emit
remove: # permissions revoked from the base role
can_send: list
can_receive: list
can_produce: list
can_emit: list
override: # properties that replace the base role's defaults
visibility: enum # override visibility mode
description: string # override description

Example — the canonical reviewer derived role:

The reviewer is the protocol’s canonical derived role (PROTOCOL.md §4.3). It demonstrates all three inheritance operations: add, remove, and override.

# Registered alongside the reviewer role:
envelope_types:
- id: report
description: >
A structured evaluation from a reviewer to the coordinator. Carries the
reviewer's assessment of a worker's output — findings, issues, recommendations.
senders: [reviewer]
receivers: [coordinator]
checkpoint_types:
- id: review
description: >
The agent evaluated another agent's work. Carries findings, issues,
recommendations, and an overall assessment. Not merged into the parent —
attached to the integration record as supporting evidence.
producers: [reviewer]
integration: attach
roles:
- name: reviewer
type: derived
extends: worker
description: >
The evaluating agent. Receives a completed artifact and its originating
directive, evaluates the work, and produces a structured review. Has
read access to the worker's workspace but cannot modify it.
add:
can_send: [report]
can_receive: []
can_produce: [review]
remove:
can_send: [query]
can_produce: [artifact]
override:
visibility: assigned
authority: none

The resolved permissions for reviewer would be:

PermissionInherited from workerAddedRemovedResolved
can_send[query][report][query][report]
can_receive[directive, feedback][directive, feedback]
can_produce[artifact, observation][review][artifact][observation, review]
can_emit[ready, started, blocked, checkpoint, complete, failed, escalation](unchanged)
visibilityownassigned (overridden)
authorityownnone (overridden)

Example — mada-swarm’s implementer role:

roles:
- name: implementer
type: derived
extends: worker
description: >
A worker specialized for software implementation. Receives specs,
produces code implementations. Can additionally produce implementation
checkpoints alongside standard artifacts.
add:
can_receive: [spec]
can_produce: [implementation]
remove: {}
override: {}

The resolved permissions for implementer would be:

PermissionInherited from workerAddedResolved
can_send[query][query]
can_receive[directive, feedback][spec][directive, feedback, spec]
can_produce[artifact, observation][implementation][artifact, observation, implementation]
can_emit[ready, started, blocked, checkpoint, complete, failed, escalation](unchanged)
visibilityownown
authorityownown

Example — a senior_worker with cross-workspace visibility:

roles:
- name: senior_worker
type: derived
extends: worker
description: >
A worker that can read peer workspaces for context. Used when
tasks are interdependent and workers benefit from seeing each
other's progress.
add:
can_produce: [decision]
remove: {}
override:
visibility: designated

Example — a code_reviewer specialized for code evaluation:

roles:
- name: code_reviewer
type: derived
extends: worker
description: >
A worker specialized for code evaluation. Receives a completed
implementation, evaluates quality, and produces a structured
code review. Has read access to the worker's workspace.
add:
can_send: [report]
can_produce: [review, code_review]
remove:
can_send: [query]
can_produce: [artifact]
override:
visibility: assigned
authority: none
  1. Single-level only. A derived role extends a base role. A derived role cannot extend another derived role. This keeps permission resolution trivial — one lookup, one merge, done.

  2. add grants additional permissions. The resolved permission set is the union of the base role’s permissions and the add list. All referenced types must be registered in the taxonomy.

  3. remove revokes base permissions. The resolved permission set excludes anything in the remove list. An application can create a restricted worker that cannot send queries:

    remove:
    can_send: [query]
  4. override replaces properties. Only visibility, authority, and description can be overridden. The reviewer derived role demonstrates this: it overrides visibility to assigned and authority to none. Authority can only be restricted (from own to none), never escalated (from none to own). This prevents privilege escalation.

  5. Special capabilities are never inherited. create_workspaces, destroy_workspaces, perform_integration, and read_global_trail belong to the coordinator and cannot be added to any derived role. Attempting to add them fails validation.

  6. add and remove are applied in order: base → add → remove. If the same type appears in both add and remove, the removal wins. This is intentional — it allows an application to add a batch of permissions and then surgically remove specific ones.

At startup, for each registered role:

CheckRule
Unique nameNo collision with base roles, protocol, or other derived roles
Valid extendsDerived roles reference an existing base role (not another derived role)
Valid add referencesEvery type in add lists is registered in the corresponding type registry
Valid remove referencesEvery type in remove lists exists in the base role’s permissions
No special escalationDerived roles do not add coordinator-only special capabilities
Authority restriction onlyDerived roles may override authority only to restrict it (ownnone, never noneown)
Cross-registry consistencycan_produce agrees with checkpoint type registry’s producers
Envelope permission consistencycan_send/can_receive agree with envelope type registry’s senders/receivers

A workflow is a named, reusable configuration that tells the coordinator how to process directives (PROTOCOL.md §10). The workflow registry ensures that every workflow referenced by the runtime is fully defined, internally consistent, and references only registered types and roles.

Registration does not define workflow behavior — that is specified in PROTOCOL.md §10.2–§10.4. Registration validates that a workflow’s references are resolvable: every role in a pipeline stage exists, every envelope type in a routing rule exists, every conditional field references a valid property.

Workflows are registered in the taxonomy with a subset of the full workflow definition (PROTOCOL.md §10.2). The taxonomy captures the structural elements that can be validated statically; runtime behavior (dispatch timing, integration ordering decisions) is not part of the registry.

workflows:
- id: string # unique identifier
name: string # human-readable name
description: string # what this workflow does and when to use it
roles_used: list[string] # all roles referenced by this workflow
# must be registered in the role registry (§6)
pipeline: # ordered list of stages
- stage: string # stage name (unique within workflow)
role: string # which role executes this stage
envelope_type: string # envelope type sent to the agent at this stage
# (optional: defaults to 'directive')
on_complete: enum # next_stage | integrate | conditional
condition: # required if on_complete is conditional
field: string # what to evaluate
operator: enum # gt | lt | eq | in
value: any # threshold or match value
if_true: string # stage name or 'integrate'
if_false: string # stage name or 'integrate'
on_failure: enum # what happens when the stage fails (PROTOCOL.md §10.3.1)
# abort (default) | retry | skip | reroute | escalate
retry: # required if on_failure is retry
max_attempts: integer # maximum retry count (default: 2)
feedback: boolean # include failure context in retry directive (default: true)
reroute_to: string # target stage name (required if on_failure is reroute)
highway: # human highway configuration for this workflow
preset: string # autonomous | supervised | gated
# OR explicit configuration:
gates:
workspace_create: boolean
envelope_delivery: boolean
integration: boolean
conflict_resolution: boolean
workspace_abort: boolean
escalation:
enabled: boolean
timeout: duration
fallback: enum # approve | reject | delegate_to_coordinator

The base taxonomy ships with zero workflows. Workflows are always application-defined — the protocol provides the pipeline mechanics, but every concrete pipeline is a domain decision.

This is deliberate. A workflow encodes domain assumptions: what roles participate, how many stages of evaluation occur, which transitions are gated. These are application choices, not protocol defaults. A “default workflow” would imply a default domain, violating the protocol’s domain-agnostic nature.

Example — mada-swarm’s work-only workflow:

workflows:
- id: work-only
name: "Work Only"
description: >
Single-stage workflow. Worker receives a spec, produces an implementation,
and the coordinator integrates it directly. No evaluation step.
Fastest path, lowest quality assurance.
roles_used: [implementer]
pipeline:
- stage: implement
role: implementer
envelope_type: spec
on_complete: integrate
highway:
preset: autonomous

Example — mada-swarm’s work-then-evaluate workflow:

workflows:
- id: work-then-evaluate
name: "Work Then Evaluate"
description: >
Two-stage workflow. Worker produces an implementation, then a reviewer
evaluates it. The coordinator integrates only after review approval.
Slower but catches quality issues.
roles_used: [implementer, code_reviewer]
pipeline:
- stage: implement
role: implementer
envelope_type: spec
on_complete: next_stage
- stage: evaluate
role: code_reviewer
on_complete: integrate
highway:
preset: supervised

Example — a conditional workflow that skips review for high-confidence work:

workflows:
- id: confidence-gated
name: "Confidence-Gated Review"
description: >
Worker produces an artifact. If confidence is high, integrate directly.
If medium or low, route through evaluation first.
roles_used: [implementer, code_reviewer]
pipeline:
- stage: implement
role: implementer
envelope_type: spec
on_complete: conditional
condition:
field: checkpoint.confidence
operator: eq
value: high
if_true: integrate
if_false: evaluate
- stage: evaluate
role: code_reviewer
on_complete: integrate
highway:
preset: supervised

Example — a research workflow with human-gated integration:

workflows:
- id: research-synthesis
name: "Research Synthesis"
description: >
Multi-stage research pipeline. Source monitor extracts findings,
reviewer cross-references, coordinator synthesizes. Human must
approve before integration.
roles_used: [source_monitor, cross_reference_reviewer]
pipeline:
- stage: extract
role: source_monitor
on_complete: next_stage
- stage: cross_reference
role: cross_reference_reviewer
on_complete: integrate
highway:
preset: gated

Applications that use multiple workflows register routing rules alongside their workflow definitions. Routing rules determine which workflow processes a given directive (PROTOCOL.md §10.4).

routing:
rules:
- match:
field: string # directive property to match against
value: any # exact match
contains: any # list membership match (alternative to value)
workflow: string # workflow id to use if matched
default: string # workflow id for directives that match no rule

Example — mada-swarm routing by priority:

routing:
rules:
- match:
field: directive.tags
contains: high-risk
workflow: work-then-evaluate
default: work-only

Routing rules reference workflow ids. All referenced workflow ids must be registered in the same taxonomy. The runtime validates this at startup.

At startup, for each registered workflow:

CheckRule
Unique idNo collision with other registered workflows
Valid roles_usedEvery role in roles_used is registered in the role registry
Pipeline role consistencyEvery role in a pipeline stage appears in roles_used
Valid envelope typesEvery envelope_type in a pipeline stage is registered
Stage name uniquenessNo two stages in a pipeline share the same name
Conditional validityif_true and if_false reference existing stage names or integrate
No dangling stagesEvery stage is reachable from the first stage through on_complete chains
Valid on_failureIf present, must be one of: abort, retry, skip, reroute, escalate
Retry config validityIf on_failure is retry, retry.max_attempts must be a positive integer
Reroute target validityIf on_failure is reroute, reroute_to must reference an existing stage name
Highway preset validityIf preset is used, it must be autonomous, supervised, or gated
Routing reference validityEvery workflow id in routing rules is registered
Default workflow existsThe default workflow id in routing is registered

The runtime validates the complete taxonomy exactly once: at startup, before any workspace is created, any directive is processed, or any agent is spawned. Validation is not incremental — the entire merged taxonomy (base + application) is checked as a unit.

If validation passes, the runtime holds the resolved taxonomy in memory for the duration of the run. No further taxonomy changes are possible mid-run. This guarantees that every reference resolved at startup remains valid throughout execution.

If validation fails, the runtime refuses to start. The error identifies the failing registration, the rule violated, and the specific reference that could not be resolved. Multiple errors may be reported in a single validation pass — the runtime does not stop at the first failure.

Validation proceeds in four ordered phases. Each phase depends on the previous phase completing without errors. If a phase fails, subsequent phases are skipped — their checks would produce misleading results against an incomplete registry.

Checks that every registration has the required fields and correct types. No cross-references are checked.

CheckApplies toRule
Required fields presentAll registrationsEvery registration has id/name, description, and type-specific required fields
Field types correctAll registrationsLists are lists, enums are valid values, strings are non-empty
Taxonomy metadata validTaxonomy documentid, name, version are present; extends references a known base taxonomy

Checks that no two registrations collide within or across registries.

CheckApplies toRule
Envelope type uniquenessEnvelope typesNo application type shares an id with a base type or another application type
Checkpoint type uniquenessCheckpoint typesNo application type shares an id with a base type or another application type
Role name uniquenessRolesNo derived role shares a name with a base role, protocol, or another derived role
Workflow id uniquenessWorkflowsNo two workflows share an id
Stage name uniquenessWorkflowsNo two stages within a single pipeline share a stage name
Cross-registry uniquenessAll registrationsNo id/name is reused across different registry types (a role and an envelope type cannot both be named report)

The cross-registry uniqueness check prevents ambiguity. When a name appears in a trail entry, routing rule, or error message, it must unambiguously identify one registration. Sharing names across registries would require contextual disambiguation — an unnecessary source of confusion.

Checks that every cross-reference between registries resolves to an existing registration.

CheckSourceTargetRule
Envelope senders validEnvelope type sendersRole registryEvery role name in senders is registered
Envelope receivers validEnvelope type receiversRole registryEvery role name in receivers is registered
Checkpoint producers validCheckpoint type producersRole registryEvery role name in producers is registered
Role extends validDerived role extendsRole registryReferences an existing base role (not a derived role)
Role add types validDerived role add listsEnvelope/checkpoint/signal registriesEvery type name in add is registered
Role remove types validDerived role remove listsBase role permissionsEvery type name in remove exists in the base role’s permission set
Workflow roles validWorkflow roles_usedRole registryEvery role name is registered
Pipeline roles validPipeline stage roleWorkflow roles_usedEvery stage role appears in the workflow’s roles_used
Pipeline envelope types validPipeline stage envelope_typeEnvelope type registryEvery envelope type is registered
Conditional targets validCondition if_true/if_falsePipeline stagesReferences an existing stage name or integrate
Reroute targets validPipeline stage reroute_toPipeline stagesIf on_failure is reroute, target stage name exists in the same pipeline
Routing workflows validRouting rules workflowWorkflow registryEvery workflow id is registered
Routing default validRouting defaultWorkflow registryThe default workflow id is registered

Checks that cross-registry declarations agree with each other. Two registries may independently declare a relationship — consistency validation ensures they say the same thing.

CheckRegistries involvedRule
Envelope-role agreementEnvelope types ↔ RolesIf envelope type spec lists implementer as a receiver, then implementer’s resolved can_receive must include spec
Checkpoint-role agreementCheckpoint types ↔ RolesIf checkpoint type implementation lists implementer as a producer, then implementer’s resolved can_produce must include implementation
Permission matrix completenessEnvelope types ↔ RolesEvery (sender, envelope_type, receiver) triple implied by the registries has a matching row in the merged permission matrix
Pipeline reachabilityWorkflow pipelinesEvery stage is reachable from the first stage through on_complete chains; no orphaned stages
Inheritance ceilingDerived roles ↔ Base rolesNo derived role grants special capabilities not present in its base role
Authority restriction onlyDerived roles ↔ Base rolesDerived roles may only restrict authority (ownnone), never escalate (noneown)

When validation fails, each error is reported with sufficient context for diagnosis:

validation_error:
phase: integer # 1–4
registry: string # envelope_types | checkpoint_types | signal_types | roles | workflows
registration: string # the id/name of the failing registration
check: string # the specific check that failed
message: string # human-readable explanation
references: # the unresolved or conflicting references
- string

Example error — unregistered role in envelope type:

validation_error:
phase: 3
registry: envelope_types
registration: spec
check: envelope_receivers_valid
message: "Envelope type 'spec' lists receiver 'implementer' but no role named 'implementer' is registered"
references: [implementer]

Example error — cross-registry inconsistency:

validation_error:
phase: 4
registry: checkpoint_types
registration: implementation
check: checkpoint_role_agreement
message: "Checkpoint type 'implementation' lists producer 'implementer' but role 'implementer' does not include 'implementation' in can_produce"
references: [implementer, implementation]

When validation passes, the runtime holds the following guarantees for the entire run:

  1. Every name is resolvable. Any type, role, or workflow referenced anywhere in the system maps to exactly one registration.
  2. The permission matrix is complete. Every possible (sender, envelope_type, receiver) combination is either explicitly permitted or implicitly denied. There are no undefined cells.
  3. Every workflow is executable. Every pipeline stage references a valid role and envelope type. Every conditional branches to a reachable stage or integrate. No workflow will fail due to a missing registration.
  4. Every derived role is correctly resolved. The add/remove/override mechanics have been applied, and the resolved permission set is cached. No inheritance computation occurs at runtime.
  5. Cross-registry declarations agree. No envelope type claims a receiver that doesn’t know it can receive. No checkpoint type claims a producer that doesn’t know it can produce.

These guarantees mean that any runtime failure after validation is a protocol-level event (agent failure, timeout, integration conflict) — not a configuration error. Configuration errors are eliminated at startup. This is the payoff of Principle T1.


WACP taxonomy v0.1 — authored by Akil Abderrahim and Claude Opus 4.6