Client API
Overview
The Jaxon platform provides multiple ways to integrate with your applications:
- Python Client Library - High-level Python API wrapping the REST endpoints
- REST API - Direct HTTP/REST access using curl or any HTTP client
- WebSocket API - Real-time streaming for advanced use cases
- Direct Kafka - For services running inside the Docker stack
Installation
Python Client
The client is distributed as a Python wheel file:
pip install jaxon-<version>-py3-none-any.whl
Replace <version> with the current platform version (e.g., 1.2.0).
REST API
No installation required - use curl, httpie, or any HTTP client library.
HTTP/WebSocket Mode (Recommended)
This is the simpler approach for most use cases, requiring only a URL and optional authentication token.
Basic Setup
from jaxon import Client
from jaxon.vendor.data_model import EntailmentFrame
# Connect to the platform via HTTP
api_url = "https://your-domain.com:8443/client-api"
client = Client(
api_base_url=api_url,
verbose=False
)
# Use the client...
# Always close when done
client.close()
With Authentication
If authentication is enabled on your platform deployment:
from jaxon import Client, ServiceAccountSession
from jaxon.vendor.data_model import EntailmentFrame
import os
# Get authentication token
token = ServiceAccountSession(
service_account=os.getenv("SERVICE_ACCOUNT_USERNAME"),
service_token=os.getenv("SERVICE_ACCOUNT_TOKEN"),
session_file=os.getenv("AUTH_SESSION_FILE")
).ensure_service_account_session(debug=False)
# Create authenticated client
client = Client(
api_base_url="https://your-domain.com:8443/client-api",
auth_token=token,
verbose=False
)
Direct Mode (For Internal Services)
For services running inside the Docker stack, you can use direct Kafka and etcd access:
from jaxon import Client
client = Client(
group="my-application-client",
bus_host="bus", # Internal Docker service name
bus_port=9092, # Internal Kafka port
config_host="config", # Internal etcd service name
config_port=2379,
verbose=False
)
Sending Requests
All requests are packaged as EntailmentFrame objects:
from jaxon.vendor.data_model import EntailmentFrame
# Create an entailment frame
frame = EntailmentFrame(
C=["Context document 1", "Context document 2"], # Context
Q="Your question here", # Question
A="Answer to validate", # Answer (optional for some guardrails)
P=[], # Proof (populated by policy rules)
E=None # Evaluation (populated by guardrails)
)
# Send to a guardrail
guardrail_id = "your-guardrail-id" # From the Web UI
response_topic = "my-response-topic"
_, trace_id = client.send_message(guardrail_id, response_topic, frame)
Receiving Responses
After sending a request, poll for the response:
# Poll for response with timeout
timeout = 120000 # milliseconds
response = client.get_response(trace_id, response_topic, timeout)
# Response is a dictionary containing the evaluated frame
print(response['entailment_frame']) # JSON string with evaluation results
Complete Example
from jaxon import Client
from jaxon.vendor.data_model import EntailmentFrame
# Create client
client = Client(
api_base_url="https://your-domain.com:8443/client-api",
verbose=False
)
try:
# Create request frame
frame = EntailmentFrame(
C=["All dogs go to heaven.", "Fido is a cat."],
Q="Does Fido go to heaven?",
A="Yes"
)
# Send request
guardrail_id = "d79c0e0d"
response_topic = "my-app-response"
_, trace_id = client.send_message(guardrail_id, response_topic, frame)
# Get response
response = client.get_response(trace_id, response_topic, timeout=120000)
# Parse result
import json
frame_data = json.loads(response['entailment_frame'])
evaluation = frame_data['E']
print(f"Conclusion: {evaluation['conclusion']}")
print(f"Confidence: {evaluation['confidence']}")
finally:
client.close()
REST API (Direct HTTP Access)
The Python client is a lightweight wrapper around the REST API. You can access the platform directly using HTTP requests and WebSocket.
Base URL
https://your-domain.com:8443/client-api
Note: All client API endpoints are prefixed with /client-api/ when accessed through the web interface.
Authentication
If authentication is enabled, you'll need a service account token:
# Set your service account credentials
USERNAME="your-service-account"
SERVICE_TOKEN="your-service-token"
# Exchange for JWT token (stored in TOKEN variable)
TOKEN=$(curl -s -k -X POST "https://your-domain.com:8443/client-api/auth/token" \
-d "username=$USERNAME&service_token=$SERVICE_TOKEN" | jq -r '.token')
Complete HTTP + WebSocket Example
Here's a complete bash script that sends a request and waits for the response:
#!/bin/bash
set -e
API_URL="https://your-domain.com:8443"
GUARDRAIL_ID="your-guardrail-id"
TRACE_ID=$(uuidgen || echo "$(date +%s)-$$-$RANDOM")
TOKEN="your-service-account-token-here"
# Send request
curl -s -k -X POST "$API_URL/client-api/bus/send?target_id=$GUARDRAIL_ID" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"trace_id": "'$TRACE_ID'", "response_topic": ["response"], "entailment_frame": {"C": ["Context document here"], "Q": "Your question?", "A": "Answer to validate", "P": [], "E": null}}' > /dev/null
# Receive response (requires websocat: brew install websocat OR apt install websocat OR yum install websocat)
WS_URL="${API_URL/https:/wss:}"
WS_URL="${WS_URL/http:/ws:}"
exec 3< <((echo '{"action":"subscribe","topic":"response","trace_id":"'$TRACE_ID'"}'; sleep 120) | \
websocat -k "$WS_URL/client-api/bus/stream?token=$TOKEN" 2>/dev/null)
while IFS= read -r line <&3; do
if echo "$line" | grep -q '"type":"response"'; then
echo "$line" | jq -r '.data.entailment_frame | fromjson'
exec 3<&-
pkill -P $$ websocat 2>/dev/null
exit 0
fi
done
This script:
1. Sends the request via HTTP POST to /client-api/bus/send?target_id=...
2. Connects to WebSocket at /client-api/bus/stream?token=...
3. Subscribes to the response topic with the trace_id
4. Waits for the response message
5. Prints the pretty-printed entailment frame result
6. Exits automatically when response is received
Manual Steps
If you prefer to understand each step:
1. Send Request
TRACE_ID=$(uuidgen)
curl -k -X POST "https://your-domain.com:8443/client-api/bus/send?target_id=$GUARDRAIL_ID" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"trace_id": "'$TRACE_ID'",
"response_topic": ["response"],
"entailment_frame": {
"C": ["All dogs go to heaven.", "Fido is a cat."],
"Q": "Does Fido go to heaven?",
"A": "Yes",
"P": [],
"E": null
}
}'
Response:
{
"status": "sent",
"topic": "qa_policy_rules",
"trace_id": "123e4567-e89b-12d3-a456-426614174000"
}
2. Receive Response via WebSocket
Connect to the WebSocket and subscribe to the response topic:
# Using websocat (brew install websocat / apt install websocat / yum install websocat)
echo '{"action":"subscribe","topic":"response","trace_id":"'$TRACE_ID'"}' | \
websocat -k "wss://your-domain.com:8443/client-api/bus/stream?token=$TOKEN"
You'll receive:
1. An acknowledgment: {"type":"ack","action":"subscribe","success":true,...}
2. The response: {"type":"response","trace_id":"...","data":{...}}
The response data contains the evaluated entailment frame:
{
"type": "response",
"trace_id": "123e4567-e89b-12d3-a456-426614174000",
"data": {
"entailment_frame": "{\"C\":[...],\"E\":{\"conclusion\":\"NO\",\"confidence\":0.95}}",
"trace_id": "123e4567-e89b-12d3-a456-426614174000",
"rail_id": "your-guardrail-id"
}
}
REST API Reference
POST /client-api/bus/send
Send a message to a guardrail or application.
URL Parameters:
- target_id (required): Guardrail ID or Application ID
Request Body:
{
"trace_id": "string",
"response_topic": ["string"],
"entailment_frame": {
"C": ["string"], // Context (array of strings)
"Q": "string", // Question (optional)
"A": "string", // Answer (optional)
"P": [], // Proof steps (populated by guardrail)
"E": null // Evaluation (populated by guardrail)
}
}
Response:
{
"status": "sent",
"topic": "string", // Kafka topic message was sent to
"trace_id": "string" // Your trace ID for tracking the response
}
Example:
curl -k -X POST "https://your-domain.com:8443/client-api/bus/send?target_id=d79c0e0d" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"response_topic": ["response"],
"entailment_frame": {
"C": ["Context here"],
"Q": "Question here",
"A": "Answer here",
"P": [],
"E": null
}
}'
POST /client-api/auth/token
Exchange service account credentials for a JWT token.
Request Parameters:
- username: Service account username
- service_token: Service account token
Response:
{
"token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"expires_in": 3600
}
WebSocket /client-api/bus/stream
WebSocket endpoint for real-time message streaming.
Connection: wss://your-domain.com:8443/client-api/bus/stream?token=YOUR_TOKEN
Protocol:
Client sends (subscribe to topic):
{"action": "subscribe", "topic": "response", "trace_id": "550e8400-e29b-41d4-a716-446655440000"}
Server responds (acknowledgment):
{"type": "ack", "action": "subscribe", "success": true, "topic": "response", "trace_id": "550e8400-e29b-41d4-a716-446655440000"}
Server sends (when response is available):
{
"type": "response",
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"entailment_frame": "{\"C\":[...],\"E\":{\"conclusion\":\"YES\",\"confidence\":0.95}}",
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"rail_id": "d79c0e0d"
}
}
Response Structure
The response is a dictionary with the following structure:
{
'entailment_frame': '<JSON string>', # Evaluated EntailmentFrame
'id': '<message-id>',
'trace_id': '<trace-id>',
'response_topic': [],
'rail_id': '<guardrail-id>'
}
The entailment_frame field contains a JSON-encoded EntailmentFrame with populated E (evaluation) and optionally P (proof) fields:
{
"C": ["context..."],
"Q": "question...",
"A": "answer...",
"P": [...],
"E": {
"conclusion": "YES",
"confidence": 0.95
},
"Error": null
}
Best Practices
Client Lifecycle
- Create one client instance per application/service
- Reuse the client for multiple requests
- Always call
client.close()when done (use try/finally or context managers)
Timeouts
- Set appropriate timeouts based on your guardrail complexity
- Policy rules guardrails: 30-60 seconds
- Agentic guardrails (consistency, critique): 120-300 seconds
- Complex DAGs: 300+ seconds
Response Topics
- Use descriptive, application-specific response topic names
- Avoid generic names like "response" when running multiple applications
- Topics are automatically created if they don't exist
Error Handling
try:
response = client.get_response(trace_id, response_topic, timeout)
frame_data = json.loads(response['entailment_frame'])
if frame_data.get('Error'):
print(f"Guardrail error: {frame_data['Error']}")
else:
evaluation = frame_data['E']
# Process evaluation...
except TimeoutError:
print("Request timed out")
except Exception as e:
print(f"Client error: {e}")
finally:
client.close()
See Also
- Tutorials - Step-by-step guides with client examples
- Guardrails - Available guardrail types and their configurations
- Applications - Creating applications and DAGs