Security
This page covers the SDK's security surface — TLS defaults, the expected_sender guardrail, and SDK-level retry behaviour for rate limits. The runtime is the source of truth for authentication, authorization, isolation, replay protection, rate limiting, and audit logging.
- Runtime API § Authentication
- Runtime API § Rate Limiting
- Runtime Deployment § Authentication
- Runtime Policy § Commitment authority
- Per-mode authorization rules: Runtime Modes
For the SDK-side AuthConfig API and identity-mismatch guardrail, see Authentication.
Transport security
TLS 1.2+ is required in production. SDK 0.2.0+ defaults to secure=True; plaintext channels require an explicit allow_insecure=True opt-in:
# Production
client = MacpClient(
target="runtime.example.com:50051",
root_certificates=open("ca.pem", "rb").read(),
auth=AuthConfig.for_bearer("tok-prod-123", expected_sender="my-agent"),
)
# Local dev against MACP_ALLOW_INSECURE=1
client = MacpClient(
target="127.0.0.1:50051",
allow_insecure=True,
auth=AuthConfig.for_dev_agent("my-agent"),
)Passing secure=False without allow_insecure=True raises MacpSdkError so plaintext can never ship accidentally.
For server-side TLS configuration (MACP_TLS_CERT_PATH, MACP_TLS_KEY_PATH), see Runtime Deployment.
Sender identity guardrail
The runtime binds the envelope sender from the authenticated identity and rejects any mismatch. The SDK additionally enforces expected_sender client-side so spoofed senders fail before the envelope leaves the process, surfacing as MacpIdentityMismatchError rather than an opaque UNAUTHENTICATED:
auth = AuthConfig.for_bearer("tok-alice", expected_sender="alice")
session = DecisionSession(client, auth=auth)
session.vote("p1", "approve") # sender defaults to "alice" — OK
session.vote("p1", "approve", sender="mallory")
# ↑ raises MacpIdentityMismatchError(expected="alice", actual="mallory")Always set expected_sender in production. See Authentication for the full pattern, including per-operation auth overrides for multi-participant agents.
Retrying rate limits and transient failures
The runtime enforces per-sender rate limits and returns RATE_LIMITED when exceeded. The SDK ships RetryPolicy + retry_send() for safe exponential-backoff retries (idempotency keys make this safe — see Core Protocol § Envelopes):
from macp_sdk import RetryPolicy, retry_send
policy = RetryPolicy(
max_retries=5,
backoff_base=0.5,
retryable_codes=frozenset({"RATE_LIMITED", "INTERNAL_ERROR"}),
)
retry_send(client, envelope, policy=policy, auth=auth)Limit defaults and environment variables: Runtime API § Rate Limiting.
SDK-side production checklist
Runtime-side hardening (TLS keys, audit logging, token storage, rate-limit tuning) is covered in Runtime Deployment § Production checklist. The items below are SDK-specific:
- Use TLS (default since SDK 0.2.0) — never pass
allow_insecure=Truein prod - Set
expected_senderon everyAuthConfig.for_bearercall so sender spoofing fails fast (MacpIdentityMismatchError) - Use real bearer tokens — never
for_dev_agentin prod - When sending as multiple participants, scope auth per call (see Authentication § Per-operation auth overrides)
- Wrap network calls in
retry_send()with aRetryPolicythat excludes permanent codes (FORBIDDEN,INVALID_ENVELOPE) - Use
SessionLifecycleWatcherfor supervisor visibility rather than pollingGetSession(see Session Discovery)