SDK capabilities & conformance

The aitp wheel ships a core v0.1 surface (identity, handshake, TCT verify, delegation, revocation) plus several experimental surfaces gated behind Cargo experimental-* features. A given wheel may or may not expose renewal, session bundles, SPKI pinning, the TCT verification cache, or multi-hop delegation verification — it depends on how it was built. This page covers how the playground discovers what's installed and degrades cleanly, plus the RFC conformance harness.

Source: src/aitp_playground/capabilities.py, src/aitp_playground/conformance.py, src/aitp_playground/api/health.py.

Feature detection

capabilities.py probes the installed wheel by hasattr (the same convention as tests/unit/test_sdk_blocked_features.py) and reports a stable set of feature keys. The probe never raises — if the wheel is absent (e.g. CI without it), every feature reports False and sdk_available is False.

Feature keyDetected byBacking surface
oidchasattr(aitp, "JwksProvider")RFC-AITP-0002 OIDC identity binding
session_bundlehasattr(aitp, "SessionBundleBuilder")RFC-AITP-0010 session bundles
spki_pinninghasattr(aitp, "SpkiPinVerifier")SPKI client-cert pinning
tct_renewalhasattr(AitpAgent, "build_renewal_request")RFC-AITP-0005 §10 in-band renewal
tct_cachehasattr(aitp, "TctStore")RFC-AITP-0005 verification cache
multihop_delegationhasattr(aitp, "verify_delegation_experimental_multihop")RFC-AITP-0011 multi-hop delegation

The keys are stable across releases — scenarios reference them by name when declaring a required capability, so don't rename them. The probe is LRU-cached (the installed wheel doesn't change during a process lifetime); tests that monkeypatch the SDK call get_capabilities.cache_clear() to force a re-probe.

Helpers: get_capabilities() (full report dict), has_feature(name), sdk_available().

GET /capabilities

The probe is exposed so operators can see the wheel's true surface at runtime:

curl -s http://localhost:8000/capabilities | jq .
{
  "sdk_available": true,
  "version": "0.2.1",
  "features": {
    "oidc": true,
    "session_bundle": false,
    "spki_pinning": true,
    "tct_renewal": true,
    "tct_cache": true,
    "multihop_delegation": false
  }
}

version comes from aitp.__version__ if present, otherwise the installed distribution metadata for aitp — the compiled wheel doesn't always set __version__.

Building a feature-complete wheel

The native build flag controls which experimental surfaces compile in:

cd ../aitp-rs/bindings/aitp-py
maturin develop --release --features experimental   # enables all experimental-* gates

Without --features experimental the core surface still works; the experimental scenarios degrade rather than crash (see below). The Docker build's INSTALL_EXTRAS and feature wiring is in docker.md. The build flags and what each feature gate turns on are documented by the SDK itself — aitp-rs · sdk-python.md § Build and the aitp-py README.

Graceful degradation

Scenarios that exercise an experimental surface check GET /capabilities (or the SDK raises) and degrade cleanly when the wheel lacks the feature — the step records a "feature not available" outcome instead of crashing the run. This is why you can run the whole scenario catalog against a core-only wheel and still get a clean event log.

The feature-gated step types and their scenarios:

FeatureStep typesDemo scenario
oidc(handshake with an identity_type: oidc agent)intra-org/oidc-identity
tct_renewalrenew_tctintra-org/tct-renewal
tct_cachetct_cache_statsintra-org/tct-cache-perf
session_bundleexport_session_bundle, verify_session_bundleintra-org/session-bundle
spki_pinningspki_pin_checkintra-org/spki-pinning
multihop_delegationdelegate / redeem_delegation (2-hop)intra-org/delegation-multihop

See aitp-integration.md for where each SDK surface is actually called.

Conformance harness

conformance.py catalogs the RFC conformance fixtures shipped by the specs repo (agentidentitytrustprotocol/schemas/conformance/, located as a sibling checkout) and reports which ones the installed wheel could execute. It's a metadata/readiness report — it does not run the fixtures; it classifies them. (The fixtures are owned by the spec; the SDK's own pass/fail status against them is the aitp-rs conformance matrix.)

Run it from the CLI:

uv run python -m aitp_playground.cli conformance
# Conformance corpus: /…/agentidentitytrustprotocol/schemas/conformance
#   installed SDK: aitp 0.2.1
#   fixtures: 42  (required for v0.1: 31)
#   by RFC:   {'RFC-AITP-0001': 6, 'RFC-AITP-0005': 9, ...}
#   by tier:  {'core': 31, 'extension': 8, 'draft': 3}
#   wheel readiness: {'core': 31, 'available': 5, 'skipped': 6}
#   ok  fixture metadata valid

uv run python -m aitp_playground.cli conformance --json          # raw report
uv run python -m aitp_playground.cli conformance --fixtures-dir <path>

Each fixture carries metadata (id, rfc, status, required_for_v0_1, feature). The harness:

  • validates metadata — required fields present, status is one of core/draft/extension/reserved, rfc is RFC-AITP-####-shaped, and a non-core fixture can't be required_for_v0_1. Any violation makes the command exit non-zero (CI can gate on a malformed corpus).
  • classifies readiness per fixture against the installed wheel:
    • core — no feature gate; always runnable.
    • available — feature-gated and the wheel exposes the feature.
    • skipped — feature-gated and the wheel lacks the feature.
    • unknown-feature — the fixture names a feature the playground doesn't map (FEATURE_TO_CAPABILITY).

build_report() returns the structured form (total, required_for_v0_1, by_rfc, by_tier, by_readiness, metadata_errors, valid) — the same dict the --json flag prints.