Skip to main content

dealgo-csc

Runtime decision firewall for AI agents. The Python SDK for the DeAlgo decision API.

Wrap any model — trading strategy, LLM tool caller, agent — in client.decide(...), get back a binding permitted | blocked + reason, and respect the verdict. The system is deterministic, observable, and bounded. Every decision is hash-chained into a tamper-evident audit log you can verify byte-by-byte.

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

What CSC actually does (verified, not marketing)

The SDK talks to the DeAlgo portal at https://api.dealgo.io/v1/decide, which runs the proposed action through a 3-layer governance pipeline. Each layer was characterized empirically in the lab (see Behavioral characterization below).

flowchart TD
    A([Agent proposes action]) --> SDK[client.decide]
    SDK -->|HTTPS POST /v1/decide<br/>Bearer sk_live_ or sk_test_| API[DeAlgo portal]

    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

Current release: v2.1.0. Targets the public DeAlgo portal at https://api.dealgo.io/v1/decide. Compatible with the dealgo-csc runtime that backs that endpoint.

The DeAlgo.decide(...) shape and Decision fields are stable. The Gate enum may grow new variants — callers should handle Gate.UNKNOWN defensively (treat as block). The legacy CSC.check(...) trading-coded signature is preserved as a backwards-compat alias and auto-translates to the neutral schema.

See CHANGELOG.md for release notes.


License

Apache-2.0. See LICENSE (or the metadata on PyPI).

Metadata

Release files for dealgo-csc 2.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for dealgo-csc 2.3.0
File Size Uploaded Provenance
dealgo_csc-2.3.0.tar.gz 25.8 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for dealgo-csc 2.3.0
File Interpreter ABI Platform
dealgo_csc-2.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 43.0 kB

Release files / dealgo_csc-2.3.0.tar.gz

Download URL dealgo_csc-2.3.0.tar.gz
Size 25.8 kB
Tags Source
SHA-256 checksum
How to use checksums
fb26c97d05bbd9d335eafafc07af7feade69dabb2fdfccb52d77633cc2cb37f2
BLAKE2b-256 checksum
How to use checksums
42c892edac49edd91d8bbda9d77958b9131f58d243dd9c466236085feeca30c8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 5, 2026.

Transparency log

Release files / dealgo_csc-2.3.0-py3-none-any.whl

Download URL dealgo_csc-2.3.0-py3-none-any.whl
Size 17.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ff797a9bd805619259ab8ac4bc3dc0a7a345a324577e41ce8fad31bae1af50f8
BLAKE2b-256 checksum
How to use checksums
80ba96abf85b222fc7949b4ef2c647c7474e02df7b5718bc02d98295853dec1c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 5, 2026.

Transparency log

Security for dealgo-csc 2.3.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for dealgo_csc-2.3.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 5, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page