Session Classes API Reference

All session classes follow the same base pattern. They differ only in their mode-specific methods.

Common Pattern

Every session class:

  1. Constructor: new XxxSession(client, options?)
  2. Properties: client, sessionId, modeVersion, configurationVersion, policyVersion, auth, projection
  3. Lifecycle: start(input) → mode-specific methods → commit(input)
  4. Control plane: cancel(reason?, auth?), suspend(reason?, auth?), resume(reason?, auth?) — thin wrappers over the client's cancelSession/suspendSession/resumeSession for this session's id. Suspension is non-terminal: TTL is banked and restored on resume().
  5. Metadata: metadata(auth?) queries session state from runtime
  6. Streaming: openStream(auth?) opens a MacpStream with the session's auth
  7. Projection: session.projection provides typed local state

Common Options

interface SessionOptions {
  sessionId?: string;             // default: auto-generated UUIDv4
  modeVersion?: string;           // default: '1.0.0'
  configurationVersion?: string;  // default: 'config.default'
  policyVersion?: string;         // default: 'policy.default'
  auth?: AuthConfig;              // default: uses client.auth
}

Common start() Input

{
  intent: string;                                    // session purpose
  participants: string[];                            // participant identifiers
  ttlMs: number;                                     // time-to-live in milliseconds
  maxSuspendMs?: number;                             // proto ≥ 0.1.5; max cumulative suspend (0 = runtime default)
  contextId?: string;                                // optional shared-context reference
  extensions?: Record<string, Buffer>;               // optional extension payloads by key
  roots?: { uri: string; name?: string }[];          // optional coordination roots
  sender?: string;                                   // optional sender override
  auth?: AuthConfig;                                 // optional per-call credential override
}

start()'s validation is identical across all five built-in mode sessions and BaseSession — participants must be non-empty (no duplicate participants), ttlMs must be in range, and maxSuspendMs (if given) must be >= 0. intent may be empty or omitted (issue #124 item 3): it's a proto3 singular string field with implicit presence — an omitted value and an explicit '' are wire-identical — and RFC-MACP-0001 §7.1 states a runtime "MUST NOT reject a SessionStart solely because intent is empty."

Common commit() Input

{
  action: string;             // outcome descriptor (e.g., 'deployment.approved')
  authorityScope: string;     // scope of authority
  reason: string;             // auditable reason
  commitmentId?: string;      // default: auto-generated UUID
  outcomePositive?: boolean;  // default: inferred from action (endsWith 'rejected'/'failed'/'declined' → false)
  sender?: string;
  auth?: AuthConfig;
}

Session Classes Summary

ClassModeKey Methods
DecisionSessionmacp.mode.decision.v1propose, evaluate, raiseObjection, vote
ProposalSessionmacp.mode.proposal.v1propose, counterPropose, accept, reject, withdraw
TaskSessionmacp.mode.task.v1request, acceptTask, rejectTask, update, complete, fail
HandoffSessionmacp.mode.handoff.v1offer, addContext, acceptHandoff, decline
QuorumSessionmacp.mode.quorum.v1requestApproval, approve, reject, abstain

BaseSession (custom modes)

BaseSession<P extends BaseProjection> is the abstract base for building session helpers for custom modes registered via registerExtMode. It provides the shared lifecycle (start, commit, cancel, suspend, resume, metadata, openStream) plus the identity-guarded protected helpers senderFor(sender?, auth?) and sendAndTrack(envelope, auth?). Subclasses supply the mode string and a createProjection() factory. The five built-in session classes pre-date BaseSession and implement their own equivalents, but expose the same surface.

import { BaseSession } from 'macp-sdk-typescript';

class CustomSession extends BaseSession<CustomProjection> {
  protected readonly mode = 'ext.custom.v1';
  protected createProjection() { return new CustomProjection(); }
}

Per-Method Auth Override

All mode-specific methods accept optional sender and auth fields:

await session.vote({
  proposalId: 'p1',
  vote: 'approve',
  sender: 'alice',                // populate envelope.sender
  auth: Auth.devAgent('alice'),   // use alice's credentials for this call
});

This enables a single process to act on behalf of multiple agents within the same session.

Identity Guard

Every mode-specific method that accepts a sender parameter runs the SDK's identity guard before the envelope is built. When auth.expectedSender is configured (via Auth.bearer(token, { expectedSender })), a caller-supplied sender that disagrees raises MacpIdentityMismatchError — client-side, before any RPC hits the wire (RFC-MACP-0004 (Security) §4).

import { Auth, DecisionSession, MacpIdentityMismatchError } from 'macp-sdk-typescript';

const session = new DecisionSession(client, {
  auth: Auth.bearer('alice-token', { expectedSender: 'alice' }),
});

try {
  await session.propose({ proposalId: 'p1', option: 'x', sender: 'mallory' });
} catch (err) {
  if (err instanceof MacpIdentityMismatchError) {
    err.expectedSender; // 'alice'
    err.actualSender;   // 'mallory'
  }
}

The guard is silent when expectedSender is undefined. Auth.devAgent(...) and the legacy Auth.bearer(token, 'hint') form preserve pre-0.2 behaviour — the SDK resolves sender from the hint but does not reject mismatched overrides.

start() participates in this guard too, using its own auth/sender fields — every mode session's start() (including BaseSession.start()) threads a per-call auth through the same senderFor() helper as every other method.

Identity Auto-Fill

TaskSession's acceptTask/rejectTask/completeTask/failTask default assignee to the resolved sender when omitted or an explicit empty string. HandoffSession.acceptHandoff's acceptedBy and decline's declinedBy behave the same way. This matches macp-sdk-python, which has always defaulted these identity fields to the caller's own identity rather than requiring it to be repeated.

Projection Integration

Each sendAndTrack() call:

  1. Builds an envelope with buildEnvelope() + ProtoRegistry.encodeKnownPayload()
  2. Sends via MacpClient.send() (throws MacpAckError on nack)
  3. On success (ack.ok === true), applies the envelope to the projection

Rejected messages are never applied to the projection.

For full details on each session class, see the Mode documentation.