KairosClient Reference
The KairosClient is your single entry point into the Ananke ecosystem. It wraps httpx for standard REST requests and websockets for real-time streaming, abstracting away the underlying tRPC envelope.
Initialization
Section titled “Initialization”from kairos import KairosClient
client = KairosClient( url="https://api.anankelabs.ai", # Optional if KAIROS_URL is set api_key="krs_...", # Optional if KAIROS_API_KEY is set timeout=30.0, # Request timeout in seconds engine_version="1.4.4", # Optional pinned engine version max_retries=3, # Max transient error retries retry_backoff=1.0, # Exponential backoff base delay)Reproducibility via Version Pinning
Section titled “Reproducibility via Version Pinning”For peer-reviewed research, it is absolutely critical that simulation traces are perfectly reproducible years later. KAIROS guarantees bit-for-bit reproducibility if you lock the engine_version.
# Pins your client to a specific release of the continuous physics engine.client = KairosClient(engine_version="1.4.4")If the requested engine version is no longer active on the server, the SDK raises an EngineVersionError detailing the valid available constraints.
Running Simulations
Section titled “Running Simulations”The highest-level method to execute a scenario is .run(). It handles creating the simulation and streaming the execution to completion.
client.run(...)
Section titled “client.run(...)”Executes a scenario eagerly into memory.
trace = client.run( scenario=my_scenario, ticks=1000, organization_id="org_id" # Optional, for billing/tracking purposes)client.stream_run(...)
Section titled “client.stream_run(...)”For massive simulations that would cause Out-Of-Memory (OOM) errors if eagerly loaded, use the iterator.
# Yields TraceStep objects iteratively over a WebSocketfor step in client.stream_run(scenario, ticks=100_000): if step.stability < 0.1: print(f"Danger at tick {step.t}")Asynchronous Execution
Section titled “Asynchronous Execution”For high-throughput evaluations (e.g., Monte Carlo sampling of different capability jumps), the client provides a full asyncio interface. All async methods are prefixed with a.
import asynciofrom kairos import KairosClientfrom kairos.domains.ai_safety import AISafetyScenario, AISafetyEventType
async def capability_sweep(): """Sweep over capability values to find the critical destabilization threshold.""" client = KairosClient()
async def run_one(capability): scenario = ( AISafetyScenario(f"sweep_{capability}", seed=capability) .add_model( name="model", capability_index=capability, alignment_score=70, guardrail_coverage=60, ) .add_event(100, AISafetyEventType.CAPABILITY_JUMP, target="model", magnitude=0.3) ) trace = await client.arun(scenario, ticks=500) return { "capability": capability, "final_phase": trace.final_phase(), "mean_stability": trace.mean_stability(), "basin_losses": len(trace.basin_losses()), }
# Run 50 simulations concurrently tasks = [run_one(cap) for cap in range(100, 1001, 18)] results = await asyncio.gather(*tasks)
for r in results: print(f" cap={r['capability']:>4} phase={r['final_phase']:<10} " f"stability={r['mean_stability']:.4f} losses={r['basin_losses']}")
asyncio.run(capability_sweep())For a full version with DataFrame collection and threshold analysis, see the Monte Carlo Parameter Sweep use case.
Error Handling & Resiliency
Section titled “Error Handling & Resiliency”The SDK is highly resilient, built to survive integration into automated ML evaluation harness pipelines. It internally catches and retries 429 Too Many Requests, 502 Bad Gateway, and 503 Service Unavailable.
It avoids mutating endpoints twice by disabling connection-error retries for simulation.create by default.
Exceptions
Section titled “Exceptions”Check kairos.errors for the exception hierarchy:
AuthenticationError: Invalid API keys.RateLimitError: Standard 429 backoff failures (includesretry_after).SimulationError: Core engine calculation faults.ValidationError: Pre-flight client-side scenario rejection.