curl --request POST \
--url https://odyssey.asteroid.ai/agents/v2/agents/{agentId}/environments \
--header 'Content-Type: application/json' \
--header 'X-Asteroid-Agents-Api-Key: <api-key>' \
--data '
{
"agentProfileId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"source": {
"kind": "workflow",
"workflowId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
}
'import requests
url = "https://odyssey.asteroid.ai/agents/v2/agents/{agentId}/environments"
payload = {
"agentProfileId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"source": {
"kind": "workflow",
"workflowId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
}
headers = {
"X-Asteroid-Agents-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-Asteroid-Agents-Api-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
agentProfileId: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
source: {kind: 'workflow', workflowId: '3c90c3cc-0d44-4b50-8888-8dd25736052a'}
})
};
fetch('https://odyssey.asteroid.ai/agents/v2/agents/{agentId}/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/agents/{agentId}/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([
'agentProfileId' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'source' => [
'kind' => 'workflow',
'workflowId' => '3c90c3cc-0d44-4b50-8888-8dd25736052a'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Asteroid-Agents-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/agents/{agentId}/environments"
payload := strings.NewReader("{\n \"agentProfileId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"source\": {\n \"kind\": \"workflow\",\n \"workflowId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Asteroid-Agents-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/agents/{agentId}/environments")
.header("X-Asteroid-Agents-Api-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"agentProfileId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"source\": {\n \"kind\": \"workflow\",\n \"workflowId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://odyssey.asteroid.ai/agents/v2/agents/{agentId}/environments")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Asteroid-Agents-Api-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"agentProfileId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"source\": {\n \"kind\": \"workflow\",\n \"workflowId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n }\n}"
response = http.request(request)
puts response.read_body{
"environmentId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"cdpUrl": "<string>",
"credentials": {},
"cua": {
"sessionId": "<string>",
"anchorBaseUrl": "<string>",
"daytonaToolboxBaseUrl": "<string>"
}
}{
"code": 400,
"message": "<string>"
}{
"code": 401,
"message": "<string>"
}{
"code": 403,
"message": "<string>"
}{
"code": 404,
"message": "<string>"
}{
"code": 500,
"message": "<string>"
}Start live environment (external)
Start a standalone live environment for the agent. Returns the (proxied) CDP URL or Daytona connection details once the env is ready; optionally returns decrypted credentials when agentProfileId is supplied. The env is stamped with an external owner and reaped on its session TTL.
curl --request POST \
--url https://odyssey.asteroid.ai/agents/v2/agents/{agentId}/environments \
--header 'Content-Type: application/json' \
--header 'X-Asteroid-Agents-Api-Key: <api-key>' \
--data '
{
"agentProfileId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"source": {
"kind": "workflow",
"workflowId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
}
'import requests
url = "https://odyssey.asteroid.ai/agents/v2/agents/{agentId}/environments"
payload = {
"agentProfileId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"source": {
"kind": "workflow",
"workflowId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
}
headers = {
"X-Asteroid-Agents-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-Asteroid-Agents-Api-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
agentProfileId: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
source: {kind: 'workflow', workflowId: '3c90c3cc-0d44-4b50-8888-8dd25736052a'}
})
};
fetch('https://odyssey.asteroid.ai/agents/v2/agents/{agentId}/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/agents/{agentId}/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([
'agentProfileId' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'source' => [
'kind' => 'workflow',
'workflowId' => '3c90c3cc-0d44-4b50-8888-8dd25736052a'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Asteroid-Agents-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/agents/{agentId}/environments"
payload := strings.NewReader("{\n \"agentProfileId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"source\": {\n \"kind\": \"workflow\",\n \"workflowId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Asteroid-Agents-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/agents/{agentId}/environments")
.header("X-Asteroid-Agents-Api-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"agentProfileId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"source\": {\n \"kind\": \"workflow\",\n \"workflowId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://odyssey.asteroid.ai/agents/v2/agents/{agentId}/environments")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Asteroid-Agents-Api-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"agentProfileId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"source\": {\n \"kind\": \"workflow\",\n \"workflowId\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n }\n}"
response = http.request(request)
puts response.read_body{
"environmentId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"cdpUrl": "<string>",
"credentials": {},
"cua": {
"sessionId": "<string>",
"anchorBaseUrl": "<string>",
"daytonaToolboxBaseUrl": "<string>"
}
}{
"code": 400,
"message": "<string>"
}{
"code": 401,
"message": "<string>"
}{
"code": 403,
"message": "<string>"
}{
"code": 404,
"message": "<string>"
}{
"code": 500,
"message": "<string>"
}Authorizations
Path Parameters
The agent the environment belongs to.
Body
Request to start a standalone live environment via the external (agents-API-key) API. Unlike the internal StartEnvironmentRequest there is no owner field — the env is stamped with an external owner for the path agent, and takes the agent's own organisation (not the caller's). Provisioning reads no workflow unless a workflow source is passed.
Optional agent profile to attach. When supplied, the profile's decrypted credentials are returned as the ##NAME## placeholder map and the profile id is stamped onto the env row for the session's lifetime.
Where the environment spec comes from. Omit for the server default (a browser env at the computer-use resolution).
- Option 1
- Option 2
Show child attributes
Show child attributes
Response
The request has succeeded.
Response from starting a live environment. Shape mirrors the legacy POST /agents/{id}/workflows/{wid}/live-environment response so callers can share rendering code; environmentId is the new wire handle astro stores for stop / attach.
The newly-provisioned environment.
The environment type the workflow is configured for.
browser, os Chrome DevTools Protocol websocket URL. Present only for browser environments.
Decrypted credential placeholders for the attached agent profile, keyed by ##NAME## placeholder. Present only when agentProfileId was supplied and the profile has credentials.
Provider-specific CUA connection details. Present for Anchor browsers and Daytona OS environments.
Show child attributes
Show child attributes

