Skip to main content

citrate-sdk-python

Part of the Citrate Network — own the means of computation. · Docs · Run a node · Contribute → free membership

The Python SDK and citrate CLI for the Citrate Network (chain 40204) — connect to the chain, deploy/run models, encrypt inference inputs, and call the inference gateway.

What it is

citrate-labs-sdk is the Python client for the Citrate distributed-AI network: a JSON-RPC CitrateClient, managers for compute/learning/staking/treasury/farming, an AES-GCM/HKDF crypto envelope for encrypted inference, an OpenAI-compatible GatewayClient, and a citrate command-line tool. Chain id 40204 is bound from a vendored federation-contract artifact and enforced at signing time (a hostile RPC cannot make you sign for another chain). It mirrors the canonical TypeScript SDK (@citratelabs/sdk) and may lag it.

Tokenomics are not yet determined; see docs.citrate.ai.

This release carries the r1006 address book (citrate-chain contracts/addresses/r1006/40204.json, genesis block 0xa3651a27…6cdd4). Two networks can share chain id 40204 (r1005 and r1006 do), so before the client or a manager sends a transaction, and before verify_wallet_address_on_chain trusts the factory, the SDK reads block 0 and raises WrongNetworkError (error_code="WRONG_NETWORK") unless its hash is that genesis. client.verify_network() runs the check up front. LiquidStakingPool is not in r1006 block 0, so StakingManager has no default address.

See the concepts in the docs: https://docs.citrate.ai. Depends on a running chain node (citrate-chain) and, for inference, the gateway (citrate-inference-gateway).

Prerequisites

python3 --version   # >= 3.10 (3.10/3.11/3.12 supported)
python3 -m pip --version
# Optional: uv (a uv.lock is committed for reproducible installs)
#   pipx install uv   # or: curl -LsSf https://astral.sh/uv/install.sh | sh
# Optional, only for "Connect it locally": a local Citrate devnet node on :8545

Build from source

git clone https://github.com/CitrateNetwork/citrate-sdk-python.git
cd citrate-sdk-python

# pip (editable install with dev extras)
python3 -m venv .venv && source .venv/bin/activate
pip install -e '.[dev]'

# --- or with uv (uses the committed uv.lock) ---
# uv sync

pytest                 # run the test suite
citrate contract       # smoke-test the CLI: prints the federation contract table

pyproject.toml is the single source of truth for dependencies (requests, cryptography, eth-account, web3, numpy). The install exposes the citrate console script.

Run locally

This is a library plus a CLI. Install it into your environment, then either import it or use the CLI:

pip install citrate-labs-sdk        # from PyPI (published as citrate-labs-sdk)
citrate --help                      # subcommands: contract, wallet, entitlement, gateway

30-second Quickstart (against the public testnet, chain 40204):

import os
from citrate_sdk import CitrateClient

client = CitrateClient(
    rpc_url="https://rpc.citrate.ai",             # testnet default (chain 40204)
    private_key=os.getenv("CITRATE_PRIVATE_KEY"), # optional; required to sign
)
print("chain id:", client.get_chain_id())          # 40204

Call the inference gateway (OpenAI-compatible; needs a cgk_ key):

from citrate_sdk.gateway import GatewayClient

gw = GatewayClient(api_key=os.environ["CITRATE_GATEWAY_API_KEY"])
print(gw.chat_completions(
    model="gemma-4-E4B-it-Q4_K_M",
    messages=[{"role": "user", "content": "Say hi from Citrate"}],
))

Runnable examples live in examples/ (basic_usage.py, encrypted_inference.py, marketplace_demo.py). Verify it's up: get_chain_id() returning 40204 confirms the RPC.

deploy_model never places key shares in deployment metadata; its key-share check on caller-supplied metadata is a safety net against accidental inclusion, not a guarantee against deliberately re-encoded data.

Security: the client warns/fails on a remote plaintext http:// RPC (keys and signed transactions would go out in cleartext). Loopback http:// is always allowed; pass allow_insecure_http=True for a trusted TLS-less internal host.

Connect it locally ← the differentiator

Point the SDK at a local Citrate stack on one machine instead of the public testnet.

  1. Local chain — run a Citrate devnet node (chain 40204) from citrate-chain and deploy its contract book. It exposes JSON-RPC on http://localhost:8545.
  2. Point the SDK at it (loopback needs no opt-in):
    from citrate_sdk import CitrateClient
    client = CitrateClient(
        rpc_url="http://localhost:8545",
        private_key="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80",  # anvil acct #0
        expected_genesis_hash=None,  # a local devnet is not the r1006 genesis
    )
    assert client.get_chain_id() == 40204
    
    The client refuses to sign if the RPC's eth_chainId does not match the expected 40204; pass chain_id= to override for a custom local chain. A local devnet has its own genesis, so also pass expected_genesis_hash=None (or your devnet's block-0 hash) when it uses chain id 40204.
  3. Local inference gateway (optional) — run citrate-inference-gateway and point the gateway client at it:
    gw = GatewayClient(api_key="cgk_...", base_url="http://localhost:8080")
    
  4. End-to-end check — run the basic example against your local node:
    CITRATE_RPC_URL=http://localhost:8545 python examples/basic_usage.py
    

For the full multi-repo bring-up (chain → identity → bundler → gateway → SDKs), see the LOCAL_STACK guide at https://docs.citrate.ai.

Verify contracts on CitrateScan

citrate_sdk.verify submits Solidity source to CitrateScan, the explorer for chain 40204, through its Etherscan-compatible API (https://explorer.citrate.ai/api). It POSTs verifysourcecode, polls checkverifystatus, and returns when the explorer has recompiled the source and matched it to the code on chain. Input is a forge or hardhat build-info, a hardhat contract artifact, or a solc standard JSON input. Only the sources the contract's metadata lists are sent, as forge and hardhat-verify do.

import os

from citrate_sdk import CitrateClient, deploy_and_verify, load_build_info, verify_contract

# forge: `forge build --build-info` writes out/build-info/<id>.json with the compiler input.
build_info, _ = load_build_info("out/build-info/<id>.json")
result = verify_contract(
    chain_id=40204,  # optional: sent as Etherscan v2 `chainid`; omit it for a local devnet explorer
    address="0xYourContractAddress",
    build_info=build_info,
    contract="src/MyContract.sol:MyContract",  # or "MyContract" when the name is unique
    constructor_args="0x...",  # optional: the explorer reads them from the creation transaction
)
print(result.status)  # "verified" or "already_verified"

# hardhat: pass the contract artifact; load_build_info follows its .dbg.json.
bi, contract = load_build_info("artifacts/contracts/MyContract.sol/MyContract.json")
verify_contract(chain_id=40204, address="0xYourContractAddress", build_info=bi, contract=contract)

# Deploy from the build-info with the client's key (same genesis/chain-id checks as every
# transaction), then verify with the creation transaction hash.
client = CitrateClient(rpc_url="https://rpc.citrate.ai", private_key=os.environ["CITRATE_PRIVATE_KEY"])
deployed = deploy_and_verify(
    client=client, chain_id=40204, build_info=build_info,
    contract="src/MyContract.sol:MyContract", args=[7, "hello"],
)
print(deployed.address, deployed.tx_hash, deployed.verification.status)

Keywords:

  • chain_id: optional. When given, it is sent as Etherscan v2 chainid on the submission and on every status call. When omitted, no chainid is sent, so an explorer for a local devnet with another chain id works. This matches citrate contract verify --chain-id.
  • explorer_url (default https://explorer.citrate.ai/api), api_key (sent as apikey; not required, and never included in error messages), compiler_version (otherwise read from the contract metadata), creation_tx_hash.
  • wait=False: return the guid without polling.
  • poll_interval (3 s) and timeout (300 s) for the status polling. A transient error while polling (connection reset, request timeout, HTTP 5xx or 429) does not end the wait: the poll is retried with a backoff that doubles from poll_interval up to transient_backoff_max (30 s), within timeout. A 4xx other than 429, or a Fail verdict, ends it. poll_interval is at least MIN_POLL_INTERVAL (5 ms), so 0 does not retry in a tight loop.
  • rate_limit_retries (3) and rate_limit_backoff (5 s) for Max rate limit reached. The explorer takes one submission per 5 s per IP, so while it has not indexed a just-deployed contract, deploy_and_verify resubmits at most every max(poll_interval, rate_limit_backoff) seconds, for up to index_timeout (120 s).

check_verify_status(guid) and wait_for_verification(guid) poll a job you submitted earlier; pass the same chain_id (or none) as the submission. CitrateClient.deploy_contract waits up to receipt_timeout (120 s) for the receipt and raises CitrateError with code DEPLOY_FAILED when the receipt has status 0.

Errors subclass VerificationError (a CitrateError):

  • BuildInfoError: bad input, nothing sent. A plain forge build without --build-info gets this error, with the fix in the message.
  • VerificationFailedError: Fail - Unable to verify.
  • VerificationRejectedError: the explorer's refusal string.
  • VerificationRateLimitedError: still rate limited after retries.
  • VerificationTimeoutError: no verdict yet. The job may still finish.
  • ExplorerResponseError: the explorer could not be reached or gave an unexpected answer. transient is true for a transport failure, a timeout, HTTP 5xx and 429.

The explorer accepts at most 64 files and 2 MiB, inline content only.

forge and hardhat can verify against the same API directly. Two details matter on chain 40204:

  • forge: use --verifier custom --verifier-url https://explorer.citrate.ai/api --verifier-api-key citrate. With forge 1.5.1, --verifier etherscan stops before sending anything ("No known Etherscan API URL for chain 40204"). --verifier-api-key must be present, and any value works.
  • hardhat-verify: give etherscan.apiKey as a per-network object ({ citrate: "citrate" }) with a customChains entry for chainId 40204 (apiURL: "https://explorer.citrate.ai/api"). With hardhat-verify 2.1.3 a single string apiKey switches it to Etherscan's v2 mode, which ignores customChains and sends the request to api.etherscan.io.

Configuration

Env var Default Purpose
CITRATE_RPC_URL http://localhost:8545 chain JSON-RPC endpoint
CITRATE_PRIVATE_KEY — signer key (examples generate an ephemeral one if unset)
CITRATE_GATEWAY_API_KEY — cgk_ bearer key for the inference gateway

CitrateClient(rpc_url, private_key=None, timeout=..., allow_insecure_http=False, chain_id=None, expected_genesis_hash=<vendored>). The expected chain id (40204), genesis hash (r1006) and gateway base URL come from the vendored federation artifact; citrate contract prints the full table. The managers take the same chain_id= / expected_genesis_hash= keywords.

License

Licensed under the Apache License, Version 2.0 (see LICENSE). This is the open-source infrastructure tier of Citrate's open-core model. The commercial application layer is source-available under BUSL-1.1. Licensor: Citrate Inc.

Metadata

Release files for citrate-labs-sdk 0.8.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 citrate-labs-sdk 0.8.0
File Size Uploaded Provenance Actions
citrate_labs_sdk-0.8.0.tar.gz 132.7 kB With provenance Details for citrate_labs_sdk-0.8.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for citrate-labs-sdk 0.8.0
File Interpreter ABI Platform Actions
citrate_labs_sdk-0.8.0-py3-none-any.whl Python 3 none any Details for citrate_labs_sdk-0.8.0-py3-none-any.whl

Total release size: 266.9 kB

Release files / citrate_labs_sdk-0.8.0.tar.gz

Download URL citrate_labs_sdk-0.8.0.tar.gz
Size 132.7 kB
Tags Source
SHA-256 checksum
How to use checksums
e6191acb43c207d12c25f8e3d46e107ff4729c1e3c142e5293c1472622bba9fb
BLAKE2b-256 checksum
How to use checksums
f56241ff6f6723e552cea58814b2a4aaac4b612c6239ff6929b166457ee495dd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Nov 9, 2026.

Transparency log

Release files / citrate_labs_sdk-0.8.0-py3-none-any.whl

Download URL citrate_labs_sdk-0.8.0-py3-none-any.whl
Size 134.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
eeb09b0b86630f7c63dc6ec83b615e3177fd3f35cc10227e1791abe3760fd61e
BLAKE2b-256 checksum
How to use checksums
a35b15acf11a5b3427148402f90a810653d387cc5216a054d20fa1e57da9956a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Nov 9, 2026.

Transparency log

Security for citrate-labs-sdk 0.8.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

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for citrate_labs_sdk-0.8.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 Nov 9, 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.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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