Checklist and step-by-step guide for taking a 9thSense agent from development to production

Deploy to Production


This guide covers everything you need to do before and after deploying a 9thSense agent to a live environment — production API keys, webhook verification, error handling, and monitoring.


Pre-deployment checklist

  • Agent is built and tested in the Playground with at least 5 real document samples
  • All pipeline steps are validated (no steps returning unexpected null fields)
  • Review policy is configured (or intentionally left blank for auto-complete)
  • A webhook endpoint is deployed and can receive HTTPS POST requests
  • Your backend has a retry mechanism for 5xx responses from the 9thSense API
  • You have a write-scoped production API key (not the development key)

Step 1 — Deploy the agent

  1. Go to Agents in the dashboard.
  2. Open your agent and confirm it is at the version you want to deploy.
  3. Click Deploy.
  4. Confirm in the dialog.

Agent editor with the Deployed toggle active, showing agent name, goal slug, version number, and pipeline configurationAgent editor with the Deployed toggle active, showing agent name, goal slug, version number, and pipeline configuration

The agent status changes to Deployed. Note the agent_goal slug — you'll pass this as goal when creating cases.


Step 2 — Create a production API key

Never use a development key in production. Development keys have overly broad scopes and are harder to audit.

Service keys page — create a production key here with a name, then copy the one-time plaintext before closingService keys page — create a production key here with a name, then copy the one-time plaintext before closing

  1. Go to Admin → API Keys → New Key.
  2. Name it clearly: "Production backend — <service name>".
  3. Select only the write scope (your backend does not need admin).
  4. Copy the key and store it in your secrets manager (AWS Secrets Manager, GCP Secret Manager, HashiCorp Vault, etc.).
  5. Inject the secret into your service as an environment variable — never hardcode it.
import os
from ninthsense import Client

client = Client(
    api_key=os.environ["NINTHSENSE_API_KEY"],
    base_url="https://api.9thsense.ai",
)

Step 3 — Configure webhooks

Polling for case completion works in development but is fragile in production. Set up a webhook endpoint instead.

Register a webhook endpoint

In your backend, create an HTTPS endpoint that accepts POST requests:

# FastAPI example
from fastapi import FastAPI, Request, Header, HTTPException
from ninthsense.webhooks import construct_event, WebhookVerificationError

app = FastAPI()
WEBHOOK_SECRET = os.environ["NINTHSENSE_WEBHOOK_SECRET"]

@app.post("/webhooks/ninthsense")
async def handle_webhook(
    request: Request,
    x_digio_checksum: str = Header(None),
):
    raw_body = await request.body()
    try:
        event = construct_event(raw_body, {"x-digio-checksum": x_digio_checksum}, WEBHOOK_SECRET)
    except WebhookVerificationError:
        raise HTTPException(status_code=400, detail="Invalid signature")

    if event["type"] == "case.completed":
        case_id = event["data"]["case_id"]
        verdict = event["data"]["verdict"]
        # update your database, trigger downstream actions, etc.

    return {"ok": True}

Register the endpoint in the dashboard

  1. Go to Admin → Connectors (or per-agent webhook in the Agent Builder).
  2. Enter your endpoint URL and the shared secret.
  3. Click Test to send a test event and verify your handler works.
  4. Save.

The webhook secret is used to generate an HMAC-SHA256 signature in the X-Digio-Checksum header. Always verify this before processing.

Return 200 quickly (within 5 seconds). Move heavy processing to a background job. If your endpoint returns 5xx or times out, 9thSense retries with exponential backoff (1s, 2s, 4s, 8s, 16s). After 5 failures the event is marked failed and no more retries occur.


Step 4 — Open a case from your backend

import asyncio
import os
from ninthsense import Client

async def start_kyc_case(document_path: str, customer_id: str) -> str:
    async with Client(
        api_key=os.environ["NINTHSENSE_API_KEY"],
        base_url="https://api.9thsense.ai",
    ) as client:
        case = await client.cases.create(
            goal="kyc_individual",
            metadata={"subject_ref": customer_id},
            idempotency_key=f"kyc-{customer_id}",
        )

        with open(document_path, "rb") as f:
            await client.cases.upload(case.id, f.read(), "pan_card.jpg")

        # Don't poll in production — the final result (extracted fields,
        # check verdicts, rule outcomes) is delivered via webhook.
        return case.id   # store this for correlation with the webhook event

Always pass idempotency_key in production. If your service retries a failed request, 9thSense deduplicates based on this key and returns the original run result instead of starting a new one.


Step 5 — Handle errors

import logging
from ninthsense.exceptions import (
    AuthenticationError,
    RateLimitError,
    APIError,
)

logger = logging.getLogger(__name__)

try:
    case = await client.cases.create(goal="kyc_individual")
except AuthenticationError:
    # API key is invalid or revoked — do not retry, alert ops
    raise
except RateLimitError as e:
    # You've hit the rate limit — back off and retry
    await asyncio.sleep(e.retry_after or 60)
    # retry...
except APIError as e:
    # 5xx from the server — safe to retry with backoff
    logger.error("9thSense API error: %s", e)
    # retry with exponential backoff...

Step 6 — Monitor in production

Dashboard

  • Cases → filter by your deployed agent. Watch the processing queue depth — a spike means the pipeline is slow or stuck.
  • Analytics → check processing volume, avg. processing time, and case completion rate after launch.
  • Admin → Audit Logs → filter by your production API key prefix to see every call it made.

Alerts to set up

Set up alerts in your monitoring system (Datadog, Grafana, CloudWatch) on:

  • Webhook endpoint 5xx rate > 1%
  • Avg. case processing time > 30 seconds (indicates a slow step)
  • RateLimitError count > 0 (you may need a quota increase)

Rotating an API key

When a key is compromised or you are doing a scheduled rotation:

  1. Create the new key in Admin → API Keys.
  2. Deploy the new key to all services using it (update the secret in your secrets manager).
  3. Verify the services are using the new key (check audit logs — you should see traffic from the new prefix).
  4. Revoke the old key.

Do steps 1–3 before step 4. Revoking first causes downtime.


Rate limits

LimitDefault
Requests per minute200
Concurrent runs20
Max file size50 MB
Max pages per PDF10 sampled automatically

To request higher limits, contact your account manager.