Cloud-Scale Reference
jac-scale Reference
Section titled “jac-scale Reference”Complete reference for jac-scale, the cloud-native deployment and scaling plugin for Jac.
Installation
Section titled “Installation”pip install jac-scaleStarting a Server
Section titled “Starting a Server”Basic Server
Section titled “Basic Server”jac start app.jacServer Options
Section titled “Server Options”| Option | Description | Default |
|---|---|---|
--port | Server port | 8000 |
--host | Bind address | 0.0.0.0 |
--workers | Number of workers | 1 |
--reload | Hot reload on changes | false |
--scale | Deploy to Kubernetes | false |
--build -b | Build and push Docker image (with —scale) | false |
--experimental -e | Install from repo instead of PyPI (with —scale) | false |
--target | Deployment target (kubernetes, aws, gcp) | kubernetes |
--registry | Image registry (dockerhub, ecr, gcr) | dockerhub |
Examples
Section titled “Examples”# Custom portjac start app.jac --port 3000
# Multiple workersjac start app.jac --workers 4
# Development with hot reloadjac start app.jac --reload
# Productionjac start app.jac --host 0.0.0.0 --port 8000 --workers 4API Endpoints
Section titled “API Endpoints”Automatic Endpoint Generation
Section titled “Automatic Endpoint Generation”Each walker becomes an API endpoint:
walker get_users { can fetch with Root entry { report []; }}Becomes: POST /walker/get_users
Request Format
Section titled “Request Format”Walker parameters become request body:
walker search { has query: str; has limit: int = 10;}curl -X POST http://localhost:8000/walker/search \ -H "Content-Type: application/json" \ -d '{"query": "hello", "limit": 20}'Response Format
Section titled “Response Format”Walker report values become the response.
@restspec Decorator
Section titled “@restspec Decorator”The @restspec decorator customizes how walkers and functions are exposed as REST API endpoints.
Options
Section titled “Options”| Option | Type | Default | Description |
|---|---|---|---|
method | HTTPMethod | POST | HTTP method for the endpoint |
path | str | "" (auto-generated) | Custom URL path for the endpoint |
protocol | APIProtocol | APIProtocol.HTTP | Protocol for the endpoint (HTTP, WEBHOOK, or WEBSOCKET) |
broadcast | bool | False | Broadcast responses to all connected WebSocket clients (only valid with WEBSOCKET protocol) |
Note:
APIProtocolandrestspecare builtins and do not require an import statement.HTTPMethodmust be imported withimport from http { HTTPMethod }.
Custom HTTP Method
Section titled “Custom HTTP Method”By default, walkers are exposed as POST endpoints. Use @restspec to change this:
import from http { HTTPMethod }
@restspec(method=HTTPMethod.GET)walker :pub get_users { can fetch with Root entry { report []; }}This walker is now accessible at GET /walker/get_users instead of POST.
Custom Path
Section titled “Custom Path”Override the auto-generated path:
@restspec(method=HTTPMethod.GET, path="/custom/users")walker :pub list_users { can fetch with Root entry { report []; }}Accessible at GET /custom/users.
Functions
Section titled “Functions”@restspec also works on standalone functions:
@restspec(method=HTTPMethod.GET)def :pub health_check() -> dict { return {"status": "healthy"};}
@restspec(method=HTTPMethod.GET, path="/custom/status")def :pub app_status() -> dict { return {"status": "running", "version": "1.0.0"};}Webhook Mode
Section titled “Webhook Mode”See the Webhooks section below.
Authentication
Section titled “Authentication”User Registration
Section titled “User Registration”curl -X POST http://localhost:8000/user/register \ -H "Content-Type: application/json" \ -d '{"email": "user@example.com", "password": "secret"}'User Login
Section titled “User Login”curl -X POST http://localhost:8000/user/login \ -H "Content-Type: application/json" \ -d '{"email": "user@example.com", "password": "secret"}'Returns:
{ "access_token": "eyJ...", "token_type": "bearer"}Authenticated Requests
Section titled “Authenticated Requests”curl -X POST http://localhost:8000/walker/my_walker \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{}'JWT Configuration
Section titled “JWT Configuration”Configure JWT authentication via environment variables:
| Variable | Description | Default |
|---|---|---|
JWT_SECRET | Secret key for JWT signing | supersecretkey |
JWT_ALGORITHM | JWT algorithm | HS256 |
JWT_EXP_DELTA_DAYS | Token expiration in days | 7 |
SSO (Single Sign-On)
Section titled “SSO (Single Sign-On)”jac-scale supports SSO with external identity providers. Currently supported: Google.
Configuration:
| Variable | Description |
|---|---|
SSO_HOST | SSO callback host URL (default: http://localhost:8000/sso) |
SSO_GOOGLE_CLIENT_ID | Google OAuth client ID |
SSO_GOOGLE_CLIENT_SECRET | Google OAuth client secret |
SSO Endpoints:
| Method | Path | Description |
|---|---|---|
| GET | /sso/{platform}/login | Redirect to provider login page |
| GET | /sso/{platform}/register | Redirect to provider registration |
| GET | /sso/{platform}/login/callback | OAuth callback handler |
Example:
# Redirect user to Google logincurl http://localhost:8000/sso/google/loginPermissions & Access Control
Section titled “Permissions & Access Control”Access Levels
Section titled “Access Levels”| Level | Value | Description |
|---|---|---|
NO_ACCESS | -1 | No access to the object |
READ | 0 | Read-only access |
CONNECT | 1 | Can traverse edges to/from this object |
WRITE | 2 | Full read/write access |
Granting Permissions
Section titled “Granting Permissions”To Everyone
Section titled “To Everyone”Use perm_grant to allow all users to access an object at a given level:
with entry { # Allow everyone to read this node perm_grant(node, READ);
# Allow everyone to write perm_grant(node, WRITE);}To a Specific Root
Section titled “To a Specific Root”Use allow_root to grant access to a specific user’s root graph:
with entry { # Allow a specific user to read this node allow_root(node, target_root_id, READ);
# Allow write access allow_root(node, target_root_id, WRITE);}Revoking Permissions
Section titled “Revoking Permissions”From Everyone
Section titled “From Everyone”with entry { # Revoke all public access perm_revoke(node);}From a Specific Root
Section titled “From a Specific Root”with entry { # Revoke a specific user's access disallow_root(node, target_root_id, READ);}Walker Access Levels
Section titled “Walker Access Levels”Walkers have three access levels when served as API endpoints:
| Access | Description |
|---|---|
Public (:pub) | Accessible without authentication |
| Protected (default) | Requires JWT authentication |
Private (:priv) | Only accessible by directly defined walkers (not imported) |
Permission Functions Reference
Section titled “Permission Functions Reference”| Function | Signature | Description |
|---|---|---|
perm_grant | perm_grant(archetype, level) | Allow everyone to access at given level |
perm_revoke | perm_revoke(archetype) | Remove all public access |
allow_root | allow_root(archetype, root_id, level) | Grant access to a specific root |
disallow_root | disallow_root(archetype, root_id, level) | Revoke access from a specific root |
Webhooks
Section titled “Webhooks”Webhooks allow external services (payment processors, CI/CD systems, messaging platforms, etc.) to send real-time notifications to your Jac application. Jac-Scale provides:
- Dedicated
/webhook/endpoints for webhook walkers - API key authentication for secure access
- HMAC-SHA256 signature verification to validate request integrity
- Automatic endpoint generation based on walker configuration
Configuration
Section titled “Configuration”Webhook configuration is managed via the jac.toml file in your project root.
[plugins.scale.webhook]secret = "your-webhook-secret-key"signature_header = "X-Webhook-Signature"verify_signature = trueapi_key_expiry_days = 365| Option | Type | Default | Description |
|---|---|---|---|
secret | string | "webhook-secret-key" | Secret key for HMAC signature verification. Can also be set via WEBHOOK_SECRET environment variable. |
signature_header | string | "X-Webhook-Signature" | HTTP header name containing the HMAC signature. |
verify_signature | boolean | true | Whether to verify HMAC signatures on incoming requests. |
api_key_expiry_days | integer | 365 | Default expiry period for API keys in days. Set to 0 for permanent keys. |
Environment Variables:
For production deployments, use environment variables for sensitive values:
export WEBHOOK_SECRET="your-secure-random-secret"Creating Webhook Walkers
Section titled “Creating Webhook Walkers”To create a webhook endpoint, use the @restspec(protocol=APIProtocol.WEBHOOK) decorator on your walker definition.
Basic Webhook Walker
Section titled “Basic Webhook Walker”@restspec(protocol=APIProtocol.WEBHOOK)walker PaymentReceived { has payment_id: str, amount: float, currency: str = 'USD';
can process with Root entry { # Process the payment notification report { "status": "success", "message": f"Payment {self.payment_id} received", "amount": self.amount, "currency": self.currency }; }}This walker will be accessible at POST /webhook/PaymentReceived.
Important Notes
Section titled “Important Notes”- Webhook walkers are only accessible via
/webhook/{walker_name}endpoints - They are not accessible via the standard
/walker/{walker_name}endpoint
API Key Management
Section titled “API Key Management”Webhook endpoints require API key authentication. Users must first create an API key before calling webhook endpoints.
Creating an API Key
Section titled “Creating an API Key”Endpoint: POST /api-key/create
Headers:
Authorization: Bearer <jwt_token>(required)
Request Body:
{ "name": "My Webhook Key", "expiry_days": 30}Response:
{ "api_key": "eyJhbGciOiJIUzI1NiIs...", "api_key_id": "a1b2c3d4e5f6...", "name": "My Webhook Key", "created_at": "2024-01-15T10:30:00Z", "expires_at": "2024-02-14T10:30:00Z"}Listing API Keys
Section titled “Listing API Keys”Endpoint: GET /api-key/list
Headers:
Authorization: Bearer <jwt_token>(required)
Calling Webhook Endpoints
Section titled “Calling Webhook Endpoints”Webhook endpoints require two headers for authentication:
X-API-Key: The API key obtained from/api-key/createX-Webhook-Signature: HMAC-SHA256 signature of the request body
Generating the Signature
Section titled “Generating the Signature”The signature is computed as: HMAC-SHA256(request_body, api_key)
cURL Example:
API_KEY="eyJhbGciOiJIUzI1NiIs..."PAYLOAD='{"payment_id":"PAY-12345","amount":99.99,"currency":"USD"}'SIGNATURE=$(echo -n "$PAYLOAD" | openssl dgst -sha256 -hmac "$API_KEY" | cut -d' ' -f2)
curl -X POST "http://localhost:8000/webhook/PaymentReceived" \ -H "Content-Type: application/json" \ -H "X-API-Key: $API_KEY" \ -H "X-Webhook-Signature: $SIGNATURE" \ -d "$PAYLOAD"Webhook vs Regular Walkers
Section titled “Webhook vs Regular Walkers”| Feature | Regular Walker (/walker/) | Webhook Walker (/webhook/) |
|---|---|---|
| Authentication | JWT Bearer token | API Key + HMAC Signature |
| Use Case | User-facing APIs | External service callbacks |
| Access Control | User-scoped | Service-scoped |
| Signature Verification | No | Yes (HMAC-SHA256) |
| Endpoint Path | /walker/{name} | /webhook/{name} |
Webhook API Reference
Section titled “Webhook API Reference”Webhook Endpoints
Section titled “Webhook Endpoints”| Method | Path | Description |
|---|---|---|
| POST | /webhook/{walker_name} | Execute webhook walker |
API Key Endpoints
Section titled “API Key Endpoints”| Method | Path | Description |
|---|---|---|
| POST | /api-key/create | Create a new API key |
| GET | /api-key/list | List all API keys for user |
| DELETE | /api-key/{api_key_id} | Revoke an API key |
Required Headers for Webhook Requests
Section titled “Required Headers for Webhook Requests”| Header | Required | Description |
|---|---|---|
Content-Type | Yes | Must be application/json |
X-API-Key | Yes | API key from /api-key/create |
X-Webhook-Signature | Yes* | HMAC-SHA256 signature (*if verify_signature is enabled) |
WebSockets
Section titled “WebSockets”Jac Scale provides built-in support for WebSocket endpoints, enabling real-time bidirectional communication between clients and walkers.
Overview
Section titled “Overview”WebSockets allow persistent, full-duplex connections between a client and your Jac application. Unlike REST endpoints (single request-response), a WebSocket connection stays open, allowing multiple messages to be exchanged in both directions. Jac Scale provides:
- Dedicated
/ws/endpoints for WebSocket walkers - Persistent connections with a message loop
- JSON message protocol for sending walker fields and receiving results
- JWT authentication via query parameter or message payload
- Connection management with automatic cleanup on disconnect
- HMR support in dev mode for live reloading
Creating WebSocket Walkers
Section titled “Creating WebSocket Walkers”To create a WebSocket endpoint, use the @restspec(protocol=APIProtocol.WEBSOCKET) decorator on an async walker definition.
Basic WebSocket Walker (Public)
Section titled “Basic WebSocket Walker (Public)”@restspec(protocol=APIProtocol.WEBSOCKET)async walker : pub EchoMessage { has message: str; has client_id: str = "anonymous";
async can echo with Root entry { report { "echo": self.message, "client_id": self.client_id }; }}This walker will be accessible at ws://localhost:8000/ws/EchoMessage.
Authenticated WebSocket Walker
Section titled “Authenticated WebSocket Walker”To create a private walker that requires JWT authentication, simply remove : pub from the walker definition.
Broadcasting WebSocket Walker
Section titled “Broadcasting WebSocket Walker”Use broadcast=True to send messages to ALL connected clients of this walker:
@restspec(protocol=APIProtocol.WEBSOCKET, broadcast=True)async walker : pub ChatRoom { has message: str; has sender: str = "anonymous";
async can handle with Root entry { report { "type": "message", "sender": self.sender, "content": self.message }; }}When a client sends a message, all connected clients receive the response, making it ideal for:
- Chat rooms
- Live notifications
- Real-time collaboration
- Game state synchronization
Private Broadcasting Walker
Section titled “Private Broadcasting Walker”To create a private broadcasting walker, remove : pub from the walker definition. Only authenticated users can connect and send messages, and all authenticated users receive broadcasts.
Important Notes
Section titled “Important Notes”- WebSocket walkers must be declared as
async walker - Use
: pubfor public access (no authentication required) or omit it to require JWT auth - Use
broadcast=Trueto send responses to ALL connected clients (only valid with WEBSOCKET protocol) - WebSocket walkers are only accessible via
ws://host/ws/{walker_name} - The connection stays open until the client disconnects
Storage
Section titled “Storage”Jac provides a built-in storage abstraction for file and blob operations. The core runtime ships with a local filesystem implementation, and jac-scale can override it with cloud storage backends — all through the same store() builtin.
The store() Builtin
Section titled “The store() Builtin”The recommended way to get a storage instance is the store() builtin. It requires no imports and is automatically hookable by plugins:
# Get a storage instance (no imports needed)glob storage = store();
# With custom base pathglob storage = store(base_path="./uploads");
# With all optionsglob storage = store(base_path="./uploads", create_dirs=True);| Parameter | Type | Default | Description |
|---|---|---|---|
base_path | str | "./storage" | Root directory for all files |
create_dirs | bool | True | Create base directory if it doesn’t exist |
Without jac-scale, store() returns a LocalStorage instance. With jac-scale installed, it returns a configuration-driven backend (reading from jac.toml and environment variables).
Storage Interface
Section titled “Storage Interface”All storage instances provide these methods:
| Method | Signature | Description |
|---|---|---|
upload | upload(source, destination, metadata=None) -> str | Upload a file (from path or file object) |
download | download(source, destination=None) -> bytes|None | Download a file (returns bytes if no destination) |
delete | delete(path) -> bool | Delete a file or directory |
exists | exists(path) -> bool | Check if a path exists |
list_files | list_files(prefix="", recursive=False) | List files (yields paths) |
get_metadata | get_metadata(path) -> dict | Get file metadata (size, modified, created, is_dir, name) |
copy | copy(source, destination) -> bool | Copy a file within storage |
move | move(source, destination) -> bool | Move a file within storage |
Usage Example
Section titled “Usage Example”import from http { UploadFile }import from uuid { uuid4 }
glob storage = store(base_path="./uploads");
walker :pub upload_file { has file: UploadFile; has folder: str = "documents";
can process with Root entry { unique_name = f"{uuid4()}.dat"; path = f"{self.folder}/{unique_name}";
# Upload file storage.upload(self.file.file, path);
# Get metadata metadata = storage.get_metadata(path);
report { "success": True, "storage_path": path, "size": metadata["size"] }; }}
walker :pub list_files { has folder: str = "documents"; has recursive: bool = False;
can process with Root entry { files = []; for path in storage.list_files(self.folder, self.recursive) { metadata = storage.get_metadata(path); files.append({ "path": path, "size": metadata["size"], "name": metadata["name"] }); } report {"files": files}; }}
walker :pub download_file { has path: str;
can process with Root entry { if not storage.exists(self.path) { report {"error": "File not found"}; return; } content = storage.download(self.path); report {"content": content, "size": len(content)}; }}Configuration
Section titled “Configuration”Configure storage in jac.toml:
[storage]storage_type = "local" # Storage backend typebase_path = "./storage" # Base directory for filescreate_dirs = true # Auto-create directories| Option | Type | Default | Description |
|---|---|---|---|
storage_type | string | "local" | Storage backend (local) |
base_path | string | "./storage" | Base path for file storage |
create_dirs | boolean | true | Automatically create directories |
Environment Variables:
| Variable | Description |
|---|---|
JAC_STORAGE_TYPE | Storage type (overrides jac.toml) |
JAC_STORAGE_PATH | Base directory (overrides jac.toml) |
JAC_STORAGE_CREATE_DIRS | Auto-create directories ("true"/"false") |
Configuration priority: jac.toml > environment variables > defaults.
StorageFactory (Advanced)
Section titled “StorageFactory (Advanced)”For advanced use cases, you can use StorageFactory directly instead of the store() builtin:
import from jac_scale.factories.storage_factory { StorageFactory }
# Create with explicit type and configglob config = {"base_path": "./my-files", "create_dirs": True};glob storage = StorageFactory.create("local", config);
# Create using jac.toml / env var / defaultsglob default_storage = StorageFactory.get_default();Graph Traversal API
Section titled “Graph Traversal API”Traverse Endpoint
Section titled “Traverse Endpoint”POST /traverseParameters
Section titled “Parameters”| Parameter | Type | Description | Default |
|---|---|---|---|
source | str | Starting node/edge ID | root |
depth | int | Traversal depth | 1 |
detailed | bool | Include archetype context | false |
node_types | list | Filter by node types | all |
edge_types | list | Filter by edge types | all |
Example
Section titled “Example”curl -X POST http://localhost:8000/traverse \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "depth": 3, "node_types": ["User", "Post"], "detailed": true }'Async Walkers
Section titled “Async Walkers”walker async_processor { has items: list;
async can process with Root entry { results = []; for item in self.items { result = await process_item(item); results.append(result); } report results; }}Direct Database Access (kvstore)
Section titled “Direct Database Access (kvstore)”Direct database operations without graph layer abstraction. Supports MongoDB (document queries) and Redis (key-value with TTL/atomic ops).
import from jac_scale.lib { kvstore }
with entry { mongo_db = kvstore(db_name='my_app', db_type='mongodb'); redis_db = kvstore(db_name='cache', db_type='redis');}Parameters: db_name (str), db_type (‘mongodb’|‘redis’), uri (str|None - priority: explicit → MONGODB_URI/REDIS_URL env vars → jac.toml)
MongoDB Operations
Section titled “MongoDB Operations”Common Methods: get(), set(), delete(), exists()
Query Methods: find_one(), find(), insert_one(), insert_many(), update_one(), update_many(), delete_one(), delete_many(), find_by_id(), update_by_id(), delete_by_id()
Example:
import from jac_scale.lib { kvstore }
with entry { db = kvstore(db_name='my_app', db_type='mongodb');
db.insert_one('users', {'name': 'Alice', 'role': 'admin', 'age': 30}); alice = db.find_one('users', {'name': 'Alice'}); admins = list(db.find('users', {'role': 'admin'})); older = list(db.find('users', {'age': {'$gt': 28}}));
db.update_one('users', {'name': 'Alice'}, {'$set': {'age': 31}}); db.delete_one('users', {'name': 'Bob'});
db.set('user:123', {'status': 'active'}, 'sessions');}Query Operators: $eq, $gt, $gte, $lt, $lte, $in, $ne, $and, $or
Redis Operations
Section titled “Redis Operations”Common Methods: get(), set(), delete(), exists()
Redis Methods: set_with_ttl(), expire(), incr(), scan_keys()
Example:
import from jac_scale.lib { kvstore }
with entry { cache = kvstore(db_name='cache', db_type='redis');
cache.set('session:user123', {'user_id': '123', 'username': 'alice'}); cache.set_with_ttl('temp:token', {'token': 'xyz'}, ttl=60); cache.set_with_ttl('cache:profile', {'name': 'Alice'}, ttl=3600);
cache.incr('stats:views'); sessions = cache.scan_keys('session:*'); cache.expire('session:user123', 1800);}Note: Database-specific methods raise NotImplementedError on wrong database type.
Database Configuration
Section titled “Database Configuration”Environment Variables
Section titled “Environment Variables”| Variable | Description | Default |
|---|---|---|
MONGODB_URI | MongoDB connection URI | None |
REDIS_URL | Redis connection URL | None |
K8s_MONGODB | Enable MongoDB deployment | false |
K8s_REDIS | Enable Redis deployment | false |
Memory Hierarchy
Section titled “Memory Hierarchy”jac-scale uses a tiered memory system:
| Tier | Backend | Purpose |
|---|---|---|
| L1 | In-memory | Volatile runtime state |
| L2 | Redis | Cache layer |
| L3 | MongoDB | Persistent storage |
Kubernetes Deployment
Section titled “Kubernetes Deployment”Deploy
Section titled “Deploy”# Deploy to Kubernetesjac start app.jac --scale
# Build Docker image and deployjac start app.jac --scale --buildRemove Deployment
Section titled “Remove Deployment”jac destroy app.jacEnvironment Variables
Section titled “Environment Variables”| Variable | Description | Default |
|---|---|---|
APP_NAME | Application name for K8s resources | jaseci |
K8s_NAMESPACE | Kubernetes namespace | default |
K8s_NODE_PORT | External NodePort | 30001 |
K8s_CPU_REQUEST | CPU resource request | None |
K8s_CPU_LIMIT | CPU resource limit | None |
K8s_MEMORY_REQUEST | Memory resource request | None |
K8s_MEMORY_LIMIT | Memory resource limit | None |
K8s_READINESS_INITIAL_DELAY | Readiness probe initial delay (seconds) | 10 |
K8s_READINESS_PERIOD | Readiness probe period (seconds) | 20 |
K8s_LIVENESS_INITIAL_DELAY | Liveness probe initial delay (seconds) | 10 |
K8s_LIVENESS_PERIOD | Liveness probe period (seconds) | 20 |
K8s_LIVENESS_FAILURE_THRESHOLD | Failure threshold before restart | 80 |
DOCKER_USERNAME | DockerHub username | None |
DOCKER_PASSWORD | DockerHub password/token | None |
Package Version Pinning
Section titled “Package Version Pinning”Configure specific package versions for Kubernetes deployments:
[plugins.scale.kubernetes.plugin_versions]jaclang = "0.1.5" # Specific versionjac_scale = "latest" # Latest from PyPI (default)jac_client = "0.1.0" # Specific versionjac_byllm = "none" # Skip installation| Package | Description | Default |
|---|---|---|
jaclang | Core Jac language package | latest |
jac_scale | Scaling plugin | latest |
jac_client | Client/frontend support | latest |
jac_byllm | LLM integration (use “none” to skip) | latest |
Health Checks
Section titled “Health Checks”Health Endpoint
Section titled “Health Endpoint”Create a health walker:
walker health { can check with Root entry { report {"status": "healthy"}; }}Access at: POST /walker/health
Readiness Check
Section titled “Readiness Check”walker ready { can check with Root entry { db_ok = check_database(); cache_ok = check_cache();
if db_ok and cache_ok { report {"status": "ready"}; } else { report { "status": "not_ready", "db": db_ok, "cache": cache_ok }; } }}Builtins
Section titled “Builtins”Root Access
Section titled “Root Access”with entry { # Get all roots in memory/database roots = allroots();}Memory Commit
Section titled “Memory Commit”with entry { # Commit memory to database commit();}CLI Commands
Section titled “CLI Commands”| Command | Description |
|---|---|
jac start app.jac | Start local API server |
jac start app.jac --scale | Deploy to Kubernetes |
jac start app.jac --scale --build | Build image and deploy |
jac destroy app.jac | Remove Kubernetes deployment |
API Documentation
Section titled “API Documentation”When server is running:
- Swagger UI:
http://localhost:8000/docs - ReDoc:
http://localhost:8000/redoc - OpenAPI JSON:
http://localhost:8000/openapi.json
Prometheus Metrics
Section titled “Prometheus Metrics”jac-scale provides built-in Prometheus metrics collection for monitoring HTTP requests and walker execution. When enabled, a /metrics endpoint is automatically registered for Prometheus to scrape.
Configuration
Section titled “Configuration”Configure metrics in jac.toml:
[plugins.scale.metrics]enabled = true # Enable metrics collection and /metrics endpointendpoint = "/metrics" # Prometheus scrape endpoint pathnamespace = "myapp" # Metrics namespace prefixwalker_metrics = true # Enable per-walker execution timinghistogram_buckets = [0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1.0, 2.5, 5.0, 10.0]| Option | Type | Default | Description |
|---|---|---|---|
enabled | bool | false | Enable Prometheus metrics collection and /metrics endpoint |
endpoint | string | "/metrics" | Path for the Prometheus scrape endpoint |
namespace | string | "jac_scale" | Metrics namespace prefix |
walker_metrics | bool | false | Enable walker execution timing metrics |
histogram_buckets | list | [0.005, ..., 10.0] | Histogram bucket boundaries in seconds |
Note: If
namespaceis not set, it is derived from the Kubernetes namespace config (sanitized) or defaults to"jac_scale".
Exposed Metrics
Section titled “Exposed Metrics”| Metric | Type | Labels | Description |
|---|---|---|---|
{namespace}_http_requests_total | Counter | method, path, status_code | Total HTTP requests processed |
{namespace}_http_request_duration_seconds | Histogram | method, path | HTTP request latency in seconds |
{namespace}_http_requests_in_progress | Gauge | — | Concurrent HTTP requests |
{namespace}_walker_duration_seconds | Histogram | walker_name, success | Walker execution duration (only when walker_metrics=true) |
# Scrape metricscurl http://localhost:8000/metricsThe metrics endpoint is auto-registered as a GET route with OpenAPI tag “Monitoring”. Requests to the metrics endpoint itself are excluded from tracking.
Kubernetes Secrets
Section titled “Kubernetes Secrets”Manage sensitive environment variables securely in Kubernetes deployments using the [plugins.scale.secrets] section.
Configuration
Section titled “Configuration”[plugins.scale.secrets]OPENAI_API_KEY = "${OPENAI_API_KEY}"DATABASE_PASSWORD = "${DB_PASS}"STATIC_VALUE = "hardcoded-value"Values using ${ENV_VAR} syntax are resolved from the local environment at deploy time. The resolved key-value pairs are created as a proper Kubernetes Secret ({app_name}-secrets) and injected into pods via envFrom.secretRef.
How It Works
Section titled “How It Works”- At
jac start --scale, environment variable references (${...}) are resolved - A Kubernetes
OpaqueSecret named{app_name}-secretsis created (or updated if it already exists) - The Secret is attached to the deployment pod spec via
envFrom.secretRef - All keys become environment variables inside the container
- On
jac destroy, the Secret is automatically cleaned up
Example
Section titled “Example”# jac.toml[plugins.scale.secrets]OPENAI_API_KEY = "${OPENAI_API_KEY}"MONGO_PASSWORD = "${MONGO_PASSWORD}"JWT_SECRET = "${JWT_SECRET}"# Set local env vars, then deployexport OPENAI_API_KEY="sk-..."export MONGO_PASSWORD="secret123"export JWT_SECRET="my-jwt-key"
jac start app.jac --scale --buildThis eliminates the need for manual kubectl create secret commands after deployment.