Overview
The sardis-openai package provides OpenAI-compatible function definitions with strict mode enabled, preventing hallucination and ensuring reliable payment execution.
When to Use OpenAI
Function Calling Agents : Use GPT-4o’s native function calling
Assistants API : Build persistent agents with payment capabilities
Structured Outputs : Strict mode prevents parameter hallucination
Production Reliability : Type-safe payment execution
Installation
pip install sardis-openai openai
Requires openai>=1.0.0 and Python 3.9+
Quick Start
import os
from openai import OpenAI
from sardis import SardisClient
from sardis_openai import get_sardis_tools, handle_sardis_tool_call
# Initialize
openai_client = OpenAI()
sardis = SardisClient( api_key = os.environ[ "SARDIS_API_KEY" ])
# Create agent wallet
agent = sardis.agents.create( name = "openai-agent" )
wallet = sardis.wallets.create(
agent_id = agent.agent_id,
chain = "base" ,
currency = "USDC" ,
limit_per_tx = 100.00 ,
limit_total = 500.00 ,
)
# Get Sardis function definitions
tools = get_sardis_tools()
# Agent loop
messages = [
{
"role" : "system" ,
"content" : "You are a procurement agent with a Sardis wallet. "
"Use sardis_pay to execute payments."
},
{
"role" : "user" ,
"content" : "Pay $25 to OpenAI for API credits"
}
]
while True :
response = openai_client.chat.completions.create(
model = "gpt-4o" ,
messages = messages,
tools = tools,
)
message = response.choices[ 0 ].message
messages.append(message)
# Handle function calls
if message.tool_calls:
for tool_call in message.tool_calls:
result = handle_sardis_tool_call(
sardis_client = sardis,
wallet_id = wallet.wallet_id,
tool_call = tool_call,
)
messages.append({
"role" : "tool" ,
"tool_call_id" : tool_call.id,
"content" : result,
})
else :
print (message.content)
break
The sardis-openai package provides 5 pre-configured tools with strict mode:
sardis_pay Execute payment with policy enforcement
sardis_check_balance Check wallet balance and limits
sardis_check_policy Dry-run policy validation
sardis_issue_card Issue virtual card for agent
sardis_get_spending_summary Get spending analytics
sardis_pay
{
"type" : "function" ,
"function" : {
"name" : "sardis_pay" ,
"description" : "Execute a payment from an AI agent's wallet with policy enforcement" ,
"strict" : True ,
"parameters" : {
"type" : "object" ,
"properties" : {
"wallet_id" : { "type" : "string" },
"to" : { "type" : "string" },
"amount" : { "type" : "string" },
"token" : { "type" : "string" , "enum" : [ "USDC" , "USDT" , "EURC" , "PYUSD" ]},
"purpose" : { "type" : "string" },
},
"required" : [ "wallet_id" , "to" , "amount" , "token" , "purpose" ],
"additionalProperties" : False ,
},
},
}
sardis_check_balance
{
"type" : "function" ,
"function" : {
"name" : "sardis_check_balance" ,
"description" : "Check wallet balance, spending limits, and remaining budget" ,
"strict" : True ,
"parameters" : {
"type" : "object" ,
"properties" : {
"wallet_id" : { "type" : "string" },
},
"required" : [ "wallet_id" ],
"additionalProperties" : False ,
},
},
}
sardis_check_policy
{
"type" : "function" ,
"function" : {
"name" : "sardis_check_policy" ,
"description" : "Validate payment against policy before execution" ,
"strict" : True ,
"parameters" : {
"type" : "object" ,
"properties" : {
"wallet_id" : { "type" : "string" },
"amount" : { "type" : "string" },
"vendor" : { "type" : "string" },
},
"required" : [ "wallet_id" , "amount" ],
"additionalProperties" : False ,
},
},
}
Import Options
from sardis_openai import get_sardis_tools
tools = get_sardis_tools()
# Returns list of 5 function definitions
from sardis_openai import SARDIS_TOOL_DEFINITIONS
# Get only payment and balance tools
tools = [
SARDIS_TOOL_DEFINITIONS [ 0 ], # sardis_pay
SARDIS_TOOL_DEFINITIONS [ 1 ], # sardis_check_balance
]
The package includes a handler for processing tool calls:
from sardis_openai import handle_sardis_tool_call
result = handle_sardis_tool_call(
sardis_client = sardis,
wallet_id = wallet.wallet_id,
tool_call = tool_call,
)
Strict Mode Benefits
Strict mode ("strict": True) ensures:
No Hallucinated Parameters : OpenAI won’t invent parameter values
Type Safety : All parameters validated against schema
Required Fields : Missing required fields cause immediate errors
No Extra Fields : additionalProperties: False prevents unexpected data
Without strict mode:
// Agent might hallucinate:
{
"to" : "openai.com" ,
"amount" : "25.00" ,
"token" : "USDC" ,
"purpose" : "API credits" ,
"urgent" : true , // ❌ Hallucinated field
"category" : "software" // ❌ Not in schema
}
With strict mode:
// Agent constrained to schema:
{
"to" : "openai.com" ,
"amount" : "25.00" ,
"token" : "USDC" ,
"purpose" : "API credits"
} // ✓ Exactly matches schema
Assistants API
Use Sardis with OpenAI Assistants:
from openai import OpenAI
from sardis import SardisClient
from sardis_openai import get_sardis_tools
client = OpenAI()
sardis = SardisClient( api_key = "sk_live_..." )
# Create assistant with Sardis tools
assistant = client.beta.assistants.create(
name = "Procurement Assistant" ,
instructions = (
"You are a procurement assistant with a Sardis wallet. "
"Help users purchase software and API credits."
),
model = "gpt-4o" ,
tools = get_sardis_tools(),
)
# Create thread
thread = client.beta.threads.create()
# Add message
client.beta.threads.messages.create(
thread_id = thread.id,
role = "user" ,
content = "Pay $30 to Anthropic for API credits" ,
)
# Run assistant
run = client.beta.threads.runs.create(
thread_id = thread.id,
assistant_id = assistant.id,
)
# Handle tool calls
while run.status == "requires_action" :
tool_outputs = []
for tool_call in run.required_action.submit_tool_outputs.tool_calls:
result = handle_sardis_tool_call(
sardis_client = sardis,
wallet_id = wallet.wallet_id,
tool_call = tool_call,
)
tool_outputs.append({
"tool_call_id" : tool_call.id,
"output" : result,
})
run = client.beta.threads.runs.submit_tool_outputs(
thread_id = thread.id,
run_id = run.id,
tool_outputs = tool_outputs,
)
# Get response
messages = client.beta.threads.messages.list( thread_id = thread.id)
print (messages.data[ 0 ].content[ 0 ].text.value)
Error Handling
import json
from decimal import Decimal
from openai import OpenAI
from sardis import SardisClient
from sardis.exceptions import PolicyViolationError, InsufficientBalanceError
def handle_sardis_pay ( args : dict , sardis : SardisClient, wallet_id : str ) -> str :
try :
result = sardis.wallets.transfer(
wallet_id,
destination = args[ "to" ],
amount = Decimal(args[ "amount" ]),
token = args[ "token" ],
chain = "base" ,
domain = args[ "to" ],
memo = args[ "purpose" ],
)
return json.dumps({
"success" : True ,
"tx_hash" : result.tx_hash,
"amount" : str (result.amount),
"token" : result.token,
})
except PolicyViolationError as e:
return json.dumps({
"success" : False ,
"error" : "policy_violation" ,
"message" : str (e),
})
except InsufficientBalanceError as e:
return json.dumps({
"success" : False ,
"error" : "insufficient_balance" ,
"message" : str (e),
})
except Exception as e:
return json.dumps({
"success" : False ,
"error" : "unknown" ,
"message" : str (e),
})
Streaming Responses
Use with OpenAI’s streaming API:
stream = client.chat.completions.create(
model = "gpt-4o" ,
messages = messages,
tools = tools,
stream = True ,
)
for chunk in stream:
if chunk.choices[ 0 ].delta.content:
print (chunk.choices[ 0 ].delta.content, end = "" )
if chunk.choices[ 0 ].delta.tool_calls:
# Handle function calls
for tool_call in chunk.choices[ 0 ].delta.tool_calls:
if tool_call.function.name:
print ( f " \n Calling { tool_call.function.name } ..." )
Best Practices
1. Use Strict Mode Always
# ✓ Good - Strict mode enabled
{
"type" : "function" ,
"function" : {
"name" : "sardis_pay" ,
"strict" : True ,
"parameters" : { ... }
}
}
# ❌ Bad - No strict mode
{
"type" : "function" ,
"function" : {
"name" : "sardis_pay" ,
"parameters" : { ... }
}
}
def handle_sardis_pay ( args : dict ) -> str :
try :
amount = Decimal(args[ "amount" ])
except ( ValueError , KeyError ):
return json.dumps({ "success" : False , "error" : "Invalid amount format" })
if amount <= 0 :
return json.dumps({ "success" : False , "error" : "Amount must be positive" })
# Proceed with payment
3. Return Structured JSON
# ✓ Good - Structured response
return json.dumps({
"success" : True ,
"tx_hash" : "0x7f3b...a2c9" ,
"amount" : "25.00" ,
"token" : "USDC" ,
"chain" : "base" ,
})
# ❌ Bad - Plain text
return "Payment successful: 0x7f3b...a2c9"
4. Handle All Error Cases
try :
result = sardis.wallets.transfer( ... )
except PolicyViolationError:
return json.dumps({ "error" : "policy_violation" })
except InsufficientBalanceError:
return json.dumps({ "error" : "insufficient_balance" })
except NetworkError:
return json.dumps({ "error" : "network_error" })
except Exception as e:
return json.dumps({ "error" : "unknown" , "message" : str (e)})
Example: Multi-Step Procurement
def run_procurement_agent ( task : str ):
client = OpenAI()
sardis = SardisClient( api_key = "sk_live_..." )
messages = [
{
"role" : "system" ,
"content" : (
"You are a procurement agent. For each purchase:"
"1. Check wallet balance first"
"2. Validate against policy"
"3. Execute payment"
"4. Confirm with transaction hash"
),
},
{ "role" : "user" , "content" : task},
]
tools = get_sardis_tools()
while True :
response = client.chat.completions.create(
model = "gpt-4o" ,
messages = messages,
tools = tools,
)
message = response.choices[ 0 ].message
messages.append(message)
if message.tool_calls:
for tool_call in message.tool_calls:
result = handle_sardis_tool_call(
sardis_client = sardis,
wallet_id = "wallet_abc123" ,
tool_call = tool_call,
)
messages.append({
"role" : "tool" ,
"tool_call_id" : tool_call.id,
"content" : result,
})
else :
return message.content
# Run
result = run_procurement_agent(
"Purchase $30 of Anthropic API credits and $50 of AWS credits. "
"Check balance before each payment."
)
print (result)
Next Steps
Vercel AI SDK Build streaming payment agents with Vercel AI
Anthropic Claude Use Claude’s Agent SDK with Sardis
Policy Engine Understand spending policy enforcement
API Reference Full Python SDK documentation