RFC-MACP-0007
RFC-MACP-0007
Multi-Agent Coordination Protocol (MACP) - Decision Mode
Document: RFC-MACP-0007 Version: 1.3.0-draft Status: Community Standards Track Updates: RFC-MACP-0002
Changelog — 1.3.0-draft: §5 gains a sixth validation rule — deliberation closes when voting begins — requiring a runtime to reject any
Proposal,EvaluationorObjectionarriving after the first acceptedVote. This pins behavior the reference runtime already implements for all three message types, but the three arms were not equally covered before, and the difference matters to anyone implementing against the corpus rather than against the runtime. TheEvaluationarm was already asserted executably —schemas/conformance/decision_reject_paths.jsonhas pinned exactly that rejection since the corpus was runtime-verified — so for that arm this revision introduces no new rejection behavior and merely supplies the rule the corpus was asserting against nothing (issue #108). TheObjectionarm existed only as narrative inside a_commentindecision_critical_objection_veto.json, which asserts nothing executable, and the post-voteProposalarm had no coverage at all; fixtures for both are added in this same revision. A runtime that had implemented only the Evaluation arm was passing the corpus and must now handle the other two. The rule deliberately covers all three rather thanEvaluationalone, because an Evaluation-only rule would leave the reference runtime'sProposalandObjectionrejections unsupported by any normative text. Rejections useINVALID_ENVELOPEper RFC-MACP-0002 §6.1, which is the only conformant code: the sender is authorized soFORBIDDENis wrong, andPOLICY_DENIEDis unproducible for a non-Commitment. Replay: neutral for every conformant stored session, with one bounded exposure stated rather than argued away. For a runtime that already implemented all three arms — which the reference runtime does — nothing changes: it never accepted such a message, so no stored history contains one. The exposure is the runtime that implemented only the Evaluation arm and was nevertheless passing the corpus, because the corpus did not constrain the other two. Such a runtime may hold a stored session whose accepted history contains a post-voteProposalorObjection. RFC-MACP-0003 §1 conditions replay reproduction on identical validation rules and bound versions, and this revision changes a validation rule without amode_versionbump, so that precondition does not hold for those histories: replaying one against rule 6 would reject a message the original run accepted. The affected messages are not inert, and this revision does not pretend otherwise: an accepted post-vote criticalObjectioncan fire acritical_severity_vetoesveto that rule 6 now prevents, flipping both the commitment outcome and the terminal state on replay, and an accepted post-voteProposalenlarges the option set that laterVotes reference. The break is nevertheless accepted, on the strongest of the reasons RFC-MACP-0012 §8's bounded exception gives — the behavior being broken was itself unsound. Admitting post-vote deliberation lets two conforming implementations derive different commitment eligibility from history that was identical at the time each ballot was cast, which is what Section 7's semantic-determinism claim forbids; such histories were therefore never replay-safe against a conformant peer to begin with. The exposure is also confined to runtimes diverging on one or both of the uncovered arms. Amode_versionbump was weighed and declined — not because it would invalidate stored sessions, which it would not: RFC-MACP-0003 §3 requires replay to use the versions bound atSessionStart, so stored1.0.0sessions would continue to replay under1.0.0. It was declined because it imposes ecosystem-wide rebinding churn to preserve histories no conformant runtime produced. Implementations that may hold such histories should re-examine them before adopting this revision. RFC-MACP-0001 §8.3 is unaffected either way: it fixes accepted history as immutable and keeps rejected envelopes out of it, and rule 6 changes only what a runtime accepts from here on.Also in 1.3.0-draft, §6.2 resolves an ambiguity in the objection-authorized decline (issue #117). The decline guard is a two-conjunct conjunction, and §6.2 waives "the decline guard" without saying whether the waiver reaches the
require_vote_quorumconjunct. It does: the waiver covers the guard whole, and theevaluation.*prerequisites are waived with it. The governing principle is authorization provenance — the quorum condition legitimizes an outcome deriving its authority from the voting result, and an objection-authorized decline derives none. The strict reading is not a conservative choice but the failure mode itself: it reconstructs the stuck state this channel exists to remove. §6.2's claim that such a session "could terminate only by expiry" is also corrected — the initiator can submitCancelSessionat any time, and a loneABSTAINclears a count-1 floor; what is unreachable is a committed outcome, not termination. This changes behavior for one configuration family (a met critical-severity veto withfinalize_declineand an unmet floor, where a negativeCommitmentmoves from denied to allowed) but is replay-neutral in the same RFC-MACP-0001 §8.3 sense: a runtime that denied it rejected the message, and rejected messages never enter accepted history.Changelog — 1.2.0-draft: §5 rule 5 drops its "unless policy explicitly allows a no-go outcome with zero proposals" clause. No published rule schema ever defined a field that could express that allowance, and every channel that can authorize a NEGATIVE commitment requires an existing
proposal_id, so no conforming configuration could exercise the clause and its deletion changes no conforming implementation's behavior; RFC-MACP-0012 §8 is not engaged because no conforming stored session can contain a zero-proposal Commitment. §5 now states explicitly that every commitment path presupposes an accepted proposal and that a zero-proposal session terminates only bySessionCancelor expiry; §6.2's face-value exception is annotated to note that it waives the decline guard, not rule 5.§2 gains a Zero declared participants note, specializing §5's general statement to the zero-participant case beside the Authority Matrix it derives from. It reaches that conclusion via rule 5 rather than asserting unresolvability as a primitive — issue #106 asked for the stronger claim, which was false when filed, since rule 5 then carved out a policy-licensed zero-proposal no-go. The note restates a consequence already derivable from §2.1 and §5 rather than introducing a new rule; its one MUST NOT (a runtime may not treat the initiator as an implicit participant) makes the Authority Matrix's membership requirement explicit for a case implementers have gotten wrong (issue #106).
Changelog — 1.1.0-draft: §6.2's NoVotes bullet now states the positive-commitment half of the rule, which it previously left to inference. Under a bound policy declaring
schema_version ≥ 3a positive commitment is denied on an empty tally for every algorithm other thannone; underschema_version ≤ 2it remains gated only bycommitment.require_vote_quorum. See RFC-MACP-0012 §4.1. The decline guard is narrowed to count only decisive rejects: underweightedaREJECTcast by a weight-0participant is non-decisive (RFC-MACP-0012 §4.1) and does not authorize a decline, at every schema version — forschema_version ≤ 2descriptors this qualifies the previously unqualifiedreject_count > 0wording; RFC-MACP-0012 §8 bounds that retroactivity and states why it is accepted. §6.2 also gains an objection-authorized decline: a decline underobjection_handling.critical_objection_action: "finalize_decline"is authorized by the recorded criticalObjectionrather than by the tally, so it is gated by neither the tri-state nor the decline guard, at every schema version that can express the field (schema_version ≥ 2).schema_version ≥ 3newly made that case reachable and nothing ruled on it; RFC-MACP-0012 §8 records why the ruling cannot alter any stored session's replay. The section heading changes to match. Thevoting.algorithm == "none"scoping and the face-value exception are unchanged.
Abstract
This document defines macp.mode.decision.v1, the standards-track Decision Mode for bounded multi-party decisions. Decision Mode lets declared participants submit proposals, evaluations, objections, and votes, and it terminates with a single authoritative Commitment. The accepted SessionStart sender (session initiator/coordinator) may also be separately authorized to emit Proposal and Commitment.
1. Purpose
Decision Mode is the foundational MACP primitive for convergent choice. It is appropriate when participants need to compare options and produce a single bound outcome inside one Session.
Decision Mode is intentionally narrower than a general workflow engine:
- it standardizes transcript semantics,
- it does not standardize one universal scoring or voting algorithm,
- decision policy is bound through
mode_version,configuration_version, andpolicy_versionatSessionStart.
2. Identifier and participant model
- Mode identifier:
macp.mode.decision.v1 - Participant model:
declared
The eligible participant set is bound at SessionStart. The session initiator (accepted SessionStart sender) MUST be included in the participants list if they intend to emit Proposal, Evaluation, Objection, or Vote messages. The session initiator is the default Commitment authority regardless of participant list membership, unless a stricter policy is bound by configuration or policy.
2.1 Authority Matrix
The following table defines which participants are authorized to emit each message type:
| Message Type | Authorized Sender |
|---|---|
Proposal | Any declared participant |
Evaluation | Any declared participant |
Objection | Any declared participant |
Vote | Any declared participant (at most one per proposal per participant in base v1) |
Commitment | Session initiator (default) or policy-designated authority |
Runtimes MUST reject messages from senders not authorized per this matrix.
Zero declared participants. A Decision session that declares no participants can never resolve positively, at any policy schema_version. Proposal is authorized only for declared participants (matrix above), so no proposal can ever enter accepted history — not even from the initiator, whose authority is role-based rather than membership-based and covers SessionStart and Commitment (SessionCancel is emitted by the runtime, not the initiator; see RFC-MACP-0001 §7.3). Section 5 rule 5 then bars the session from resolving in either direction, so its only terminations are cancellation and expiry. Section 5 states this consequence for the general case — any session whose participant set cannot produce a proposal; it is specialized here to the zero-participant case, beside the Authority Matrix it derives from. Runtimes MUST NOT treat the initiator as an implicit participant: doing so would admit a proposal and make the vacuously-true zero-participant case of RFC-MACP-0012 §4.1's unanimous arm reachable. schemas/conformance/decision_zero_participants.json pins this guard.
3. SessionStart requirements
A Decision Mode Session MUST bind the following fields explicitly in SessionStartPayload:
participants- decision participants,mode_version- the decision-mode semantic profile,configuration_version- voting or evaluation profile,policy_version— governance profile (MAY be empty; when empty, the runtime resolves topolicy.defaultper RFC-MACP-0012 Section 5),ttl_ms- explicit decision deadline,context_id- optional bound decision context reference (arbitrary attached data goes inextensions).
4. Message types
Decision Mode defines the following mode-specific message types:
- Proposal - creates an option for consideration.
- Evaluation - records analysis of a proposal.
Valid recommendation values are:
APPROVE,REVIEW,BLOCK,REJECT.REVIEWindicates that the evaluator has analyzed the proposal but does not issue a definitive recommendation — it is semantically equivalent to "analyzed, no strong stance."REVIEWevaluations do not block or approve a proposal; they serve as informational analysis records only. - Objection - records a concern or blocking issue.
An Evaluation with BLOCK recommendation is an advisory assessment indicating the evaluator recommends against proceeding. An Objection is a formal blocking action with a severity level (low, medium, high, critical). Only Objections are subject to objection_handling governance rules (e.g., critical_severity_vetoes). A BLOCK evaluation does not trigger veto logic.
- Vote - records a participant preference. Valid vote values are:
APPROVE,REJECT,ABSTAIN. The semantics of abstention (e.g., impact on quorum and outcome calculation) are defined by the decision policy bound atSessionStart. When no policy is bound, abstentions do not count toward any threshold.
All enum-like string values in Decision Mode use UPPER_CASE. Comparisons MUST be case-sensitive.
- Commitment - authoritative terminal outcome.
Canonical payloads are defined in decision.proto.
5. Validation rules
Implementations of macp.mode.decision.v1 MUST enforce the following:
Proposal.proposal_idMUST be unique within the Session.Evaluation,Objection, andVoteMUST reference an existingproposal_id.- A participant MUST cast at most one
Voteperproposal_id. A runtime MUST reject a secondVotefrom the same sender for the sameproposal_id; the first acceptedVotestands. Configuration MAY bind a stricter rule (for example, restricting which participants may vote at all), but MUST NOT relax this one. A permissive multi-vote rule would need replacement or tally semantics that this mode does not define, and without them two conforming implementations could tally identical accepted history differently — which Section 7's semantic-deterministic claim forbids. - The runtime or policy authority MUST reject
Commitmentfrom unauthorized senders. - The Session MUST NOT resolve before at least one proposal exists.
- Deliberation closes when voting begins. After the first
Voteis accepted within the Session, a runtime MUST reject any subsequentProposal,Evaluation, orObjection. The first acceptedVotefixes the option set and the deliberation record from which the voting result and the objection-handling rules of RFC-MACP-0012 are computed; admitting post-vote deliberation messages would let two conforming implementations derive different commitment eligibility from what was identical accepted history at the time each ballot was cast — which Section 7's semantic-deterministic claim forbids. Configuration MAY bind a stricter rule (for example, closing deliberation earlier), but MUST NOT relax this one. Rejections under this rule are session-state breaches and useINVALID_ENVELOPEper RFC-MACP-0002 §6.1.
Rule 5 has no exceptions in macp.mode.decision.v1, and it binds every commitment-authorization path of Section 6.2. An objection-authorized commitment requires a standing critical Objection, and a vote-authorized commitment backed by a decisive tally requires a Vote; both message types MUST reference an existing proposal_id (rule 2), so those routes presuppose an accepted Proposal independently of this rule. Two routes presuppose no prior message at all, and for them rule 5 is the ONLY gate: the face-value exception (Section 6.2), which is initiator-driven; and, under a bound policy with schema_version ≤ 2 and commitment.require_vote_quorum false, a positive commitment on the empty tally (Section 6.2, NoVotes) — that commitment is vote-authorized, because its authorization derives from the computed voting result, yet it requires no Vote and therefore carries no proposal_id of its own. The face-value exception waives the decline guard, not this rule.
The only Decision Mode messages that do not reference a proposal_id are Proposal itself, SessionStart, Commitment, and the runtime lifecycle annotations (SessionCancel, SessionSuspend, SessionResume). It follows that a session whose declared participant set cannot produce an accepted Proposal can never resolve in either direction and terminates only by SessionCancel or expiry. A deployment that needs an auditable "no proposals arrived" terminal record SHOULD use SessionCancel with an explanatory reason.
6. Terminal semantics
Decision Mode resolves when an authorized Commitment is accepted.
The CommitmentPayload SHOULD identify:
- the selected action,
- the authority scope,
- the
mode_version,configuration_version, andpolicy_versionthat governed the decision, - a reason that can be replayed and audited.
The mode does not prescribe a single voting algorithm. A runtime or deployment may use majority vote, weighted vote, objection handling, veto rules, or another deterministic policy, provided that the policy is version-bound and replay-safe.
Decision Mode allows both positive and negative committed outcomes. CommitmentPayload.outcome_positive MUST be set explicitly on all Decision Mode commitments.
6.1 Governance Policy
Decision sessions MAY be governed by declarative policies that constrain voting algorithms, quorum requirements, objection handling, and commitment authority. See RFC-MACP-0012 for the governance policy framework and schemas/json/policy/decision-rules.schema.json for the Decision Mode rule schema.
6.2 Negative committed outcomes (vote-gated and objection-gated decline)
When a Decision session binds a governance policy with a real voting algorithm (voting.algorithm != "none"), the eligibility of a positive versus negative Commitment is gated as follows. A vote-authorized commitment — one whose authorization derives from the computed voting result — is gated by that result per the tri-state below; an objection-authorized negative commitment (defined after the face-value exception) is the single exception to this gate:
- Passed — a positive commitment (
outcome_positive: true) is allowed; a negative commitment is denied unlesscommitment.allow_decline_over_approvalistrue. - Failed — a positive commitment is denied; a negative commitment is allowed iff the decline guard (below) is satisfied.
- NoVotes — the decisive tally is empty. A negative commitment is denied: an empty decisive tally contains no decisive reject, so the decline guard cannot be satisfied. A positive commitment is governed by the bound policy's
schema_version: underschema_version ≥ 3it is denied (every algorithm other thannonefails on the empty tally), and underschema_version ≤ 2it is denied only whencommitment.require_vote_quorumistrue(RFC-MACP-0012 §4.1). Forweighted, a vote cast by a weight-0participant is non-decisive (RFC-MACP-0012 §4.1), so a tally whose total decisive weight is zero — including a ballot set consisting entirely of weight-0votes — is the NoVotes state at every schema version; the weight-0REJECTs such a tally may contain do not satisfy the decline guard.
Decline guard (normative): a vote-authorized negative commitment MUST be backed by at least one decisive explicit Vote with vote == "REJECT" (reject_count > 0, where reject_count counts decisive rejects; under weighted a REJECT cast by a weight-0 participant is non-decisive and does not count), and, when commitment.require_vote_quorum is true, the voting quorum MUST be met. The guard applies across all three voting results and at every policy schema_version.
Face-value exception: when voting.algorithm == "none" (or no policy is bound), the commitment is initiator-driven and outcome_positive is taken at face value with no decline guard. Section 5 rule 5 still applies: no Commitment — positive or negative — may resolve the session before at least one proposal exists.
Objection-authorized decline: when the bound policy sets objection_handling.critical_objection_action to finalize_decline and a standing critical objection blocks the positive direction under the policy's objection-handling rules, a negative commitment is objection-authorized: its authorization is the recorded critical Objection, not the voting result. An objection-authorized decline is not gated by the tri-state above and is not subject to the decline guard — the objection is itself the explicit, attributable dissent the guard exists to require — and it is available at every tally, including the empty tally under schema_version ≥ 3 (RFC-MACP-0012 §4.1). The waiver covers the guard whole, its require_vote_quorum conjunct included: the quorum condition legitimizes an outcome that derives its authority from the voting result, and an objection-authorized decline derives none, so a runtime MUST NOT deny it for an unmet voting quorum. The evaluation prerequisites (evaluation.required_before_voting, evaluation.minimum_confidence; RFC-MACP-0012 §4.1) are prerequisites of the same voting pipeline and likewise MUST NOT be applied to an objection-authorized decline. Applying either gate here reconstructs the stuck state this channel exists to remove: with the gate unmet and no ballot arriving, no Commitment would be acceptable in either direction. Without this channel, a schema_version ≥ 3 session with a non-none algorithm, an empty tally, and a standing critical objection could reach no committed outcome at all, ending only by cancellation or expiry, neither of which records one — precisely the stuck state finalize_decline exists to resolve. This rule applies at every schema version that can express finalize_decline (schema_version ≥ 2). It cannot alter the replay of any stored session: a runtime that formerly read the tri-state as denying such a decline rejected the message, and rejected messages never enter accepted history (RFC-MACP-0001 §8.3).
Both governing knobs — commitment.allow_decline_over_approval (bool, default false) and objection_handling.critical_objection_action (enum deny | finalize_decline | hold, default deny) — are policy-controlled with conservative defaults that preserve pre-existing behavior. See RFC-MACP-0012 §4.1 for their semantics.
7. Determinism class
Decision Mode claims semantic-deterministic determinism.
Given the same accepted message history, the same participant set, and the same bound mode/configuration/policy versions, the same semantic outcome MUST be produced.
8. Security considerations
Implementations MUST address all of the following:
- authenticate the sender of each
Proposal,Evaluation,Objection,Vote, andCommitment, - reject Decision Mode messages from unauthorized senders, distinguishing declared-participant authority from any separately bound coordinator authority,
- protect confidential decision context and proposal data,
- ensure only authorized actors can emit
Commitment, - preserve append-only accepted history for audit and replay.
9. Canonical schemas and examples
Canonical schemas:
schemas/proto/macp/modes/decision/v1/decision.protoschemas/modes/decision.proto
Example transcript:
examples/decision-mode-session.json