SDKs

Python SDK

Full reference for triage-integrity-sdk: sync and async checks, errors, retries.

The Python SDK (triage-integrity-sdk, imported as triage_sdk) is a thin HTTP client for the Integrity classifiers. Requires Python 3.10+.

Install#

Shell
pip install triage-integrity-sdk

init()#

Call once before any check. Configuration is process-global.

Python
triage_sdk.init(
    api_key="tsk_...",
    base_url=None,        # defaults to https://integrity.triage-sec.com
    timeout=30.0,         # per-request seconds
    max_retries=2,        # transient-failure retries
)
ArgumentDefaultDescription
api_keyrequiredProject API key (tsk_...). Enforced server-side.
base_urlhttps://integrity.triage-sec.comService base URL. Per-classifier routes derive from it.
timeout30.0Per-request timeout in seconds.
max_retries2Retries on connection errors, timeouts, and HTTP 429, 500, 502, 503, and 504.

Per-classifier URL overrides (input_url, tooling_url, cot_url, output_url) are covered under Configuration.

Checks#

Four live classifiers, each returning a frozen dataclass. INT-CoT is exposed as an experimental advisory signal:

  • triage_sdk.input.check(text, model_provider=None, model_name=None, session_id=None) InputCheckResult
  • triage_sdk.cot.check(reasoning_text, final_output="", source_model=None, ...) CotCheckResult (experimental; includes score, threshold, rising, verdict, is_divergent, and raw)
  • triage_sdk.tool_call.check(user_request, tool_name, tool_description="", interaction_history="", env_info="", ..., tool_arguments=None) ToolCallCheckResult (pass tool_arguments by keyword; it is the last parameter)
  • triage_sdk.output.check(assistant_text, user_text="", messages=None, ...) OutputCheckResult

The natural inference order is input, CoT, tooling, output. Standalone INT-CoT calls return an advisory result and do not change the sensitivity of another SDK check. The gateway can separately combine material, rising CoT risk with a flagged tool or output result. Every result also carries a raw dict of the untouched server payload for forward compatibility.

Use tool_arguments when you have structured function-call arguments. It takes precedence over tool_description and exposes argument-sensitive risk, like URLs, domains, payloads, and target repositories:

Python
tool_result = triage_sdk.tool_call.check(
    user_request=user_text,
    tool_name="github_create_issue",
    tool_arguments={
        "repo": "triage-sec/triage",
        "title": "Investigate trace",
        "body": "Observed risk in session sess_abc",
    },
    session_id=f"repo:triage-sec/triage:pr:{pr_id}",
)

Call-site scoping#

The SDK is call-site scoped. It only sends traffic where you call it, so you can instrument one route, agent, tool runner, workflow, or package without ingesting traces from the whole repository. For per-subsystem reporting, encode scope in session_id.

Python
session_id = f"repo:payments-service:agent:security-review:run:{run_id}"

input_result = triage_sdk.input.check(user_text, session_id=session_id)
if not input_result.is_safe:
    block()

tool_result = triage_sdk.tool_call.check(
    user_request=user_text,
    tool_name="github_create_issue",
    tool_arguments={"repo": "org/payments-service", "title": issue_title},
    session_id=session_id,
)
if tool_result.composite_score >= 0.8:
    block()
elif tool_result.is_flagged:
    print("tool call flagged for review")

For a larger app, put a thin wrapper around the specific OpenAI or agent client you care about, for example security_review_agent, and leave other model calls untouched. Do the same with the gateway: route selected client instances through the proxy rather than the whole app unless you want global coverage.

Async#

Each check has an async twin, acheck, that shares one pooled client. Use it to run the three boundaries concurrently:

Python
import asyncio

async def screen(user_msg, reasoning, answer):
    input_result, _cot, output_result = await asyncio.gather(
        triage_sdk.input.acheck(user_msg),
        triage_sdk.cot.acheck(reasoning_text=reasoning, final_output=answer),
        triage_sdk.output.acheck(assistant_text=answer, user_text=user_msg),
    )
    if output_result.severity_score is not None and output_result.severity_score >= 0.75:
        print("response flagged for review")
    output_blocks = output_result.severity_score is None or output_result.severity_score >= 1.0
    return input_result.is_safe and not output_blocks

Errors#

Service, transport, response, and configuration errors raised by the SDK derive from triage_sdk.TriageError. Invalid arguments passed to a check raise the built-in ValueError before a request is sent.

ExceptionRaised when
TriageConfigErrorinit() not called, or invalid configuration.
TriageAuthenticationErrorAPI key missing/invalid (HTTP 401/403).
TriageAPIErrorOther non-2xx responses. Has .status_code and .detail.
TriageTimeoutErrorRequest timed out after retries.
TriageConnectionErrorTransport failure after retries (DNS/TLS/refused).
TriageResponseErrorA required response field is missing or has the wrong type.
Python
try:
    verdict = triage_sdk.input.check(user_text)
    allowed = verdict.is_safe
except triage_sdk.TriageError:
    allowed = False  # fail closed: treat unavailability as unsafe

Retries & pooling#

Transient failures (connection errors, timeouts, and HTTP 429, 500, 502, 503, and 504) are retried up to max_retries times with jittered exponential backoff, honoring Retry-After on 429. Other 4xx responses are never retried. Requests reuse a shared keep-alive connection pool.

Lifecycle#

The sync client can live for the process lifetime. The shared async client assumes one long-lived event loop and must not be reused across event loops. On graceful shutdown, release the pools with triage_sdk.close() (sync) and await triage_sdk.aclose() (async).