SpendGuard SDK — runtime safety layer client for AI agent frameworks (Pydantic-AI, LangChain, LangGraph, OpenAI Agents SDK).
Project description
spendguard-sdk
Runtime safety layer client for AI agent frameworks. Talks to the SpendGuard sidecar over Unix-domain-socket gRPC; gates each LLM / tool-call boundary through a Contract DSL evaluator and an atomic budget ledger with immutable audit chain.
Install
# Core only (raw client, no framework integration)
pip install spendguard-sdk
# With the integration you need
pip install 'spendguard-sdk[pydantic-ai]'
pip install 'spendguard-sdk[langchain]'
pip install 'spendguard-sdk[langgraph]'
pip install 'spendguard-sdk[openai-agents]'
Quickstart (Pydantic-AI)
import asyncio
from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIModel
from spendguard import SpendGuardClient, new_uuid7
from spendguard.integrations.pydantic_ai import (
RunContext,
SpendGuardModel,
run_context,
)
from spendguard._proto.spendguard.common.v1 import common_pb2
async def main():
client = SpendGuardClient(
socket_path="/var/run/spendguard/adapter.sock",
tenant_id="00000000-0000-4000-8000-000000000001",
)
await client.connect()
await client.handshake()
guarded = SpendGuardModel(
inner=OpenAIModel("gpt-4o-mini"),
client=client,
budget_id="44444444-4444-4444-8444-444444444444",
window_instance_id="55555555-5555-4555-8555-555555555555",
unit=common_pb2.UnitRef(
unit_id="66666666-6666-4666-8666-666666666666",
token_kind="output_token",
model_family="gpt-4",
),
pricing=common_pb2.PricingFreeze(
pricing_version="demo-pricing-v1",
price_snapshot_hash=b"<32 bytes>",
fx_rate_version="demo-fx-v1",
unit_conversion_version="demo-units-v1",
),
claim_estimator=lambda messages, settings: [
common_pb2.BudgetClaim(
budget_id="44444444-4444-4444-8444-444444444444",
unit=common_pb2.UnitRef(
unit_id="66666666-6666-4666-8666-666666666666",
token_kind="output_token",
model_family="gpt-4",
),
amount_atomic="500",
direction=common_pb2.BudgetClaim.DEBIT,
window_instance_id="55555555-5555-4555-8555-555555555555",
)
],
)
agent = Agent(model=guarded)
async with run_context(RunContext(run_id=str(new_uuid7()))):
result = await agent.run("Say hello in three words.")
print(result.output)
asyncio.run(main())
If a contract rule denies the call, agent.run(...) raises
spendguard.DecisionStopped carrying reason_codes and
matched_rule_ids.
API surface (core)
| Symbol | Purpose |
|---|---|
SpendGuardClient |
UDS gRPC client to the sidecar |
DecisionStopped, DecisionSkipped, ApprovalRequired |
per-decision exceptions |
derive_idempotency_key(...) |
deterministic key from (tenant, run, step, llm_call, trigger) |
new_uuid7() |
UUID v7 helper |
Wire-protocol compatibility
This SDK pins to a specific protobuf wire version. Check the
sidecar's published version against spendguard.__version__; minor
versions are wire-compatible, major bumps are breaking. (Not yet
enforced at handshake; planned for v0.2.)
License
Apache-2.0.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file spendguard_sdk-0.1.0a1.tar.gz.
File metadata
- Download URL: spendguard_sdk-0.1.0a1.tar.gz
- Upload date:
- Size: 55.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6c70c2f2f26fa8accd914527f1c8d47e2f86511d2266e52b09b113e21dcf475a
|
|
| MD5 |
2ee05529870859c60b8d695c4d3ee151
|
|
| BLAKE2b-256 |
4e9aaec5e9168243cef7fabf90b884ccd172c5f47a1a6ce17148dfb1b5c05e86
|
File details
Details for the file spendguard_sdk-0.1.0a1-py3-none-any.whl.
File metadata
- Download URL: spendguard_sdk-0.1.0a1-py3-none-any.whl
- Upload date:
- Size: 67.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c7c03e46f27530a20c784e521b726d2124d056f40e204d139178228105a92234
|
|
| MD5 |
670d5ae39955881482b32af47c3b13fd
|
|
| BLAKE2b-256 |
12ef0fc2254ae5f9a162d85daebb0f59c13eb8c06e05d9e823604b21030dd9e5
|