curl --request PATCH \
--url https://odyssey.asteroid.ai/agents/v2/agents/{agentId}/workflow-head/files \
--header 'Content-Type: application/json' \
--header 'X-Asteroid-Agents-Api-Key: <api-key>' \
--data '
{
"baseRev": 123,
"deletes": [
"<string>"
],
"writes": [
{
"contentBase64": "<string>",
"path": "<string>"
}
]
}
'import requests
url = "https://odyssey.asteroid.ai/agents/v2/agents/{agentId}/workflow-head/files"
payload = {
"baseRev": 123,
"deletes": ["<string>"],
"writes": [
{
"contentBase64": "<string>",
"path": "<string>"
}
]
}
headers = {
"X-Asteroid-Agents-Api-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {'X-Asteroid-Agents-Api-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
baseRev: 123,
deletes: ['<string>'],
writes: [{contentBase64: '<string>', path: '<string>'}]
})
};
fetch('https://odyssey.asteroid.ai/agents/v2/agents/{agentId}/workflow-head/files', 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}/workflow-head/files",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'baseRev' => 123,
'deletes' => [
'<string>'
],
'writes' => [
[
'contentBase64' => '<string>',
'path' => '<string>'
]
]
]),
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}/workflow-head/files"
payload := strings.NewReader("{\n \"baseRev\": 123,\n \"deletes\": [\n \"<string>\"\n ],\n \"writes\": [\n {\n \"contentBase64\": \"<string>\",\n \"path\": \"<string>\"\n }\n ]\n}")
req, _ := http.NewRequest("PATCH", 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.patch("https://odyssey.asteroid.ai/agents/v2/agents/{agentId}/workflow-head/files")
.header("X-Asteroid-Agents-Api-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"baseRev\": 123,\n \"deletes\": [\n \"<string>\"\n ],\n \"writes\": [\n {\n \"contentBase64\": \"<string>\",\n \"path\": \"<string>\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://odyssey.asteroid.ai/agents/v2/agents/{agentId}/workflow-head/files")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["X-Asteroid-Agents-Api-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"baseRev\": 123,\n \"deletes\": [\n \"<string>\"\n ],\n \"writes\": [\n {\n \"contentBase64\": \"<string>\",\n \"path\": \"<string>\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"agentId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"createdAt": "2023-11-07T05:31:56Z",
"files": [
{
"createdAt": "2023-11-07T05:31:56Z",
"fileName": "<string>",
"filePath": "<string>",
"fileSize": 123,
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"updatedAt": "2023-11-07T05:31:56Z",
"checksum": "<string>",
"mimeType": "<string>"
}
],
"graph": {
"nodes": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"properties": {
"type": "start"
},
"description": "<string>",
"position": {
"x": 123,
"y": 123
}
}
],
"sticky_notes": [
{
"content": "<string>",
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"color": "<string>",
"position": {
"x": 123,
"y": 123
},
"size": {
"height": 123,
"width": 123
}
}
],
"transitions": [
{
"from": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"properties": {
"type": "iris"
},
"require_confirmation": true,
"to": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"description": "<string>",
"schema": {}
}
]
},
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"inputs": [
{
"name": "<string>",
"required": true,
"schema": {},
"defaultValue": "<unknown>",
"description": "<string>"
}
],
"isPublished": true,
"rev": 123,
"rules": "<string>",
"settings": {
"max_timeout_mins": 123,
"viewport_height": 123,
"viewport_width": 123,
"new_agent_loop": true
},
"version": 123,
"author": "<string>",
"environmentTemplate": {
"config": {}
},
"parentId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}{
"code": 400,
"message": "<string>"
}{
"code": 401,
"message": "<string>"
}{
"code": 403,
"message": "<string>"
}{
"code": 404,
"message": "<string>"
}{
"code": 409,
"message": "<string>"
}{
"code": 500,
"message": "<string>"
}Patch workflow head files
Patch the editable headβs file representation in place: apply file writes/deletes, re-derive the structured workflow, and persist it. Structural files re-derive the graph; agent files go to the blob store. Guarded by baseRev for optimistic concurrency. When the head is frozen (published or executed) the edit forks a fresh version behind the scenes.
curl --request PATCH \
--url https://odyssey.asteroid.ai/agents/v2/agents/{agentId}/workflow-head/files \
--header 'Content-Type: application/json' \
--header 'X-Asteroid-Agents-Api-Key: <api-key>' \
--data '
{
"baseRev": 123,
"deletes": [
"<string>"
],
"writes": [
{
"contentBase64": "<string>",
"path": "<string>"
}
]
}
'import requests
url = "https://odyssey.asteroid.ai/agents/v2/agents/{agentId}/workflow-head/files"
payload = {
"baseRev": 123,
"deletes": ["<string>"],
"writes": [
{
"contentBase64": "<string>",
"path": "<string>"
}
]
}
headers = {
"X-Asteroid-Agents-Api-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {'X-Asteroid-Agents-Api-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
baseRev: 123,
deletes: ['<string>'],
writes: [{contentBase64: '<string>', path: '<string>'}]
})
};
fetch('https://odyssey.asteroid.ai/agents/v2/agents/{agentId}/workflow-head/files', 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}/workflow-head/files",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'baseRev' => 123,
'deletes' => [
'<string>'
],
'writes' => [
[
'contentBase64' => '<string>',
'path' => '<string>'
]
]
]),
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}/workflow-head/files"
payload := strings.NewReader("{\n \"baseRev\": 123,\n \"deletes\": [\n \"<string>\"\n ],\n \"writes\": [\n {\n \"contentBase64\": \"<string>\",\n \"path\": \"<string>\"\n }\n ]\n}")
req, _ := http.NewRequest("PATCH", 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.patch("https://odyssey.asteroid.ai/agents/v2/agents/{agentId}/workflow-head/files")
.header("X-Asteroid-Agents-Api-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"baseRev\": 123,\n \"deletes\": [\n \"<string>\"\n ],\n \"writes\": [\n {\n \"contentBase64\": \"<string>\",\n \"path\": \"<string>\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://odyssey.asteroid.ai/agents/v2/agents/{agentId}/workflow-head/files")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["X-Asteroid-Agents-Api-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"baseRev\": 123,\n \"deletes\": [\n \"<string>\"\n ],\n \"writes\": [\n {\n \"contentBase64\": \"<string>\",\n \"path\": \"<string>\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"agentId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"createdAt": "2023-11-07T05:31:56Z",
"files": [
{
"createdAt": "2023-11-07T05:31:56Z",
"fileName": "<string>",
"filePath": "<string>",
"fileSize": 123,
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"updatedAt": "2023-11-07T05:31:56Z",
"checksum": "<string>",
"mimeType": "<string>"
}
],
"graph": {
"nodes": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"properties": {
"type": "start"
},
"description": "<string>",
"position": {
"x": 123,
"y": 123
}
}
],
"sticky_notes": [
{
"content": "<string>",
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"color": "<string>",
"position": {
"x": 123,
"y": 123
},
"size": {
"height": 123,
"width": 123
}
}
],
"transitions": [
{
"from": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"properties": {
"type": "iris"
},
"require_confirmation": true,
"to": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"description": "<string>",
"schema": {}
}
]
},
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"inputs": [
{
"name": "<string>",
"required": true,
"schema": {},
"defaultValue": "<unknown>",
"description": "<string>"
}
],
"isPublished": true,
"rev": 123,
"rules": "<string>",
"settings": {
"max_timeout_mins": 123,
"viewport_height": 123,
"viewport_width": 123,
"new_agent_loop": true
},
"version": 123,
"author": "<string>",
"environmentTemplate": {
"config": {}
},
"parentId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}{
"code": 400,
"message": "<string>"
}{
"code": 401,
"message": "<string>"
}{
"code": 403,
"message": "<string>"
}{
"code": 404,
"message": "<string>"
}{
"code": 409,
"message": "<string>"
}{
"code": 500,
"message": "<string>"
}Authorizations
Path Parameters
The ID of the agent
Body
The file writes and deletes to apply
Request to patch the editable head's file representation. The server classifies each path: structural files re-derive the structured workflow, the agent's own files (memory, uploads, node scripts) go to their blob store β the client just writes files. Rev-guarded by baseRev: a stale value is rejected with 409.
Response
The request has succeeded.
A workflow (commit) representing an immutable snapshot of agent configuration
The agent ID this workflow belongs to
When this workflow was created. For the editable head this is restamped on each in-place edit, so it doubles as the last-edited time.
The files stored on this workflow version. Empty when the workflow has no files.
Show child attributes
Show child attributes
The workflow graph
Show child attributes
Show child attributes
The unique ID of this workflow
Typed input definitions for workflow execution. Includes names referenced in prompts, which default to optional strings.
Show child attributes
Show child attributes
Whether this snapshot is the agent's published version (the API default). At most one snapshot per agent is published.
Monotonic optimistic-concurrency revision. Only meaningful for the editable head: supply it as baseRev on the next head patch; a stale baseRev is rejected with 409. Frozen snapshots never receive in-place patches.
The rules/instructions for this workflow
The settings for this workflow
Show child attributes
Show child attributes
The monotonic per-agent snapshot version number.
The email of the user who created this workflow.
Optional environment template. Defaults to browser/anchor if not provided.
Show child attributes
Show child attributes
The ID of the parent workflow this was derived from (for lineage tracking)

