Who this is for: Everyone -- developers integrating SDKs, DevOps engineers configuring pipelines, compliance officers using the dashboard, assessors reviewing evidence, and account administrators managing billing. If you have a question, start here.
1. Getting Started and Onboarding
How do I create an account?
- Go to sovereign.tenova.io/signup
- Enter your email, password, organization name, and select your primary framework (NIST 800-53, CMMC, AI RMF, EU AI Act, SR 11-7, or NIST 800-171).
- On success, you receive a tenant ID and API key. Copy the API key immediately -- it is shown once and cannot be recovered.
- You start on the OPEN (Free) tier with 10 requests/second and 100 anchors/month.
My API key is not working (401 error)
- Check the format: Keys must start with
axm_live_oraxm_trial_. If yours does not, it is not a valid SWT3 API key. - Check for whitespace: Copy-paste can add leading/trailing spaces. Trim the key.
- Check the header format: It must be
Authorization: Bearer axm_live_...(with the word "Bearer" and a space). - Key lost? Keys are stored as SHA-256 hashes -- the raw key cannot be recovered. Go to Settings > API Keys and create a new one.
- Key revoked? Check the audit log at Settings > Audit Log to see if someone revoked it.
Diagnostic command:
curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer $SWT3_API_KEY" \
https://sovereign.tenova.io/api/v1/health
If this returns 200, your key is valid. If 401, the key is invalid or revoked.
My first anchor is not appearing in the dashboard
This is the most common onboarding issue. Work through these checks in order:
- Verify connectivity:
curl https://sovereign.tenova.io/api/v1/healthshould return{"status":"healthy"}. If it does not, check your firewall allows outbound HTTPS (port 443). - Verify your API key works: See the diagnostic command above.
- Check that the SDK flushed: The SDK buffers anchors and flushes asynchronously. Call
witness.flush()(Python) orawait witness.flush()(TypeScript) explicitly during testing. - Check your tenant ID: The tenant ID in the SDK must match the one shown in Settings on the dashboard.
- Check the clearing level: At Clearing Level 3 (Classified),
ai_model_idis hashed. The anchor still exists in the ledger but model names appear as hashes. - Check the dashboard filter: The ledger page has filters for verdict type and time range. Make sure "All" is selected.
How do I install the SDK?
| Language | Install Command | Verify |
|---|---|---|
| Python | pip install swt3-ai | python -c "import swt3_ai; print(swt3_ai.__version__)" |
| TypeScript | npm install @tenova/swt3-ai | node -e "console.log(require('@tenova/swt3-ai').version)" |
| Rust | cargo add swt3-ai | cargo build |
| C# | dotnet add package swt3-ai | dotnet build |
| Ruby | gem install swt3-ai | ruby -e "require 'swt3_ai'; puts Swt3Ai::VERSION" |
| Swift | Add https://github.com/tenova-labs/swt3-ai-swift via SPM | Build in Xcode |
| Kotlin | Add Maven Central dependency io.tenova:swt3-ai | ./gradlew build |
| MCP | npm install @tenova/swt3-mcp | npx swt3-mcp --version |
Minimum runtime versions: Python 3.9+, Node.js 18+, Rust stable, .NET 6+, Ruby 3.0+, Swift 5.9+, Kotlin 1.9+.
What environment variables does the SDK need?
| Variable | Required | Description |
|---|---|---|
SWT3_API_KEY | Yes (cloud mode) | Your API key starting with axm_ |
SWT3_ENDPOINT | No | Override the default endpoint. Defaults to https://sovereign.tenova.io |
SWT3_TENANT_ID | Yes | Your tenant identifier (shown in Settings) |
SWT3_CLEARING_LEVEL | No | Default clearing level (0-3). Defaults to 1. |
Alternatively, pass these as constructor arguments: Witness(api_key="...", tenant_id="...", clearing_level=1)
What is the difference between local mode and cloud mode?
| Feature | Local Mode | Cloud Mode |
|---|---|---|
| Network required | No | Yes |
| API key required | No | Yes |
| Anchors stored | Local WAL file | Cloud evidence ledger |
| Dashboard visible | No | Yes |
| Verification | Terminal SHA-256 only | Public verifier + Merkle proofs |
| Retention | Unlimited (your disk) | By tier (7d / 90d / 365d / unlimited) |
Local mode is useful for evaluation, air-gapped environments, and development. To switch to cloud mode, add your API key and tenant ID. See the Self-Hosted Quick Start.
How do I run the SDK demo?
Both Python and TypeScript SDKs include a zero-dependency demo that works without an API key:
# Python python -m swt3_ai.demo # TypeScript npx swt3-demo
The demo mints sample anchors locally and verifies them via SHA-256. No network connection or API key required.
2. SDK Integration
The Python class is Witness, not SWT3Witness
The correct import is:
from swt3_ai import Witness
Not from swt3_ai import SWT3Witness. There is no SWT3Witness class.
What is the difference between wrap() and individual witness methods?
wrap(client) is the recommended approach. It creates a transparent proxy around your OpenAI, Anthropic, Bedrock, or LiteLLM client. Every inference is witnessed automatically with zero code changes.
Individual methods (e.g., witness_drift(), witness_hardware(), witness_rag_context()) are for custom pipelines where you control the exact procedure and factors.
Use wrap() for standard inference witnessing. Use individual methods for specialized procedures like RAG provenance, model weight attestation, or hardware health.
My fingerprints do not match across languages
The fingerprint formula is:
SHA256("WITNESS:{tenant_id}:{procedure_id}:{factor_a}:{factor_b}:{factor_c}:{fingerprint_timestamp_ms}").hex()[:12]
Common causes of mismatch:
- Timestamp precision: The formula uses milliseconds, not seconds. A timestamp of
1774800000(seconds) is wrong -- it should be1774800000000(milliseconds). - Tenant ID casing: Tenant IDs are case-sensitive.
DEMO_TENANTanddemo_tenantproduce different fingerprints. - Factor types: Factors must be integers, not floats.
1.0and1may produce different string representations depending on the language.
Verify against the published test vectors:
echo -n "WITNESS:ENCLAVE_PROD:AI-INF.1:1:1:0:1774800000000" | sha256sum | cut -c1-12
# Expected: 2e16e2fe92dd
The test-vectors.json file contains 55 fingerprint vectors verified across all 9 SDKs.
flush_interval is in seconds, not milliseconds
A common mistake: flush_interval=5000 means 5,000 seconds (83 minutes), not 5 seconds.
# Correct: flush every 5 seconds witness = Witness(flush_interval=5.0) # Wrong: flush every 83 minutes witness = Witness(flush_interval=5000)
The default is 30 seconds. For testing, use flush_interval=1.0 or call witness.flush() manually.
What is the dead-letter queue and why is it growing?
When the SDK cannot reach the API (network timeout, server error, rate limit), it stores failed payloads in a dead-letter queue. These are retried automatically on the next flush cycle.
If the queue keeps growing:
- Check connectivity:
curl https://sovereign.tenova.io/api/v1/health - Check your API key is valid (not revoked).
- Check you are not hitting the monthly anchor limit (OPEN tier: 100/month).
- The queue is bounded in memory. If your process restarts, undelivered payloads are lost. For mission-critical environments, use
signing_keyfor tamper detection and monitor the queue size.
How does the SDK handle network timeouts?
The Python and TypeScript SDKs never block your application. Witnessing is asynchronous:
- The SDK queues anchors in memory.
- A background flush sends them to the API.
- If the API is unreachable, the SDK stores payloads in the dead-letter queue and retries on the next flush cycle.
- Your inference call returns immediately -- witnessing never adds latency to your AI pipeline.
For the Rust, C#, and Ruby SDKs (core primitives), you handle HTTP transport yourself. The SDK provides fingerprint minting and signing only.
How do I set up a signing key?
Signing keys add tamper detection. The SDK signs each anchor's fingerprint with HMAC-SHA256, and the server verifies the signature.
# Python
witness = Witness(
api_key="axm_live_...",
tenant_id="YOUR_TENANT",
signing_key="your-secret-key-here"
)
The server validates signatures progressively -- if you provide a signature, it must be valid. If you do not provide one, the anchor is accepted as unsigned.
Key rotation: Create a new Witness instance with the new key. The server accepts signatures from any registered key. After all clients are updated, revoke the old key.
What clearing level should I use?
| Level | Name | What the Server Sees | Use When |
|---|---|---|---|
| 0 | Analytics | Full prompt, response, and metadata | Internal testing, non-sensitive workloads |
| 1 | Standard | Hashes of prompt/response + factors | Production (recommended default) |
| 2 | Sensitive | Hashes + factors only, no metadata beyond model_id | PII-heavy workloads, healthcare, finance |
| 3 | Classified | Factors only, model_id hashed, zero metadata | Defense, SCIF, classified environments |
Level 1 is the recommended default. It provides full auditability with zero exposure of sensitive content.
How do I check my SDK version?
# Python pip show swt3-ai # TypeScript npm list @tenova/swt3-ai # MCP npm list @tenova/swt3-mcp # Rust cargo tree -p swt3-ai # Ruby gem list swt3-ai
Current version: 0.6.4 (Python, TypeScript, Rust, C#, Ruby, Swift, MCP). Kotlin: 0.1.1.
3. API Integration
I am getting a 401 Unauthorized error
The three most common causes:
- Missing header: The header must be exactly
Authorization: Bearer axm_live_.... Note the capital "B" in Bearer and the space before the key. - Wrong key format: Keys must start with
axm_. If your key starts with anything else, it is not a valid SWT3 key. - Revoked key: If the key was revoked (by you or another admin), it returns 401. Generate a new key at Settings > API Keys.
I am getting a 403 Forbidden error
403 means your authentication succeeded, but you lack permission:
- "Enclave tier required" -- You are on OPEN or PRO tier. Webhooks, VC export, and some endpoints require Enclave ($9,500/mo) or higher.
- "Assessor mode is read-only" -- You are logged in as an assessor. Assessors cannot create, modify, or delete resources.
- "Admin role required" -- This action requires the admin role. Check your role at Settings.
- "Agent revoked" -- The agent_id in your payload was revoked via AI-REV.1. Re-register the agent or use a different agent_id.
I am getting a 400 Validation Error
The error message tells you exactly what is wrong. Common causes:
- "Unknown AI procedure" -- The procedure_id is not recognized. Check the UCT Registry for valid IDs (113 total).
- "clearing_level must be 0-3" -- You passed a value outside this range.
- "Anchor timestamp out of bounds" -- The
fingerprint_timestamp_msis more than 24 hours old or more than 5 minutes in the future. Sync your system clock via NTP. - "Anchor fingerprint validation failed" -- The factors in the request body do not match the fingerprint. Something modified the request body between SDK and server (proxy, middleware, serialization).
- "Invalid lifecycle_chain_id format" -- Must match
LC-[0-9a-f]{16}(the prefix "LC-" followed by exactly 16 hex characters).
I am getting a 429 Rate Limit Exceeded error
Two types of rate limits:
- Per-second limit: OPEN=10/s, PRO=50/s, ENCLAVE=200/s, SOVEREIGN=500/s. Use the
Retry-Afterheader to determine wait time. Implement exponential backoff. - Monthly anchor limit: OPEN tier is limited to 100 anchors per calendar month. Upgrade to Pro for unlimited.
Optimization tips:
- Use the batch endpoint (
POST /api/v1/witness/batch) to send up to 500 anchors in one request. - Increase
flush_intervalto batch more anchors per flush cycle. - If you are hitting limits regularly, upgrade your tier.
I am getting a 502 error with an AXM-XXXX reference code
502 errors are transient upstream failures (database write, external service timeout). They are always retryable.
- Wait 5-10 seconds and retry.
- If the error persists for more than 5 minutes, check the health endpoint:
curl https://sovereign.tenova.io/api/v1/health - Include the
AXM-XXXXreference code when contacting support@tenovaai.com. This code links to server-side logs for fast diagnosis.
What Content-Type header should I use?
Always: Content-Type: application/json. The API only accepts JSON request bodies. If you omit this header, you may receive a 400 error or unexpected behavior.
How do I handle partial success in batch requests?
The batch endpoint validates each payload independently. The response includes both accepted and rejected counts, and rejected items include an error field:
{
"results": [
{ "procedure_id": "AI-INF.1", "verdict": "PASS", "swt3_anchor": "SWT3-..." },
{ "procedure_id": "AI-FOO.1", "error": "Unknown AI procedure: AI-FOO.1" }
],
"accepted": 1,
"rejected": 1
}
Check the rejected count and handle individual errors. Do not retry the entire batch -- only retry rejected items after fixing the validation issue.
4. Webhook Integration
My webhook is not firing
Work through this checklist:
- Tier check: Webhooks require Enclave tier ($9,500/mo) or above. OPEN and PRO tiers do not have webhook access.
- Subscription active? Go to Settings > Webhooks. Verify
is_activeis true. - Event types match? If you subscribed to
verdict.failedbut all your anchors are PASS, no webhook fires. Addverdict.issuedto capture PASS verdicts too. - URL reachable? Your endpoint must be HTTPS and publicly reachable. Localhost URLs do not work.
- Test it: Use
POST /api/v1/webhooks/:id/testto send a testpingevent. Check the delivery status atGET /api/v1/webhooks/:id/deliveries.
HMAC signature verification is failing
The X-SWT3-Signature header contains an HMAC-SHA256 hex digest of the raw request body using your webhook secret.
Common causes of verification failure:
- Parsing before verifying: You must verify the signature against the raw bytes, not a parsed/re-serialized JSON string. Parsing may reorder keys or change whitespace.
- Wrong secret: The secret (
whsec_...) is shown once when you create the subscription. If lost, delete the subscription and create a new one. - Encoding mismatch: The signature is hex-encoded (not base64). Use
hexdigest()notb64encode().
See the API Reference -- Webhooks for Python and TypeScript verification code.
What event types are available?
| Event | Description |
|---|---|
verdict.issued | A PASS verdict was recorded |
verdict.failed | A FAIL verdict was recorded |
drift.detected | A control changed from PASS to FAIL |
attestation.lapsed | A manual attestation expired |
score.threshold | Sovereign Score dropped below threshold |
hw.attestation.stale | Hardware attestation exceeds staleness window |
hw.drift.detected | Hardware configuration drift detected |
ping | Test event from the test endpoint |
How do I check delivery history and failures?
Use GET /api/v1/webhooks/:id/deliveries to see delivery attempts, HTTP status codes, response bodies, and retry status. This helps you debug why deliveries are failing on your end (e.g., 500 from your server, TLS error, timeout).
5. Verification and Anchors
How do I verify an anchor?
Three methods, from simplest to most rigorous:
- Web UI: Go to sovereign.tenova.io/verify, paste the anchor token, and click Verify. No login required.
- API:
GET /api/v1/verify/public?token=SWT3-E-VULTR-AI-AI-INF.1-PASS-... - Terminal (offline): Re-derive the fingerprint from the factors:
echo -n "WITNESS:{tenant}:{proc}:{fa}:{fb}:{fc}:{ts_ms}" | sha256sum | cut -c1-12If the output matches the last 12 characters of the anchor token, the factors are authentic.
What is the difference between structural verification and ledger verification?
Structural verification (public endpoint) confirms the anchor token is well-formed and the fingerprint is mathematically valid. It does not query the ledger.
Ledger verification (dashboard or Merkle proof) confirms the anchor exists in the immutable compliance ledger and has a valid Merkle inclusion proof.
For audits, use both: structural verification for quick checks, Merkle proofs for cryptographic certainty.
Why does my anchor look different from older anchors?
Legacy anchors minted before v5.21.0 may have slightly different formatting. Specifically, older anchors may strip hyphens and periods from procedure IDs (e.g., AI-GRD.1 becomes AIGRD1). The public verifier checks both formats automatically.
How does revocation work?
Revocation (AI-REV.1) creates a new anchor that marks a previous anchor as revoked. Seven reason codes:
| Code | Reason |
|---|---|
| 0 | Unspecified |
| 1 | Model recall |
| 2 | Policy violation |
| 3 | Data contamination |
| 4 | Consent withdrawal |
| 5 | Regulatory order |
| 6 | Error correction |
SDK: witness.revoke(fingerprint, reason="policy_violation")
An anchor exists but is not showing in the dashboard
- Tenant mismatch: You may be logged into a different tenant than the one used by the SDK.
- Ledger filters: Clear all filters (verdict, type, time range) on the Ledger page.
- Retention: OPEN tier anchors expire after 7 days. If the anchor is older, it has been purged.
- Eventual consistency: After a witness ingestion, there may be a 1-2 second delay before the anchor appears in dashboard queries.
6. Dashboard and Audit Portal
I cannot log in to the dashboard
- Email + password login: Use the email and password you registered with at signup. If you forgot your password, click "Forgot password" on the login page.
- MFA enrolled? If you enabled TOTP MFA, you need your authenticator app code after entering your password.
- Browser cookies: The dashboard uses httpOnly session cookies. Ensure cookies are enabled and not blocked by browser extensions.
- Incognito/private mode: Try a regular browser window. Some privacy extensions block session cookies.
How do I set up MFA (multi-factor authentication)?
- Log in to the dashboard.
- Go to Settings.
- Click Enable MFA.
- Scan the QR code with your authenticator app (Google Authenticator, Authy, 1Password, etc.).
- Enter the 6-digit code to confirm enrollment.
MFA uses TOTP (Time-based One-Time Password). The codes rotate every 30 seconds. Make sure your device clock is accurate.
How do I share audit access with an external assessor?
- Go to Settings > Auditor Share Links (Pro+ tier).
- Click Create Share Link.
- Send the generated URL to your assessor.
The assessor can view evidence, submit findings, and export the conformity evidence package. They cannot modify verdicts, attestations, or settings. No account creation required.
What can an assessor see vs. what they cannot?
| Can See | Cannot See / Do |
|---|---|
| Controls catalog | Gap analysis (ISSM-only) |
| Compliance ledger (all verdicts) | Settings or configuration |
| Anchor verification | Create/revoke API keys |
| Evidence exports | Manage tenants or users |
| Submit findings | Modify verdicts or attestations |
| Merkle proofs | Evidence ingestion |
What export formats are available from the dashboard?
- OSCAL: SSP, POA&M, Assessment Results (JSON, validated against NIST oscal-cli)
- Compliance Passport: HTML, HMAC-signed JSON (Pro+), W3C Verifiable Credential (Enclave+)
- Executive Summary: Self-contained HTML, printable to PDF
- Gap-to-Green: Self-contained HTML with score ring and remediation roadmap
- Ledger: CSV or JSON from the Ledger page
- CVE Report: Printable HTML with POA&M status and SWT3 anchor
- Conformity Evidence Package: SWT3 Spec v1.0.1 format (from audit portal)
7. Compliance and Exports
Which compliance frameworks are supported?
36 frameworks including: NIST 800-53, CMMC, NIST AI RMF 100, EU AI Act, FedRAMP, SR 11-7, NIST 800-171, ISO 42001, GPAI Code of Practice, NIST CSF 2.0, MITRE ATLAS, OWASP Top 10 for LLMs, and 24 more. See the UCT Registry for the full list with crosswalk mappings.
How do Compliance Passport format options differ?
| Format | Minimum Tier | Machine-Readable | Self-Verifiable |
|---|---|---|---|
| HTML | Pro | No | No |
| JSON (HMAC) | Pro | Yes | Server-side only |
| W3C VC (Ed25519) | Enclave | Yes | Yes (any verifier) |
The W3C Verifiable Credential format is self-verifiable -- anyone with the public key (published in the DID document at did:web:sovereign.tenova.io) can verify the passport without contacting TeNova.
What is the data retention policy by tier?
| Tier | Anchor Retention | Export Retention |
|---|---|---|
| OPEN (Free) | 7 days | On-demand (no storage) |
| PRO | 90 days | 90 days |
| ENCLAVE | 365 days | 365 days |
| SOVEREIGN | Unlimited | Unlimited |
After retention expires, anchors are purged from the ledger. Exported artifacts (OSCAL, Passport, reports) remain on your infrastructure.
How do crosswalk mappings work?
Crosswalks map procedures from one framework to another. For example, NIST 800-53 AC-2 maps to CMMC AC.L2-3.1.1. There are 1,057 crosswalk rows across 36 frameworks.
Use the API: POST /api/v1/crosswalks/resolve with source and target frameworks. Or browse the full matrix at GET /api/v1/crosswalks/matrix.
OSCAL export is failing or contains validation errors
All OSCAL exports are validated against NIST oscal-cli v3.1.0 (JRE 21) before delivery. If validation fails:
- The export will still be returned but will include a validation status section.
- Common issue: custom control IDs that do not match the NIST catalog. This does not affect the evidence quality.
- For eMASS compatibility, use
GET /api/v1/emass-guidewhich documents the 2 pre-import adjustments needed (system-id and POA&M risk-level property mapping).
8. Operations and Scaling
How do I monitor the API health?
curl -s https://sovereign.tenova.io/api/v1/health | jq .
# Expected: {"status":"healthy","checks":{"supabase":true},...}
Set up automated monitoring (Datadog, UptimeRobot, Pingdom) against this endpoint. Alert on:
- HTTP status != 200
checks.supabase== false- Response time > 2 seconds
How do I rotate API keys without downtime?
- Create a new key at Settings > API Keys. (You can have up to 5 active keys.)
- Update your SDK configuration and CI/CD pipelines to use the new key.
- Verify anchors flow with the new key (check the ledger for new entries).
- Revoke the old key once you confirm no systems still use it.
Both keys work simultaneously during the transition. There is zero downtime.
How do I upgrade my tier?
- Pro or Enclave: Go to Settings and click the upgrade button. Payment is processed via Stripe. Tier activation is instant.
- Sovereign: This is a sales-led engagement ($125,000 ATO sprint). Contact support@tenovaai.com.
Upgrading preserves all existing anchors, API keys, and configuration. No migration required.
How do I deploy in an air-gapped environment?
SWT3 is designed for air-gapped deployment. The SDK works in local mode with zero network dependency:
- Install the SDK package via your internal mirror or manual file transfer.
- Initialize without an API key:
Witness(tenant_id="YOUR_ENCLAVE") - Anchors are stored in a local Write-Ahead Log (WAL).
- Verify anchors using the terminal SHA-256 method (no network required).
- Optionally sync to the cloud ledger later using .pulse bundles.
See the Self-Hosted Quick Start for detailed deployment patterns.
How do I optimize for high throughput?
- Use batch ingestion:
POST /api/v1/witness/batchaccepts up to 500 anchors per request, reducing HTTP overhead. - Increase flush_interval: Larger intervals batch more anchors per flush cycle (e.g.,
flush_interval=30seconds). - Upgrade tier: OPEN=10 req/s, PRO=50, ENCLAVE=200, SOVEREIGN=500.
- The API handles ~227 anchors/second on the current infrastructure (benchmarked). This supports 19.6 million anchors per day.
9. Billing and Account
How do I manage my subscription?
Go to Settings > Manage Billing (Pro+ tiers). This opens the Stripe billing portal where you can:
- Update your payment method
- View invoices and payment history
- Change your plan
- Cancel your subscription
What happens if I cancel my subscription?
Your account is automatically downgraded to the OPEN (Free) tier. All existing data is preserved -- no data is deleted. However:
- Anchor retention drops to 7 days (anchors older than 7 days are purged on a rolling basis).
- Rate limit drops to 10 req/s and 100 anchors/month.
- Webhook subscriptions are deactivated (Enclave+ feature).
- Compliance Passport export is disabled (Pro+ feature).
What are the subscription tiers and pricing?
| Tier | Monthly | Annual | Key Features |
|---|---|---|---|
| OPEN | Free | Free | 10 req/s, 100 anchors/mo, 7-day retention, local mode |
| PRO | $499 | $4,990 | 50 req/s, unlimited anchors, 90-day retention, Passport export, Auditor Share |
| ENCLAVE | $9,500 | $102,000 | 200 req/s, 365-day retention, W3C VC export, webhooks, agent governance |
| SOVEREIGN | Contact us | Contact us | 500 req/s, unlimited retention, dedicated support, ATO sprint |
How do I check how many anchors I have used this month?
For OPEN tier, the monthly limit (100 anchors) is enforced server-side. When you hit the limit, witness requests return 429 with the message "Monthly anchor limit reached (100)". The counter resets on the 1st of each calendar month (UTC).
Pro, Enclave, and Sovereign tiers have unlimited monthly anchors.
10. Still Need Help?
If you have worked through this guide and the API Reference and still cannot resolve your issue:
- Email: support@tenovaai.com -- include your tenant ID and any AXM-XXXX reference codes from error responses.
- SDK Documentation: sovereign.tenova.io/docs -- Python and TypeScript reference with tabbed examples.
- UCT Registry: sovereign.tenova.io/registry -- browse all 114 AI procedures with framework mappings.
- Public Verifier: sovereign.tenova.io/verify -- verify any anchor without logging in.
- All Guides: sovereign.tenova.io/guides -- regulatory crosswalks, integration patterns, and deployment guides.
pip show swt3-ai or npm list @tenova/swt3-ai). This eliminates the first round of back-and-forth.