disclarion
AI disclosure logging SDK. Wraps your LLM provider responses and reports standardized disclosure/labeling metadata to Disclarion.
Install
pip install disclarion
Usage
from disclarion import Disclarion
import openai
client = openai.OpenAI()
dc = Disclarion(api_key="dcl_live_...")
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "hello"}],
)
dc.track(response, session_id="session-123")
track() never modifies response by default — it attaches a
disclarion_meta dict to it instead, and your own UI decides what to show:
tracked = dc.track(response, session_id="session-123")
tracked.disclarion_meta
# {"ai_generated": True, "is_first_message": True, "disclosed": False, "logged_at": "..."}
is_first_message is what a host-app disclosure widget should key off of —
show a one-time blocking notice on True, keep a small persistent badge up
for the rest of the session on False. See widget/ for a ready React and
vanilla-JS implementation of exactly that pattern.
This is the disclosure_mode="modal_once" default, set on the client, not
per call:
modal_once(default) — never touches response content; onlydisclarion_metachanges, as above.inline_every_message— the SDK's original behavior, kept for backward compatibility. Despite the name, it still only rewrites the response's own content on a session's first message (never later ones) to append/prependdisclosure_text;disclarion_meta["disclosed"]reflects whether that happened.off— pure logging, no disclosure signal at all:disclarion_metaomitsis_first_message/disclosedentirely. Use this if your product already has its own unrelated AI-disclosure UI.
dc = Disclarion(api_key="dcl_live_...", disclosure_mode="inline_every_message")
Regardless of disclosure_mode, every track() call is still logged to
Disclarion's audit trail (interaction_logs) exactly the same way — the UI
mode only changes what happens to response and disclarion_meta, never
what gets recorded for compliance.
track() makes one fast synchronous attempt (that's what makes
is_first_message available immediately) and never retries inline — a
slow or erroring Disclarion backend can never turn into multi-second
latency on your own request path. Anything worth retrying (a network
error, a 5xx, a transient 429) is handed to a background thread with
a bounded queue (up to 1000 pending logs, oldest dropped first if your
process is generating logs faster than Disclarion can accept them) that
retries with capped, jittered exponential backoff, honoring a 429's
Retry-After header when present. The queue is flushed on normal
process exit, SIGINT, and SIGTERM (bounded to a couple of seconds, so
shutdown is never blocked indefinitely by a backend that's still down).
A 429 that means "you've exceeded your monthly plan quota" is handled
differently from a transient rate limit: retrying it is pointless until
next period, so the SDK opens a circuit breaker instead — every track()
call skips the network entirely (sub-millisecond) until an hourly (then
exponentially longer, capped at 24h) cooldown elapses and one probe
request checks whether it's resolved. One logging.warning marks each
state change (opened/resolved), not one per call, so a month-long outage
doesn't spam your logs. Call dc.get_stats() any time for the queue size,
circuit state, and delivery counters.
An invalid or revoked API key is different from all of the above: the
backend is reachable and is explicitly rejecting it, which is a setup
mistake you need to see, so that raises disclarion.AuthenticationError
immediately — no retry, no circuit-breaking, no silent fallback.
Unsupported response types raise a ValueError immediately for the same
reason: both are programming/config errors to fix, not a runtime
condition to swallow.
OpenAI (ChatCompletion), Anthropic (Message), and Gemini
(GenerateContentResponse) responses are all supported — see
disclarion/adapters/.
Testing without a live backend
To exercise _send_log() end to end without hitting the real
api.disclarion.com:
python scripts/mock_server.py # terminal 1 - fake /v1/logs endpoint
python scripts/manual_test.py # terminal 2 - sends a fake ChatCompletion
The mock server prints every received payload and the Authorization
header so you can confirm the normalized log shape is correct. See
scripts/README.md for details, or tests/ for the automated unit tests
(pytest) which mock the HTTP layer instead of needing a running server.
Metadata
Release files for disclarion 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| disclarion-0.2.0.tar.gz | 25.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| disclarion-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 43.3 kB
Release files / disclarion-0.2.0.tar.gz
| Download URL | disclarion-0.2.0.tar.gz |
|---|---|
| Size | 25.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b99ec83c8c75f1de48c7b07d6b858914e26c19a08ece8748283e084600d3b991
|
|
BLAKE2b-256 checksum How to use checksums |
606ab674ba730d44203a3be23e919a8703e478224477d1243d031355c259fb5b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.6
|
Release files / disclarion-0.2.0-py3-none-any.whl
| Download URL | disclarion-0.2.0-py3-none-any.whl |
|---|---|
| Size | 17.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c5fd138a1ed5b0344cc7b7c4c39779b86fb5edb413733fc65b305a66a4df1b93
|
|
BLAKE2b-256 checksum How to use checksums |
83920ac27b3a4238418cad08ffe0af955ff89c40b1e3fbaf448cb01cf2d1a88f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.6
|