Skip to main content

Python SDK for the DeAlgo decision firewall — runtime governance for autonomous AI agents

Project description

dealgo-csc-sdk

Reduces drawdown by suppressing loss clusters in real time.

Instead of predicting better trades, CSC controls when NOT to trade during high-risk bursts. Plug any model — trading strategy, LLM tool caller, agent — into csc.check(...), get back a binding permitted | blocked + reason, and respect the verdict. The system is deterministic, observable, and bounded.

Measured result on a synthetic mean-reversion strategy across 5 seeds: ~8.5 percentage points drawdown reduction, robust 5/5. See dealgo-csc-lab/experiments/017_ab_synthetic for methodology.

CSC answers one question: Should this proposed action be permitted to execute right now?

It does not answer "is this profitable" or "is this optimal." It's the layer that stops a confused, hostile, or simply wrong model from firing at the worst time.

Why this exists

problem what CSC does
Strategy fires bad-trade clusters during turbulent regimes Token-bucket throttle structurally caps cluster volume → drawdown drops
LLM agent hallucinates a destructive tool call Reality gate blocks; verdict carries the reason
Compromised agent fires actions in a flood Bucket rate-limits at ~12 permits/min globally
Multi-agent system has conflicting goals Per-source bias + safety judgment route the conflict
You want to learn from bad outcomes safely v2 outcome channel: signed, integrity-gated, capped influence
Need post-hoc audit of every decision Full pipeline trace + audit log per stimulus

Verified properties (lab phases 001–017)

  • ~8.5 pp drawdown reduction robust across 5 seeds on cluster-prone mean-reversion strategy (Phase 017 multi-seed sweep)
  • Zero verdict flips across 220+ real and synthetic decisions
  • Deterministic safety geometry — same input, same verdict
  • Clamped adaptive bias — v2 cannot flip a v1 verdict (capped ±0.05)
  • Two-layer decay — old bias fades by both time AND traffic volume
  • Byte-identical v1 path when callers don't opt into v2

What CSC is, and is not

claim evidence
defensible "Reduces drawdown by suppressing loss clusters" 5/5 seeds, mean +8.5 pp drawdown improvement
"Improves expectancy / makes strategies profitable" tested, falsified — single-seed result was noise
"Predicts better trades" not a prediction system; pure control layer

Quick install

pip install -e .

Wrap an agent's tool call in csc.check(...) and respect the verdict. Every blocked action carries a structured reason and a stimulus ID for audit lookup. See "Quick start" below.


What CSC actually does (verified, not marketing)

The SDK talks to a CSC server. That server runs a 3-layer pipeline. We mapped each layer empirically (see Behavioral characterization below).

flowchart TD
    A([Agent proposes action]) --> SDK[csc.check]
    SDK -->|HTTP POST /csc/live-stimulus| API[CSC server]

    API --> V{Validation boundary}
    V -- bad type / out of range / missing fields --> R422([HTTP 422<br/>raises ValidationError])

    V -- valid --> SPS{SPS gate<br/>survival policy}
    SPS -- DELAY --> Bp([blocked_policy])

    SPS -- APPROVE --> RG{Reality gate<br/>vol &lt; 0.15<br/>conf &gt;= 0.90}
    RG -- fail --> Br([blocked_reality_mismatch])

    RG -- pass --> TB{Token bucket<br/>capacity 4<br/>refill ~5s}
    TB -- empty --> Bt([blocked_controlled])
    TB -- token available --> P([permitted])

    Bp --> D[Decision]
    Br --> D
    Bt --> D
    P --> D
    D --> SDK
    SDK --> Caller([Caller acts<br/>or logs block])

Install

pip install dealgo-csc

Requires Python ≥3.9. Single runtime dependency: requests.


Quick start (v2.1+) — recommended for new integrations

Get a sandbox key from your portal at https://api.dealgo.io/keys (test keys don't count toward your monthly quota), then:

from csc_sdk import DeAlgo

client = DeAlgo(api_key="dealgo_sk_test_…")

verdict = client.decide(
    action_type="send_email",
    risk_score=0.3,
    confidence=0.95,
    intent="reply to customer with quote",
    metadata={"agent_id": "support-bot-7"},
)

if verdict.permitted:
    send_the_email()
else:
    print(f"Blocked: {verdict.reason}")
    print(f"Trace: https://api.dealgo.io/decisions/{verdict.decision_log_id}")

The decision_log_id is your direct link to the full pipeline trace: every gate that ran, every threshold compared, every reality check, in order — with a cryptographic chain proof.

Idempotency

Pass the same idempotency_key on a retry to avoid double-metering:

verdict = client.decide(
    action_type="send_email",
    risk_score=0.3,
    confidence=0.95,
    idempotency_key="my-request-uuid",   # safe to retry
)
if verdict.idempotency_replayed:
    print("This was a replayed response — meter not bumped twice.")

Closing the loop with report_outcome()

After observing the real-world result of an action, sign and report it back to feed the v2 adaptive-bias layer:

client.report_outcome(
    stimulus_id=verdict.id,
    magnitude=0.7,           # outcome was beneficial
    confidence=0.95,
    signature="…ed25519 base64…",
    public_key="…base64…",
    source="support-bot-7",
    context_type="General Stimulus",
    outcome_observed_at="2026-04-30T12:00:00Z",
    is_final=True,
)

Backwards compatibility — v1.x / v2.0 callers

Existing trading code keeps working unchanged:

from csc_sdk import CSC

csc = CSC(base_url="http://localhost:8765")   # direct-runtime mode

decision = csc.check(
    feed="trading",
    symbol="BTC",
    volatility=0.05,
    confidence=0.95,
    v2_aware=True,
)

if decision.permitted:
    execute_trade()

CSC is now an alias for DeAlgo. The check() method internally translates the trading-coded fields into the neutral schema before the request goes out, so trading callers get identical behavior with no code changes.

v2_aware=True still folds per-source outcome history into the SPS score (capped ±0.05). decision.v2_bias is None when v2 didn't fire.


The Decision object

field type meaning
permitted bool True = action may run
gate Gate which CSC layer decided: permit, policy, reality, throttle, override, unknown
reason str human-readable, suitable for logs and audit notes
id str stimulus ID for cross-referencing CSC's audit log
raw dict full underlying response body (audit / debug)

Decision is a frozen dataclass — safe to log, hash, pass between threads.

Gate semantics

flowchart LR
    G[Gate] --> P[permit<br/>action allowed]
    G --> Po[policy<br/>SPS verdict was DELAY]
    G --> R[reality<br/>vol or conf out of safe band]
    G --> T[throttle<br/>token bucket empty]
    G --> O[override<br/>founder override engaged]
    G --> U[unknown<br/>future or unrecognized state]

    style P fill:#cfc,stroke:#0a0
    style Po fill:#fcc,stroke:#a00
    style R fill:#fcc,stroke:#a00
    style T fill:#ffc,stroke:#aa0
    style O fill:#fcc,stroke:#a00
    style U fill:#eee,stroke:#888

Why distinguish throttle from policy/reality? Throttle is transient — the bucket refills in seconds and the same action will be permitted shortly. Policy and reality blocks indicate the action itself is unsafe; retrying will not help.


Convenience APIs

check_or_raise — for tool wrappers

from csc_sdk import CSC, BlockedError, ThrottledError

csc = CSC()

@tool  # your agent framework's tool decorator
def execute_trade(symbol: str, side: str):
    csc.check_or_raise(
        feed="trading", symbol=symbol,
        volatility=current_vol(), confidence=signal_confidence(),
        source="agent-1",
    )
    # If we get here, CSC permitted the action.
    return broker.place_order(symbol, side)

ThrottledError is a subclass of BlockedError, so wrappers can choose to retry or fail loudly per gate.

check_with_retry — for transient throttle handling

decision = csc.check_with_retry(
    feed="trading", symbol="BTC",
    volatility=0.05, confidence=0.95,
    max_attempts=4, base_backoff=5.0,
)
# Retries only on Gate.THROTTLE. Policy/reality blocks return immediately.

Backoff is linear: base_backoff * attempt, calibrated to the bucket's ~5s saturation behavior.


Testing your agent without a CSC server

from csc_sdk import Gate
from csc_sdk.testing import FakeCSC, permitted, blocked

# Always permits
csc = FakeCSC()

# Replays canned decisions in order
csc = FakeCSC([
    permitted("first-call"),
    blocked(Gate.REALITY, "volatility above 0.15"),
    blocked(Gate.THROTTLE, "no tokens"),
])

result = my_agent.run(csc=csc)
# Inspect what the agent asked CSC about:
assert csc.calls[0]["feed"] == "trading"

FakeCSC implements the same surface as CSC (check, check_or_raise, check_with_retry) but never opens a socket.


Operational characteristics (measured, not promised)

These numbers come from the lab harness adversarial sweeps; see Behavioral characterization below for methodology.

dimension value notes
Permit window (vol) ≤ 0.14 reality-gate hard threshold
Permit window (conf) ≥ 0.90 reality-gate hard threshold
Bucket capacity 4 permits exact, deterministic
Bucket refill ~5s wall-clock saturates from 0→4 in ~5s of quiet
Steady-state ceiling ~12 permits/min 4 permits per ~20s under continuous load
Per-decision latency 2–3 s single CSC server, serial processing
Concurrent requests serialized linear latency under contention
False permits under chaos 0 / 100 random uniform sampling
False permits under spike 0 / 18 adversarial vol/conf spikes
False permits under multi-agent 0 / 8 concurrent dangerous agents

Behavioral characterization

The companion lab harness (dealgo-csc-lab) ran 8 phases of black-box probing against CSC. Every characteristic above is grounded in one of them:

flowchart LR
    P1[Phase 1<br/>chaos baseline<br/>100/100 blocked] --> P2[Phase 2<br/>boundary sweep<br/>permit island found]
    P2 --> P3[Phase 3<br/>fine sweep<br/>blocked_controlled is stateful]
    P3 --> P4[Phase 4<br/>controlled gate probe<br/>permit runs always 4]
    P4 --> P5[Phase 5<br/>bucket characterization<br/>refill is wall-clock]
    P5 --> P6[Phase 6<br/>refill curve<br/>~5s saturation]
    P6 --> P7[Phase 7<br/>adversarial spike<br/>judgment correct]
    P7 --> P8[Phase 8<br/>multi-agent<br/>safety holds under concurrency]

Architecture (where this fits)

flowchart LR
    subgraph YOUR[Your application]
        AGENT[Agent / bot / workflow]
    end

    subgraph SDK[dealgo-csc-sdk this repo]
        CLIENT[CSC client]
        DECISION[Decision model]
        FAKE[FakeCSC for tests]
    end

    subgraph CORE[CSC server]
        VAL[Pydantic validation]
        SPS[SPS gate]
        REALITY[Reality validator]
        BUCKET[Execution gate<br/>token bucket]
        AUDIT[Audit log]
    end

    AGENT -->|csc.check| CLIENT
    CLIENT -->|HTTP POST| VAL
    VAL --> SPS
    SPS --> REALITY
    REALITY --> BUCKET
    BUCKET -->|writes| AUDIT
    BUCKET -->|response| CLIENT
    CLIENT -->|Decision| AGENT

This SDK is the only surface external code should touch. The CSC server is internal infrastructure. Treat the HTTP shape of /csc/live-stimulus as private — its full response contract may change without notice. The SDK pins the public contract.


Errors

flowchart TD
    E[CSCError] --> V[ValidationError<br/>HTTP 422 from server]
    E --> T[TransportError<br/>network or non-decision HTTP]
    E --> B[BlockedError<br/>raised by check_or_raise]
    B --> Th[ThrottledError<br/>specifically Gate.THROTTLE]

ValidationError.detail carries the Pydantic error list from the server, so callers can surface field-level diagnostics.


Running the SDK tests

pip install -e ".[test]"
pytest tests/ -q

8 unit tests cover Decision parsing across all gate types and FakeCSC's canned-response semantics.


Repo layout

dealgo-csc-sdk/
├── csc_sdk/
│   ├── __init__.py     public surface
│   ├── client.py       CSC HTTP client (check / check_or_raise / check_with_retry)
│   ├── models.py       Decision (frozen dataclass), Gate enum
│   ├── errors.py       exception hierarchy
│   └── testing.py      FakeCSC for offline tests
├── tests/              pytest suite
├── pyproject.toml
└── README.md           you are here

Three-repo system context

repo role contents
dealgo-csc Core — runs the actual server FastAPI app, SPS, reality validator, token bucket, audit
dealgo-csc-lab Lab — black-box harness Chaos / boundary / adversarial / multi-agent experiment runners
dealgo-csc-sdk (this) SDK — public client Typed CSC client, Decision, FakeCSC

The lab never imports core; the SDK never imports core. All three communicate only through the documented HTTP API.


Versioning

This SDK at v1.0.0 targets the v1 CSC contract. The CSC.check shape and Decision fields are stable. The Gate enum may grow new variants — callers should handle Gate.UNKNOWN defensively (treat as block).

A v2 server contract is frozen in dealgo-csc/docs/v2-spec.md. The v2 layer adds an additional bias axis to the SPS score (capped ±0.05), opt-in per-stimulus via payload.v2_aware = true. This SDK does not yet expose that flag. SDK 2.0.0 will add a v2_aware=True argument to csc.check(...) and surface the bias delta as Decision.v2_bias: Optional[float]. Until then, this client always gets pure v1 behavior — byte-identical regardless of whether the server is running v1 or the v2-prototype branch.


License

Proprietary.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dealgo_csc-2.1.0.tar.gz (23.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dealgo_csc-2.1.0-py3-none-any.whl (17.0 kB view details)

Uploaded Python 3

File details

Details for the file dealgo_csc-2.1.0.tar.gz.

File metadata

  • Download URL: dealgo_csc-2.1.0.tar.gz
  • Upload date:
  • Size: 23.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for dealgo_csc-2.1.0.tar.gz
Algorithm Hash digest
SHA256 a50bf94ea768aff70b28c0ac36b5cece1e625b3266293bbf1c052a628eca90e3
MD5 5d66cd1a8a2296bcf1ddce52920e8039
BLAKE2b-256 7299f30df45a825a6a5e721848235896042db7ef0acbfcf73593550f8fb6b10e

See more details on using hashes here.

Provenance

The following attestation bundles were made for dealgo_csc-2.1.0.tar.gz:

Publisher: publish.yml on dealgo-systems/dealgo-csc-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dealgo_csc-2.1.0-py3-none-any.whl.

File metadata

  • Download URL: dealgo_csc-2.1.0-py3-none-any.whl
  • Upload date:
  • Size: 17.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for dealgo_csc-2.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9a0f690cde637929a2c96365a3aa652cecbf8bd82c2261993752d8909cb704a3
MD5 cc726d841c6ef0c30e133cdbb8d6dffb
BLAKE2b-256 7ba668070415d33230e062da5863536ad77cd9b97263d6c0787bcef96ac62c8d

See more details on using hashes here.

Provenance

The following attestation bundles were made for dealgo_csc-2.1.0-py3-none-any.whl:

Publisher: publish.yml on dealgo-systems/dealgo-csc-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page