SDKs
Official client libraries for the Hot API, released in lockstep versions:
| Language | Package | Source | API Reference |
|---|---|---|---|
| JavaScript / TypeScript | @hot-dev/sdk (npm) | hot-dev/hot-js | Package README |
| Python | hot-dev (PyPI) | hot-dev/hot-python | README |
| Go | github.com/hot-dev/hot-go | hot-dev/hot-go | pkg.go.dev |
| Rust | hot-dev (crates.io) | hot-dev/hot-rust | docs.rs |
| Java | dev.hot:hot-sdk (Maven Central) | hot-dev/hot-java | javadoc.io |
Every SDK covers the full API v1 surface: the twelve resources (Endpoints), SSE run-stream subscriptions with automatic reconnection across the API's 5-minute stream timeout, structured API errors, and escape hatches for endpoints that do not yet have a helper.
Authenticated clients should run server-side. Browser apps and untrusted
clients should call your own backend route instead of exposing a Hot API key
(the JavaScript SDK ships a @hot-dev/sdk/proxy helper for this).
Install
JavaScript
npm install @hot-dev/sdk
Requires Node 20+. ESM-only.
Python
pip install hot-dev
Python 3.10+. Import as hot.
Go
go get github.com/hot-dev/hot-go
Go 1.23+. Zero dependencies.
Rust
cargo add hot-dev tokio --features tokio/full
cargo add futures-util serde_json
Async on tokio; TLS via rustls. Import as hot_dev.
Java
// Gradle
implementation("dev.hot:hot-sdk:1.1.3")
<!-- Maven -->
<dependency>
<groupId>dev.hot</groupId>
<artifactId>hot-sdk</artifactId>
<version>1.1.3</version>
</dependency>
Java 17+. Jackson is the only runtime dependency.
Quick Start
Publish an event and stream its run to completion. base_url defaults to
https://api.hot.dev; for local development with hot dev, point it at
http://localhost:4681.
JavaScript
import { HotClient } from "@hot-dev/sdk";
const hot = new HotClient({ token: process.env.HOT_API_KEY });
for await (const event of hot.streams.subscribeWithEvent({
event_type: "team-agent:ask",
event_data: { question: "what is blocking launch?" },
})) {
if (event.type === "stream:data") console.log(event.data_type, event.payload);
if (event.type === "run:stop") {
console.log(event.run?.result);
break;
}
}
Python
import os
from hot import HotClient
hot = HotClient(token=os.environ["HOT_API_KEY"])
for event in hot.streams.subscribe_with_event(
{"event_type": "team-agent:ask", "event_data": {"question": "what is blocking launch?"}}
):
if event["type"] == "stream:data":
print(event["data_type"], event.get("payload"))
if event["type"] == "run:stop":
print(event.get("run", {}).get("result"))
break
Go
client, err := hot.NewClient(hot.Config{Token: os.Getenv("HOT_API_KEY")})
if err != nil {
log.Fatal(err)
}
ctx := context.Background()
for event, err := range client.Streams.SubscribeWithEvent(ctx, map[string]any{
"event_type": "team-agent:ask",
"event_data": map[string]any{"question": "what is blocking launch?"},
}, nil) {
if err != nil {
log.Fatal(err)
}
if event.Type() == "stream:data" {
fmt.Println(event["data_type"], event["payload"])
}
if event.Type() == "run:stop" {
fmt.Println(event.Run()["result"])
break
}
}
Rust
use futures_util::StreamExt;
use hot_dev::{HotClient, StreamEventExt, SubscribeWithEventOptions};
use serde_json::json;
let client = HotClient::builder(std::env::var("HOT_API_KEY").unwrap()).build();
let mut events = client.streams().subscribe_with_event(
json!({
"event_type": "team-agent:ask",
"event_data": { "question": "what is blocking launch?" },
}),
SubscribeWithEventOptions::default(),
);
while let Some(event) = events.next().await {
let event = event?;
if event.event_type() == "stream:data" {
println!("{:?} {:?}", event.get("data_type"), event.get("payload"));
}
if event.event_type() == "run:stop" {
println!("{:?}", event.run().and_then(|run| run.get("result")));
break;
}
}
Java
HotClient client = HotClient.builder(System.getenv("HOT_API_KEY")).build();
try (StreamEvents events = client.streams().subscribeWithEvent(Map.of(
"event_type", "team-agent:ask",
"event_data", Map.of("question", "what is blocking launch?")))) {
while (events.hasNext()) {
Map<String, Object> event = events.next();
if (StreamEvents.typeOf(event).equals("stream:data")) {
System.out.println(event.get("data_type") + " " + event.get("payload"));
}
if (StreamEvents.typeOf(event).equals("run:stop")) {
System.out.println(StreamEvents.runOf(event).get("result"));
break;
}
}
}
Call a Hot Function
Every SDK wraps the publish-and-wait flow for hot:call events:
JavaScript
const result = await hot.events.callHot("::myapp::math/add-nums", [2, 3]);
// result === 5
Python
result = hot.events.call_hot("::myapp::math/add-nums", [2, 3])
# result == 5
Go
result, err := client.Events.CallHot(ctx, "::myapp::math/add-nums", []any{2, 3}, nil)
// result == float64(5)
Rust
let result = client
.events()
.call_hot("::myapp::math/add-nums", vec![json!(2), json!(3)], CallOptions::default())
.await?;
// result == json!(5)
Java
Object result = client.events().callHot("::myapp::math/add-nums", List.of(2, 3));
// result equals 5
Errors
Non-2xx responses surface as structured errors with status_code, code,
request_id, and retry_after:
JavaScript
import { HotApiError } from "@hot-dev/sdk";
try {
await hot.projects.get("missing-project");
} catch (error) {
if (error instanceof HotApiError) {
console.log(error.status, error.code, error.requestId, error.retryAfter);
}
}
Python
from hot import HotApiError
try:
hot.projects.get("missing-project")
except HotApiError as error:
print(error.status_code, error.code, error.request_id, error.retry_after)
Go
_, err := client.Projects.Get(ctx, "missing-project")
var apiErr *hot.APIError
if errors.As(err, &apiErr) {
fmt.Println(apiErr.StatusCode, apiErr.Code, apiErr.RequestID, apiErr.RetryAfter)
}
Rust
match client.projects().get("missing-project").await {
Err(hot_dev::Error::Api(error)) => {
println!("{} {:?} {:?} {:?}", error.status_code, error.code, error.request_id, error.retry_after);
}
other => drop(other),
}
Java
try {
client.projects().get("missing-project");
} catch (HotApiException error) {
System.out.println(error.statusCode() + " " + error.code() + " "
+ error.requestId() + " " + error.retryAfter());
}
Shared Behavior
All five SDKs follow the same conventions:
- Wire-format payloads. Request and response payloads use the API wire
format (
event_type,event_data,stream_id). SDK-only options use each language's idiom (baseUrl,base_url,BaseURL). No SDK ever transforms user-owned payloads such asevent_data. - Retries. JSON requests retry automatically (at most twice) when the API
responds 429 with a
retry_after. Streaming and raw requests never retry. - Streaming reconnection.
subscribeWithEventresubscribes across the API's 5-minute SSE timeout, dedupes replayedrun:startand terminal events byrun_id, and ends after the first terminalrun:*event. Use the plainsubscribewhen your app expects multiple independent runs on one stream. - Identification. Each SDK sends
User-Agent: hot-sdk-<lang>/<version>. - Escape hatches. A
request(...)method (plus a raw-response variant) covers endpoints that do not yet have a resource helper.
Building chat or agent frontends? The JavaScript SDK additionally ships
agent, webhook, and BFF proxy helpers as subpath exports
(@hot-dev/sdk/agent, /webhook, /proxy); the other SDKs intentionally
cover the core API.