curl --request PUT \
--url https://api.runaether.dev/agent/inference \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"runs_on": "aether"
}
'import requests
url = "https://api.runaether.dev/agent/inference"
payload = { "runs_on": "aether" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({runs_on: 'aether'})
};
fetch('https://api.runaether.dev/agent/inference', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.runaether.dev/agent/inference",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'runs_on' => 'aether'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.runaether.dev/agent/inference"
payload := strings.NewReader("{\n \"runs_on\": \"aether\"\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.put("https://api.runaether.dev/agent/inference")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"runs_on\": \"aether\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.runaether.dev/agent/inference")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"runs_on\": \"aether\"\n}"
response = http.request(request)
puts response.read_body{
"browser_tools": true,
"created_at": "2023-11-07T05:31:56Z",
"cron_model": "claude-fable-5-1",
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"last_used_at": "2023-11-07T05:31:56Z",
"model": "claude-fable-5-1",
"runs_on": "aether",
"state": "provisioning",
"connection_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"default_project_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}{
"code": "account_deleting",
"error": "<string>",
"errors": [
{
"location": "<string>",
"message": "<string>",
"value": "<unknown>"
}
]
}{
"code": "account_deleting",
"error": "<string>",
"errors": [
{
"location": "<string>",
"message": "<string>",
"value": "<unknown>"
}
]
}{
"code": "org_membership_required",
"error": "<string>"
}{
"code": "account_deleting",
"error": "<string>",
"errors": [
{
"location": "<string>",
"message": "<string>",
"value": "<unknown>"
}
]
}{
"code": "account_deleting",
"error": "<string>",
"errors": [
{
"location": "<string>",
"message": "<string>",
"value": "<unknown>"
}
]
}{
"code": "account_deleting",
"error": "<string>",
"errors": [
{
"location": "<string>",
"message": "<string>",
"value": "<unknown>"
}
]
}{
"code": "account_deleting",
"error": "<string>",
"errors": [
{
"location": "<string>",
"message": "<string>",
"value": "<unknown>"
}
]
}Choose what your agent runs on and its model
Points your agent at Aether inference or one of your connections, and sets the model it converses on; both are required. aether runs on Aether inference, paid from your balance and held to the daily cap, and serves Claude models; stored runs on the connection connection_id names: a Claude plan or an Anthropic API key for Claude models, an OpenAI API key for GPT models, none paid from your balance or held to the cap. Scheduled jobs use Claude Haiku 5.5 or GPT-6 Luna, from the modelโs family. A changed selection restarts a running agent; the same selection issues nothing. 422 for a write outside the two shapes or an unknown value, and 400 model_not_on_aether_inference for a GPT model on Aether inference. 404 connection_not_found for a connection you do not hold. 409 connection_kind_not_runnable for a connection your agent cannot run on (a ChatGPT plan, an OpenCode auth file, an OpenRouter API key), and 409 connection_not_of_agent_family for a connection serving the other family than the modelโs. 409 agent_credential_unreadable while the connection cannot be read; 409 agent_host_illegal_transition while going to sleep or pausing.
curl --request PUT \
--url https://api.runaether.dev/agent/inference \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"runs_on": "aether"
}
'import requests
url = "https://api.runaether.dev/agent/inference"
payload = { "runs_on": "aether" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({runs_on: 'aether'})
};
fetch('https://api.runaether.dev/agent/inference', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.runaether.dev/agent/inference",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'runs_on' => 'aether'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.runaether.dev/agent/inference"
payload := strings.NewReader("{\n \"runs_on\": \"aether\"\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.put("https://api.runaether.dev/agent/inference")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"runs_on\": \"aether\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.runaether.dev/agent/inference")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"runs_on\": \"aether\"\n}"
response = http.request(request)
puts response.read_body{
"browser_tools": true,
"created_at": "2023-11-07T05:31:56Z",
"cron_model": "claude-fable-5-1",
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"last_used_at": "2023-11-07T05:31:56Z",
"model": "claude-fable-5-1",
"runs_on": "aether",
"state": "provisioning",
"connection_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"default_project_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}{
"code": "account_deleting",
"error": "<string>",
"errors": [
{
"location": "<string>",
"message": "<string>",
"value": "<unknown>"
}
]
}{
"code": "account_deleting",
"error": "<string>",
"errors": [
{
"location": "<string>",
"message": "<string>",
"value": "<unknown>"
}
]
}{
"code": "org_membership_required",
"error": "<string>"
}{
"code": "account_deleting",
"error": "<string>",
"errors": [
{
"location": "<string>",
"message": "<string>",
"value": "<unknown>"
}
]
}{
"code": "account_deleting",
"error": "<string>",
"errors": [
{
"location": "<string>",
"message": "<string>",
"value": "<unknown>"
}
]
}{
"code": "account_deleting",
"error": "<string>",
"errors": [
{
"location": "<string>",
"message": "<string>",
"value": "<unknown>"
}
]
}{
"code": "account_deleting",
"error": "<string>",
"errors": [
{
"location": "<string>",
"message": "<string>",
"value": "<unknown>"
}
]
}Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
- Option 1
- Option 2
The model your agent converses on, in the family what it runs on serves: Claude models on Aether inference, a Claude plan or an Anthropic API key; GPT models on an OpenAI API key. Scheduled jobs run on the family's Claude Haiku 5.5 or GPT-6 Luna.
claude-fable-5-1, claude-opus-5-5, claude-sonnet-5-5, claude-haiku-5-5, gpt-6.1-sol, gpt-6-sol, gpt-6-astra, gpt-6-luna Aether inference, paid from your balance and held to the daily cap.
aether Response
OK
Whether your agent may drive a browser. Off by default; a change applies when Hermes next starts, which a running agent does at once.
The model your agent's scheduled jobs run on, unless a job names another.
claude-fable-5-1, claude-opus-5-5, claude-sonnet-5-5, claude-haiku-5-5, gpt-6.1-sol, gpt-6-sol, gpt-6-astra, gpt-6-luna When your agent was created or resumed, was sent a message, or last worked. Thirty days unused pauses it.
The model your agent converses on.
claude-fable-5-1, claude-opus-5-5, claude-sonnet-5-5, claude-haiku-5-5, gpt-6.1-sol, gpt-6-sol, gpt-6-astra, gpt-6-luna What your agent runs on: aether, Aether inference, paid from your balance and held to the daily cap; stored, your connection connection_id names, paid by its plan or key, neither from your balance nor held to the cap.
aether, stored The host's lifecycle state. running: Hermes takes messages now; suspending and idle: asleep, woken by the next message; waking, resuming: coming up for a message; provisioning and booting: being created; updating: moving onto a new image; pausing and paused: backed up after thirty days unused, or paused by you, and resumed by you (a message from the web does not resume it); lost: its machine is gone and only deleting it helps; destroying: being deleted.
provisioning, booting, running, suspending, idle, waking, updating, pausing, paused, resuming, lost, destroying, destroyed The connection your agent runs on; present exactly when runs_on is stored.
The project a task your agent starts runs on when it names no repository. Without it such a task is refused.