Examples
The runtime ships with example clients in src/bin that demonstrate each coordination mode. This page walks through what each example does and highlights the runtime behavior you should pay attention to.
For protocol-level example transcripts, see the protocol examples documentation.
All examples target macp-runtime v0.4.0 and use the development security shortcut:
export MACP_ALLOW_INSECURE=1
cargo runThe example binaries attach Authorization: Bearer <sender> metadata so the runtime derives the authenticated sender from the bearer token. Every example creates a session with the required fields: participants, mode_version ("1.0.0"), configuration_version ("config.default"), and a positive ttl_ms.
Decision Mode
cargo run --bin clientThe coordinator initializes the connection, lists available modes, starts a Decision session, submits a proposal, receives an evaluation and a vote from participants, then commits the outcome. After commitment, it queries the session with GetSession to confirm the terminal state.
The runtime enforces automatic phase progression: the first evaluation moves the session from the Proposal phase to Evaluation, and the first vote moves it to Voting. Once in the Voting phase, new proposals are rejected. Commitment version fields must match the bound session versions.
Proposal Mode
cargo run --bin proposal_clientA buyer starts a session, the seller creates a proposal, the buyer counters with a different offer, both participants accept the same live proposal, and the buyer commits. The session does not resolve merely because a proposal exists -- convergence (all required parties accepting the same proposal) must be reached before a commitment is accepted.
Task Mode
cargo run --bin task_clientA planner starts a session, sends a task request, a worker accepts the task, sends a progress update, and reports completion. The planner then commits the result. Only the active assignee can send task updates -- this is enforced against the authenticated sender identity.
Handoff Mode
cargo run --bin handoff_clientAn owner starts a session, sends a handoff offer with context, and the target agent accepts the offer. The owner commits to finalize the responsibility transfer. Only one outstanding offer is allowed at a time, and once an offer is accepted, no further offers can be issued.
Quorum Mode
cargo run --bin quorum_clientA coordinator starts a session, sends an approval request, participants submit their ballots, and the coordinator commits once the approval threshold is met. The runtime accepts a commitment either when enough approvals exist or when the threshold becomes mathematically unreachable.
Multi-Round Mode
cargo run --bin multi_round_clientA coordinator starts a session using ext.multi_round.v1, participants exchange contributions across multiple rounds, and the runtime tracks convergence (all participants contributing the same value). Convergence does not auto-resolve the session -- an explicit commitment is still required. This mode is discoverable via ListExtModes, not ListModes.
StreamSession
StreamSession provides per-session bidirectional streaming. A stream is bound to a session by sending the first session-scoped envelope. From that point, the client receives all accepted envelopes for that session in real time.
Key behaviors to note:
- Use
SessionStartto create a new session over the stream, or send a session-scoped message to attach to an existing one. - For observers and late joiners, send a passive-subscribe frame (
subscribe_session_id+after_sequence) as the first frame -- the runtime replays accepted history starting atafter_sequenceand then delivers live envelopes on the same stream. Useafter_sequence = 0to replay from session start. - Mixed-session streams (envelopes targeting different sessions) are rejected.
- A single frame must not carry both
envelopeandsubscribe_session_id-- the stream terminates withInvalidArgument. - Application errors are delivered inline without closing the stream.
Extension Mode Lifecycle
The runtime supports dynamic extension management through four RPCs:
ListExtModesdiscovers available extensions (includingext.multi_round.v1).RegisterExtModeregisters a new extension with a mode descriptor. The runtime creates a passthrough handler for it.UnregisterExtModeremoves a dynamic extension (built-in modes are protected).PromoteModepromotes an extension to standards-track, optionally renaming it.
Extension mode names must not use the reserved macp.mode.* namespace. All registry changes are broadcast to WatchModeRegistry subscribers, and both GetManifest and Initialize include all modes.
Error Path Testing
cargo run --bin fuzz_clientThis client deliberately exercises failure paths: invalid protocol versions, empty modes, malformed payloads, duplicate messages, unauthorized sender spoofing, oversized payloads, and session access without membership. Use it to verify that the runtime rejects invalid requests correctly.
Troubleshooting
UNAUTHENTICATED: Start the runtime without MACP_AUTH_* configured (so dev-mode auth is active) and ensure the client sets Authorization: Bearer <sender>. With auth resolvers configured, send a matching static bearer or JWT instead.
INVALID_ENVELOPE on SessionStart: Verify that the mode name is canonical, the payload is not empty, and all four required fields (mode_version, configuration_version, ttl_ms > 0, participants) are present.
SESSION_NOT_OPEN: The session has already been resolved or expired. Use GetSession to confirm the terminal state.
RATE_LIMITED: Increase the limits if appropriate:
export MACP_SESSION_START_LIMIT_PER_MINUTE=120
export MACP_MESSAGE_LIMIT_PER_MINUTE=2000