curl --request PATCH \
--url https://api.reasonmachines.com/v3/organizations/{orgId}/automations/{automationId} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"instructions": "<string>",
"model": "<string>",
"tools": {
"mcp_servers": [
"<string>"
],
"app_tools": [
"<string>"
]
},
"enabled": true
}
'import requests
url = "https://api.reasonmachines.com/v3/organizations/{orgId}/automations/{automationId}"
payload = {
"name": "<string>",
"instructions": "<string>",
"model": "<string>",
"tools": {
"mcp_servers": ["<string>"],
"app_tools": ["<string>"]
},
"enabled": True
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: '<string>',
instructions: '<string>',
model: '<string>',
tools: {mcp_servers: ['<string>'], app_tools: ['<string>']},
enabled: true
})
};
fetch('https://api.reasonmachines.com/v3/organizations/{orgId}/automations/{automationId}', 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.reasonmachines.com/v3/organizations/{orgId}/automations/{automationId}",
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([
'name' => '<string>',
'instructions' => '<string>',
'model' => '<string>',
'tools' => [
'mcp_servers' => [
'<string>'
],
'app_tools' => [
'<string>'
]
],
'enabled' => true
]),
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.reasonmachines.com/v3/organizations/{orgId}/automations/{automationId}"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"instructions\": \"<string>\",\n \"model\": \"<string>\",\n \"tools\": {\n \"mcp_servers\": [\n \"<string>\"\n ],\n \"app_tools\": [\n \"<string>\"\n ]\n },\n \"enabled\": true\n}")
req, _ := http.NewRequest("PATCH", 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.patch("https://api.reasonmachines.com/v3/organizations/{orgId}/automations/{automationId}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"instructions\": \"<string>\",\n \"model\": \"<string>\",\n \"tools\": {\n \"mcp_servers\": [\n \"<string>\"\n ],\n \"app_tools\": [\n \"<string>\"\n ]\n },\n \"enabled\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.reasonmachines.com/v3/organizations/{orgId}/automations/{automationId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"instructions\": \"<string>\",\n \"model\": \"<string>\",\n \"tools\": {\n \"mcp_servers\": [\n \"<string>\"\n ],\n \"app_tools\": [\n \"<string>\"\n ]\n },\n \"enabled\": true\n}"
response = http.request(request)
puts response.read_body{
"id": "automation_example",
"org_id": "org_example",
"name": "Daily repository review",
"instructions": "Review open issues.",
"model": null,
"enabled": true,
"tools": {
"mcp_servers": null,
"app_tools": []
},
"environment": {
"repo": "example/project",
"provider": "github"
},
"triggers": [
{
"id": "trigger_example",
"kind": "schedule",
"enabled": true,
"schedule": {
"kind": "cron",
"expression": "0 9 * * *",
"every_seconds": null,
"next_run_at": "2026-09-24T09:00:00Z"
},
"github": null,
"webhook": null,
"run_kind": null,
"last_fired_at": null,
"created_at": "2026-09-01T00:00:00Z",
"updated_at": "2026-09-01T00:00:00Z"
}
],
"created_at": "2026-09-01T00:00:00Z",
"updated_at": "2026-09-01T00:00:00Z"
}{
"error": "prompt_required"
}{
"error": "missing_bearer",
"message": "Authorization required"
}{
"error": "missing_scope",
"required_scope": "sessions:read"
}{
"error": "session_not_found"
}{
"error": {
"type": "rate_limited",
"message": "This API key exceeded its request-rate limit"
}
}Update an automation
Partial update of the automation’s configuration. Send only the fields you want to change. The same name, instructions and tools rules as create apply to the fields you send. Triggers are managed through the triggers sub-resource. Only the automation’s creator can change it; workspace owners and admins can pause or delete it. Anyone else receives 403 automation_owner_only. An automation filed under a Reason has that Reason’s access: everyone who can use the Reason changes it, workspace owners and admins can pause or delete it (anyone else with sight of it receives 403 loop_reason_access_required), and to anyone else it does not exist (404 automation_not_found). A system automation (include=system) is changed only by workspace owners and admins (403 workspace_agent_admin_only); any member may add a trigger to it, which runs as that member, and remove their own triggers.
Scope:automations:writecurl --request PATCH \
--url https://api.reasonmachines.com/v3/organizations/{orgId}/automations/{automationId} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"instructions": "<string>",
"model": "<string>",
"tools": {
"mcp_servers": [
"<string>"
],
"app_tools": [
"<string>"
]
},
"enabled": true
}
'import requests
url = "https://api.reasonmachines.com/v3/organizations/{orgId}/automations/{automationId}"
payload = {
"name": "<string>",
"instructions": "<string>",
"model": "<string>",
"tools": {
"mcp_servers": ["<string>"],
"app_tools": ["<string>"]
},
"enabled": True
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: '<string>',
instructions: '<string>',
model: '<string>',
tools: {mcp_servers: ['<string>'], app_tools: ['<string>']},
enabled: true
})
};
fetch('https://api.reasonmachines.com/v3/organizations/{orgId}/automations/{automationId}', 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.reasonmachines.com/v3/organizations/{orgId}/automations/{automationId}",
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([
'name' => '<string>',
'instructions' => '<string>',
'model' => '<string>',
'tools' => [
'mcp_servers' => [
'<string>'
],
'app_tools' => [
'<string>'
]
],
'enabled' => true
]),
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.reasonmachines.com/v3/organizations/{orgId}/automations/{automationId}"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"instructions\": \"<string>\",\n \"model\": \"<string>\",\n \"tools\": {\n \"mcp_servers\": [\n \"<string>\"\n ],\n \"app_tools\": [\n \"<string>\"\n ]\n },\n \"enabled\": true\n}")
req, _ := http.NewRequest("PATCH", 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.patch("https://api.reasonmachines.com/v3/organizations/{orgId}/automations/{automationId}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"instructions\": \"<string>\",\n \"model\": \"<string>\",\n \"tools\": {\n \"mcp_servers\": [\n \"<string>\"\n ],\n \"app_tools\": [\n \"<string>\"\n ]\n },\n \"enabled\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.reasonmachines.com/v3/organizations/{orgId}/automations/{automationId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"instructions\": \"<string>\",\n \"model\": \"<string>\",\n \"tools\": {\n \"mcp_servers\": [\n \"<string>\"\n ],\n \"app_tools\": [\n \"<string>\"\n ]\n },\n \"enabled\": true\n}"
response = http.request(request)
puts response.read_body{
"id": "automation_example",
"org_id": "org_example",
"name": "Daily repository review",
"instructions": "Review open issues.",
"model": null,
"enabled": true,
"tools": {
"mcp_servers": null,
"app_tools": []
},
"environment": {
"repo": "example/project",
"provider": "github"
},
"triggers": [
{
"id": "trigger_example",
"kind": "schedule",
"enabled": true,
"schedule": {
"kind": "cron",
"expression": "0 9 * * *",
"every_seconds": null,
"next_run_at": "2026-09-24T09:00:00Z"
},
"github": null,
"webhook": null,
"run_kind": null,
"last_fired_at": null,
"created_at": "2026-09-01T00:00:00Z",
"updated_at": "2026-09-01T00:00:00Z"
}
],
"created_at": "2026-09-01T00:00:00Z",
"updated_at": "2026-09-01T00:00:00Z"
}{
"error": "prompt_required"
}{
"error": "missing_bearer",
"message": "Authorization required"
}{
"error": "missing_scope",
"required_scope": "sessions:read"
}{
"error": "session_not_found"
}{
"error": {
"type": "rate_limited",
"message": "This API key exceeded its request-rate limit"
}
}Authorizations
Your Reason API key from Settings › API keys. New keys use reason_; legacy ara_ keys remain accepted. Keys are capability-scoped: run, mcp:read, mcp:write, secrets:read, secrets:write, sessions:read, sessions:debug, knowledge:read, memory:read, memory:write, skills:read, skills:write, repos:read, repos:write, reviews:read, reviews:write, deployment:read, analytics:read, org:read, org:write, attachments:read, attachments:write, guardrails:read, guardrails:write, network:read, network:write, automations:read, automations:write, agent_auth:read. network:read and network:write are opt-in, excluded from default keys. network:read reads the saved workspace network policy; network:write replaces custom allowed hosts and requires a current organization owner/admin. Legacy project PATCH requests containing network_allowed_hosts also require network:write plus their existing run scope and project management permission; saved project hosts do not affect current session egress. Only owners/admins can mint or manage keys with network:write; keys cannot grant themselves more authority. See /docs/network-policies for replacement semantics and runtime applicability. mcp:write manages MCP server configuration only; it does not authorize remote MCP-tool execution. sessions:read reads sessions, including the assistant, reasoning and tool activity in their events. sessions:debug is privileged: only for organization owners/admins, it expands session events to the full diagnostic projection (diagnostic event kinds, status text and raw event metadata).
Path Parameters
Organization id or slug. Resolve it with GET /v3/self.
The automation id, returned as id by listAutomations and createAutomation.
Body
All fields optional. Only the fields you send are changed.
New label that identifies the automation in lists and audit entries; omit it to keep the current name.
200New task for future runs, written as the prompt the agent receives; runs already started keep the old instructions. Omit it to keep the current instructions.
100000Model override for future runs, from the currently available Reason model catalog. Send null to use the workspace default; omit to keep the current override.
Show child attributes
Show child attributes
Set false to pause the automation, so none of its triggers fire, or true to resume it. Omit it to keep the current state.
Response
Updated.
An automation: its instructions, tools, environment binding, and triggers.
Automation id; pass it as automationId to read, update, delete or add triggers.
Workspace the automation belongs to.
Label that identifies the automation.
The system instructions the automation runs with.
Model override for its runs; null uses the workspace default.
A paused (false) automation's triggers never fire.
Tools the automation's runs may use.
Show child attributes
Show child attributes
Repository each run starts in; repo is null for an automation without one.
Show child attributes
Show child attributes
Every condition that fires this automation. Empty until you add one.
Show child attributes
Show child attributes
Present only when the request was accepted but something is not as sent or not usable yet. Codes: schedule_interval_raised, app_tool_not_connected.
Show child attributes
Show child attributes
When the automation was created.
When the automation's configuration last changed.

