curl --request POST \
--url https://odyssey.asteroid.ai/agents/v2/environments \
--header 'Content-Type: application/json' \
--header 'X-Api-Key: <api-key>' \
--data '
{
"agentId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"agentProfileId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"organizationId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"profileId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"source": {
"kind": "workflow",
"workflowId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
},
"workflowId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
'import requests
url = "https://odyssey.asteroid.ai/agents/v2/environments"
payload = {
"agentId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"agentProfileId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"organizationId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"profileId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"source": {
"kind": "workflow",
"workflowId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
},
"workflowId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
headers = {
"X-Api-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-Api-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
agentId: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
agentProfileId: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
organizationId: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
profileId: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
source: {kind: 'workflow', workflowId: '3c90c3cc-0d44-4b50-8888-8dd25736052a'},
workflowId: '3c90c3cc-0d44-4b50-8888-8dd25736052a'
})
};
fetch('https://odyssey.asteroid.ai/agents/v2/environments', 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://odyssey.asteroid.ai/agents/v2/environments",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'agentId' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'agentProfileId' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'organizationId' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'profileId' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'source' => [
'kind' => 'workflow',
'workflowId' => '3c90c3cc-0d44-4b50-8888-8dd25736052a'
],
'workflowId' => '3c90c3cc-0d44-4b50-8888-8dd25736052a'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Api-Key: <api-key>"
],
]);
$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://odyssey.asteroid.ai/agents/v2/environments"
payload := strings.NewReader("{\n \"agentId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"agentProfileId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"organizationId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"profileId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"source\": {\n \"kind\": \"workflow\",\n \"workflowId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n },\n \"workflowId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Api-Key", "<api-key>")
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.post("https://odyssey.asteroid.ai/agents/v2/environments")
.header("X-Api-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"agentId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"agentProfileId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"organizationId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"profileId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"source\": {\n \"kind\": \"workflow\",\n \"workflowId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n },\n \"workflowId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://odyssey.asteroid.ai/agents/v2/environments")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Api-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"agentId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"agentProfileId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"organizationId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"profileId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"source\": {\n \"kind\": \"workflow\",\n \"workflowId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n },\n \"workflowId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n}"
response = http.request(request)
puts response.read_body{
"connection": {
"cdpUrl": "<string>"
},
"createdAt": "2023-11-07T05:31:56Z",
"environmentType": "browser",
"expiresAt": "2023-11-07T05:31:56Z",
"hasRecording": true,
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"organizationId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"owner": {
"agentId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"executionId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "execution",
"workflowId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
},
"state": {
"environmentType": "browser",
"hasRecording": true,
"height": 123,
"provider": "<string>",
"width": 123,
"browserIp": "<string>",
"liveViewUrl": "<string>",
"providerConfig": {
"type": "anchor",
"sessionId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"sessionUrl": "<string>"
},
"recordingStartedAt": "2023-11-07T05:31:56Z",
"recordingUrl": "<string>"
},
"status": "requested",
"agentProfileId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"osType": "linux",
"profileId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"readyAt": "2023-11-07T05:31:56Z",
"stoppedAt": "2023-11-07T05:31:56Z"
}{
"code": 400,
"message": "<string>",
"detail": "<string>",
"errors": [
{
"detail": "<string>",
"parameter": "<string>"
}
],
"instance": "<string>",
"status": 123,
"title": "<string>",
"type": "<string>"
}{
"code": 401,
"message": "<string>",
"detail": "<string>",
"instance": "<string>",
"status": 123,
"title": "<string>",
"type": "<string>"
}{
"code": 403,
"message": "<string>",
"detail": "<string>",
"instance": "<string>",
"status": 123,
"title": "<string>",
"type": "<string>"
}{
"code": 404,
"message": "<string>",
"detail": "<string>",
"instance": "<string>",
"status": 123,
"title": "<string>",
"type": "<string>"
}{
"code": 429,
"message": "<string>",
"detail": "<string>",
"instance": "<string>",
"status": 123,
"title": "<string>",
"type": "<string>"
}{
"code": 500,
"message": "<string>",
"detail": "<string>",
"instance": "<string>",
"status": 123,
"title": "<string>",
"type": "<string>"
}Start environment
Start an environment. Blocks until it is ready (or the provider fails) and returns the environment together with its connection details, so a caller boots in one round trip. The organisation in the body is the scope; the agent, when given, is a binding the server verifies belongs to it.
curl --request POST \
--url https://odyssey.asteroid.ai/agents/v2/environments \
--header 'Content-Type: application/json' \
--header 'X-Api-Key: <api-key>' \
--data '
{
"agentId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"agentProfileId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"organizationId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"profileId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"source": {
"kind": "workflow",
"workflowId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
},
"workflowId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
'import requests
url = "https://odyssey.asteroid.ai/agents/v2/environments"
payload = {
"agentId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"agentProfileId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"organizationId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"profileId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"source": {
"kind": "workflow",
"workflowId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
},
"workflowId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
headers = {
"X-Api-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-Api-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
agentId: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
agentProfileId: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
organizationId: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
profileId: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
source: {kind: 'workflow', workflowId: '3c90c3cc-0d44-4b50-8888-8dd25736052a'},
workflowId: '3c90c3cc-0d44-4b50-8888-8dd25736052a'
})
};
fetch('https://odyssey.asteroid.ai/agents/v2/environments', 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://odyssey.asteroid.ai/agents/v2/environments",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'agentId' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'agentProfileId' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'organizationId' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'profileId' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'source' => [
'kind' => 'workflow',
'workflowId' => '3c90c3cc-0d44-4b50-8888-8dd25736052a'
],
'workflowId' => '3c90c3cc-0d44-4b50-8888-8dd25736052a'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Api-Key: <api-key>"
],
]);
$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://odyssey.asteroid.ai/agents/v2/environments"
payload := strings.NewReader("{\n \"agentId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"agentProfileId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"organizationId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"profileId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"source\": {\n \"kind\": \"workflow\",\n \"workflowId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n },\n \"workflowId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Api-Key", "<api-key>")
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.post("https://odyssey.asteroid.ai/agents/v2/environments")
.header("X-Api-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"agentId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"agentProfileId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"organizationId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"profileId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"source\": {\n \"kind\": \"workflow\",\n \"workflowId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n },\n \"workflowId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://odyssey.asteroid.ai/agents/v2/environments")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Api-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"agentId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"agentProfileId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"organizationId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"profileId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"source\": {\n \"kind\": \"workflow\",\n \"workflowId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n },\n \"workflowId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n}"
response = http.request(request)
puts response.read_body{
"connection": {
"cdpUrl": "<string>"
},
"createdAt": "2023-11-07T05:31:56Z",
"environmentType": "browser",
"expiresAt": "2023-11-07T05:31:56Z",
"hasRecording": true,
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"organizationId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"owner": {
"agentId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"executionId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "execution",
"workflowId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
},
"state": {
"environmentType": "browser",
"hasRecording": true,
"height": 123,
"provider": "<string>",
"width": 123,
"browserIp": "<string>",
"liveViewUrl": "<string>",
"providerConfig": {
"type": "anchor",
"sessionId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"sessionUrl": "<string>"
},
"recordingStartedAt": "2023-11-07T05:31:56Z",
"recordingUrl": "<string>"
},
"status": "requested",
"agentProfileId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"osType": "linux",
"profileId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"readyAt": "2023-11-07T05:31:56Z",
"stoppedAt": "2023-11-07T05:31:56Z"
}{
"code": 400,
"message": "<string>",
"detail": "<string>",
"errors": [
{
"detail": "<string>",
"parameter": "<string>"
}
],
"instance": "<string>",
"status": 123,
"title": "<string>",
"type": "<string>"
}{
"code": 401,
"message": "<string>",
"detail": "<string>",
"instance": "<string>",
"status": 123,
"title": "<string>",
"type": "<string>"
}{
"code": 403,
"message": "<string>",
"detail": "<string>",
"instance": "<string>",
"status": 123,
"title": "<string>",
"type": "<string>"
}{
"code": 404,
"message": "<string>",
"detail": "<string>",
"instance": "<string>",
"status": 123,
"title": "<string>",
"type": "<string>"
}{
"code": 429,
"message": "<string>",
"detail": "<string>",
"instance": "<string>",
"status": 123,
"title": "<string>",
"type": "<string>"
}{
"code": 500,
"message": "<string>",
"detail": "<string>",
"instance": "<string>",
"status": 123,
"title": "<string>",
"type": "<string>"
}Authorizations
Body
Request to start an environment. An environment belongs to an organisation; the agent is an optional binding carried in the body, not a path segment. With an agent, the environment is stamped external-owned and the agent's workflow/profile drive provisioning; without one, it is organization-owned and provisions from the explicit spec alone.
Deprecated: use workflowId. The agent to bind the environment to.
Deprecated: use profileId. Optional agent profile to attach.
The organisation the environment belongs to. With an agent, the server verifies the agent belongs to it, so a mismatched binding fails instead of stamping the wrong organisation. Defaults to the one organization the caller acts in, such as an API key's. Required when the caller belongs to several.
Optional login profile to attach. The profile id is stamped onto the env row for the session's lifetime, so later reads resolve against the stamped profile rather than the workflow's current one. Its decrypted credentials come back on the response's connection only for service-to-service callers — they are never returned to an API key or a browser. Do not set together with agentProfileId.
Where the environment spec comes from. Omit for the server default (a browser env at the computer-use resolution). The workflow arm needs a workflow to resolve against, so it requires workflowId.
- Option 1
- Option 2
Show child attributes
Show child attributes
The workflow to bind the environment to. Gates access to that workflow. Omit for an organization-owned environment with no workflow binding. Do not set together with agentId.
Response
The request has succeeded.
A single environment: what it is, its provider state, and how to drive it. state is the same shape the execution endpoint returns, so the LiveView/OsLiveView components render either without branching.
How to connect to it.
Show child attributes
Show child attributes
When the environment row was created.
Browser or OS.
browser, os When the reaper will tear the environment down if no graceful Stop arrives first.
Whether a playable recording has been persisted (GCS object or provider URL). The playable URL itself is minted on the by-id read.
Environment identifier.
The organisation the environment belongs to.
Who the environment belongs to, and the identity that owner carries.
- Option 1
- Option 2
- Option 3
- Option 4
- Option 5
Show child attributes
Show child attributes
Environment state (browser or OS): live-view URL, viewport, provider config and a freshly-minted recording URL when one exists.
- Option 1
- Option 2
Show child attributes
Show child attributes
Current status, terminal states included. Lists exclude terminal environments unless includeTerminal is set.
requested, provisioning, ready, stopping, stopped, failed, dead Deprecated: use profileId. Profile snapshot the environment was booted against, if any.
Operating system for OS environments. Absent for browser environments; linux when an OS environment predates explicit osType storage.
linux, windows Profile snapshot the environment was booted against, if any.
When the environment first became ready, if it reached that state.
When the environment reached a terminal state. Set after Stop runs.

