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#
pip install triage-integrity-sdkinit()#
Call once before any check. Configuration is process-global.
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
)| Argument | Default | Description |
|---|---|---|
api_key | required | Project API key (tsk_...). Enforced server-side. |
base_url | https://integrity.triage-sec.com | Service base URL. Per-classifier routes derive from it. |
timeout | 30.0 | Per-request timeout in seconds. |
max_retries | 2 | Retries 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)→ InputCheckResulttriage_sdk.cot.check(reasoning_text, final_output="", source_model=None, ...)→ CotCheckResult (experimental; includesscore,threshold,rising,verdict,is_divergent, andraw)triage_sdk.tool_call.check(user_request, tool_name, tool_description="", interaction_history="", env_info="", ..., tool_arguments=None)→ ToolCallCheckResult (passtool_argumentsby 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:
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.
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:
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_blocksErrors#
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.
| Exception | Raised when |
|---|---|
TriageConfigError | init() not called, or invalid configuration. |
TriageAuthenticationError | API key missing/invalid (HTTP 401/403). |
TriageAPIError | Other non-2xx responses. Has .status_code and .detail. |
TriageTimeoutError | Request timed out after retries. |
TriageConnectionError | Transport failure after retries (DNS/TLS/refused). |
TriageResponseError | A required response field is missing or has the wrong type. |
try:
verdict = triage_sdk.input.check(user_text)
allowed = verdict.is_safe
except triage_sdk.TriageError:
allowed = False # fail closed: treat unavailability as unsafeRetries & 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).