curl --request PATCH \
--url https://guidinghand.ai/v1/agents/{agent_id}/draft \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"instructions": "<string>",
"greeting": "<string>",
"display_name": "<string>",
"narration": true,
"customer_answers": true,
"customer_approvals": true,
"guardrails": {
"confirm": [],
"block": [],
"apps": {
"allow": [
"<string>"
],
"block": [
"<string>"
]
},
"sites": {
"allow": [
"<string>"
],
"block": [
"<string>"
]
},
"scope": "<string>",
"screen_check": true,
"max_steps": 250,
"max_minutes": 120,
"approval_timeout_minutes": 720
},
"tools": {
"files": {
"enabled": true
},
"http": [
{
"name": "lookup_order",
"description": "Look up an order by its number: status, items and delivery date.",
"url": "https://api.acme.com/guidinghand/lookup-order",
"parameters": {
"type": "object",
"properties": {}
},
"approval": "never"
}
]
}
}
'const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: '<string>',
instructions: '<string>',
greeting: '<string>',
display_name: '<string>',
narration: true,
customer_answers: true,
customer_approvals: true,
guardrails: {
confirm: [],
block: [],
apps: {allow: ['<string>'], block: ['<string>']},
sites: {allow: ['<string>'], block: ['<string>']},
scope: '<string>',
screen_check: true,
max_steps: 250,
max_minutes: 120,
approval_timeout_minutes: 720
},
tools: {
files: {enabled: true},
http: [
{
name: 'lookup_order',
description: 'Look up an order by its number: status, items and delivery date.',
url: 'https://api.acme.com/guidinghand/lookup-order',
parameters: {type: 'object', properties: {}},
approval: 'never'
}
]
}
})
};
fetch('https://guidinghand.ai/v1/agents/{agent_id}/draft', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://guidinghand.ai/v1/agents/{agent_id}/draft"
payload = {
"name": "<string>",
"instructions": "<string>",
"greeting": "<string>",
"display_name": "<string>",
"narration": True,
"customer_answers": True,
"customer_approvals": True,
"guardrails": {
"confirm": [],
"block": [],
"apps": {
"allow": ["<string>"],
"block": ["<string>"]
},
"sites": {
"allow": ["<string>"],
"block": ["<string>"]
},
"scope": "<string>",
"screen_check": True,
"max_steps": 250,
"max_minutes": 120,
"approval_timeout_minutes": 720
},
"tools": {
"files": { "enabled": True },
"http": [
{
"name": "lookup_order",
"description": "Look up an order by its number: status, items and delivery date.",
"url": "https://api.acme.com/guidinghand/lookup-order",
"parameters": {
"type": "object",
"properties": {}
},
"approval": "never"
}
]
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text){
"object": "agent_draft",
"agent_id": "billing",
"name": "Billing help",
"instructions": "<string>",
"model": "claude-sonnet-5-5",
"effort": "low",
"greeting": "<string>",
"display_name": "Acme Support",
"narration": true,
"customer_answers": true,
"customer_approvals": true,
"guardrails": {
"mode": "supervised",
"confirm": [
"purchase",
"send",
"delete",
"install",
"security",
"terms"
],
"block": [],
"apps": {
"allow": [],
"block": []
},
"sites": {
"allow": [],
"block": []
},
"safety_checks": "ask",
"scope": "",
"screen_check": false,
"max_steps": 150,
"max_minutes": null,
"approval_timeout_minutes": null
},
"tools": {
"files": {
"enabled": true,
"access": "read_write"
},
"http": []
},
"is_default": true,
"invite_url_template": "https://guidinghand.ai/acme/billing/{code}",
"version": 1,
"has_draft": true,
"created_by": {
"type": "user",
"email": "jane@acme.com"
},
"updated_by": {
"type": "user",
"email": "jane@acme.com"
},
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"based_on_version": 1,
"saved_at": "2023-11-07T05:31:56Z",
"saved_by": {
"type": "user",
"email": "jane@acme.com"
}
}{
"error": {
"type": "invalid_request",
"message": "<string>",
"code": "<string>",
"answered_by": "customer",
"test_case_ids": [
"<string>"
]
}
}{
"error": {
"type": "invalid_request",
"message": "<string>",
"code": "<string>",
"answered_by": "customer",
"test_case_ids": [
"<string>"
]
}
}{
"error": {
"type": "invalid_request",
"message": "<string>",
"code": "<string>",
"answered_by": "customer",
"test_case_ids": [
"<string>"
]
}
}{
"error": {
"type": "invalid_request",
"message": "<string>",
"code": "<string>",
"answered_by": "customer",
"test_case_ids": [
"<string>"
]
}
}Save a draft
Saves changes to the agent’s draft without changing what runs: sessions and tasks keep the published version until you publish it. Send only the fields to change, as for PATCH /v1/agents/{agent_id}; they apply on top of the draft. A draft that ends up the same as the published version is no draft (has_draft: false). POST works too.
curl --request PATCH \
--url https://guidinghand.ai/v1/agents/{agent_id}/draft \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"instructions": "<string>",
"greeting": "<string>",
"display_name": "<string>",
"narration": true,
"customer_answers": true,
"customer_approvals": true,
"guardrails": {
"confirm": [],
"block": [],
"apps": {
"allow": [
"<string>"
],
"block": [
"<string>"
]
},
"sites": {
"allow": [
"<string>"
],
"block": [
"<string>"
]
},
"scope": "<string>",
"screen_check": true,
"max_steps": 250,
"max_minutes": 120,
"approval_timeout_minutes": 720
},
"tools": {
"files": {
"enabled": true
},
"http": [
{
"name": "lookup_order",
"description": "Look up an order by its number: status, items and delivery date.",
"url": "https://api.acme.com/guidinghand/lookup-order",
"parameters": {
"type": "object",
"properties": {}
},
"approval": "never"
}
]
}
}
'const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: '<string>',
instructions: '<string>',
greeting: '<string>',
display_name: '<string>',
narration: true,
customer_answers: true,
customer_approvals: true,
guardrails: {
confirm: [],
block: [],
apps: {allow: ['<string>'], block: ['<string>']},
sites: {allow: ['<string>'], block: ['<string>']},
scope: '<string>',
screen_check: true,
max_steps: 250,
max_minutes: 120,
approval_timeout_minutes: 720
},
tools: {
files: {enabled: true},
http: [
{
name: 'lookup_order',
description: 'Look up an order by its number: status, items and delivery date.',
url: 'https://api.acme.com/guidinghand/lookup-order',
parameters: {type: 'object', properties: {}},
approval: 'never'
}
]
}
})
};
fetch('https://guidinghand.ai/v1/agents/{agent_id}/draft', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://guidinghand.ai/v1/agents/{agent_id}/draft"
payload = {
"name": "<string>",
"instructions": "<string>",
"greeting": "<string>",
"display_name": "<string>",
"narration": True,
"customer_answers": True,
"customer_approvals": True,
"guardrails": {
"confirm": [],
"block": [],
"apps": {
"allow": ["<string>"],
"block": ["<string>"]
},
"sites": {
"allow": ["<string>"],
"block": ["<string>"]
},
"scope": "<string>",
"screen_check": True,
"max_steps": 250,
"max_minutes": 120,
"approval_timeout_minutes": 720
},
"tools": {
"files": { "enabled": True },
"http": [
{
"name": "lookup_order",
"description": "Look up an order by its number: status, items and delivery date.",
"url": "https://api.acme.com/guidinghand/lookup-order",
"parameters": {
"type": "object",
"properties": {}
},
"approval": "never"
}
]
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text){
"object": "agent_draft",
"agent_id": "billing",
"name": "Billing help",
"instructions": "<string>",
"model": "claude-sonnet-5-5",
"effort": "low",
"greeting": "<string>",
"display_name": "Acme Support",
"narration": true,
"customer_answers": true,
"customer_approvals": true,
"guardrails": {
"mode": "supervised",
"confirm": [
"purchase",
"send",
"delete",
"install",
"security",
"terms"
],
"block": [],
"apps": {
"allow": [],
"block": []
},
"sites": {
"allow": [],
"block": []
},
"safety_checks": "ask",
"scope": "",
"screen_check": false,
"max_steps": 150,
"max_minutes": null,
"approval_timeout_minutes": null
},
"tools": {
"files": {
"enabled": true,
"access": "read_write"
},
"http": []
},
"is_default": true,
"invite_url_template": "https://guidinghand.ai/acme/billing/{code}",
"version": 1,
"has_draft": true,
"created_by": {
"type": "user",
"email": "jane@acme.com"
},
"updated_by": {
"type": "user",
"email": "jane@acme.com"
},
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"based_on_version": 1,
"saved_at": "2023-11-07T05:31:56Z",
"saved_by": {
"type": "user",
"email": "jane@acme.com"
}
}{
"error": {
"type": "invalid_request",
"message": "<string>",
"code": "<string>",
"answered_by": "customer",
"test_case_ids": [
"<string>"
]
}
}{
"error": {
"type": "invalid_request",
"message": "<string>",
"code": "<string>",
"answered_by": "customer",
"test_case_ids": [
"<string>"
]
}
}{
"error": {
"type": "invalid_request",
"message": "<string>",
"code": "<string>",
"answered_by": "customer",
"test_case_ids": [
"<string>"
]
}
}{
"error": {
"type": "invalid_request",
"message": "<string>",
"code": "<string>",
"answered_by": "customer",
"test_case_ids": [
"<string>"
]
}
}Authorizations
An org API key (gh_live_…) from Settings → API keys in the console.
Path Parameters
The agent’s id, e.g. billing or default.
Body
8020000The AI model the agent runs on: claude-sonnet-5-5, claude-opus-5-5 or claude-fable-5-1 (Anthropic), gpt-6.1-sol or gpt-6-astra (OpenAI), gemini-3.8-flash (Google). Null for GuidingHand’s default, GPT-6 Astra (gpt-6-astra). With effort, it sets the per-minute price (see /pricing). Starting a task with a model this server can’t run returns 503 with code: "model_unavailable".
claude-sonnet-5-5, claude-opus-5-5, claude-fable-5-1, gpt-6.1-sol, gpt-6-astra, gemini-3.8-flash, null How much the model thinks per step. Null for GuidingHand’s default (Low). With model, it sets the per-minute price (see /pricing).
low, medium, high, null 500What the app calls the agent on the person’s screen, in place of “GuidingHand”. One line; empty goes back to “GuidingHand”.
40Show the agent’s thoughts and steps on the person’s screen as it works, and its summary when it finishes. Off: the banner with the Stop button only (and the agent’s questions and approval requests, if customer_answers and customer_approvals are on).
Let the person at the computer answer the agent’s questions in the GuidingHand app.
Let the person at the computer approve or deny the agent’s approval requests in the GuidingHand app.
Send only the keys to change: the others keep their value. A key set to null goes back to its default, and "guardrails": null resets them all. An invalid value returns 400 with a message saying which.
Show child attributes
Show child attributes
Send only what to change. In files, only the keys you send change. http, when sent, is the whole list: it replaces the agent’s HTTP tools ([] or null removes them all). "files": null goes back to the default, and "tools": null resets both. An invalid tool (a bad name, no description, a URL that isn’t public https) is a 400 that says which.
Show child attributes
Show child attributes
Response
OK
The agent as its draft would make it: its unpublished changes over the published version (the published version itself when there are none). Tasks run it when started with agent_version: "draft".
"billing"
"Billing help"
Added under GuidingHand’s own rules, which always win.
The AI model the agent runs on: claude-sonnet-5-5, claude-opus-5-5 or claude-fable-5-1 (Anthropic), gpt-6.1-sol or gpt-6-astra (OpenAI), gemini-3.8-flash (Google). Null for GuidingHand’s default, GPT-6 Astra (gpt-6-astra). With effort, it sets the per-minute price (see /pricing). Starting a task with a model this server can’t run returns 503 with code: "model_unavailable".
claude-sonnet-5-5, claude-opus-5-5, claude-fable-5-1, gpt-6.1-sol, gpt-6-astra, gemini-3.8-flash, null How much the model thinks per step. Null for GuidingHand’s default (Low). With model, it sets the per-minute price (see /pricing).
low, medium, high, null Shown to the person on the invite page.
What the GuidingHand app calls the agent on the person’s screen while it works (“Acme Support is typing”). Empty means “GuidingHand”.
"Acme Support"
The app shows the agent’s thoughts and steps on the person’s screen as it works, and its summary when it finishes. These are the agent’s own words, so they can repeat what your team answered. Off: no thoughts, steps or summary; they see the banner with the Stop button (and the agent’s questions and approval requests, if customer_answers and customer_approvals are on).
The person at the computer can answer the agent’s questions in the GuidingHand app (your team still can too; the first answer is used). Off: only your team answers, and the question isn’t shown on the person’s screen.
The person at the computer can approve or deny the agent’s approval requests in the GuidingHand app (your team still can too; the first decision is used). Off: only your team decides, and the request isn’t shown on the person’s screen.
Rules GuidingHand enforces on each action the agent asks for, before it runs. They add to GuidingHand’s own rules and can’t loosen them. In order, the first that applies decides: text that looks like a secret, or typing into a password field, is not typed (the person is asked to type it); a match in apps.block or sites.block is blocked; with a non-empty apps.allow or sites.allow, anything not on it is blocked; a step in a block category is blocked; a step in a confirm category waits for an approval; anything else runs. On a Mac (GuidingHand 1.0.20 or later) a step’s category comes from what it would do: what’s under a click; what Space, Return or Enter presses (the focused button, or a dialog’s default button); Cmd/Ctrl+Enter, and Enter in a message box, count as sending; Delete or Backspace outside a text field counts as deleting; both ends of a drag (dropping on the Trash counts as deleting); and typed text a line at a time (text holding a secret is refused whole). A click or acting key GuidingHand can’t see waits for an approval when the agent has any confirm or block categories. A Mac where GuidingHand isn’t allowed Accessibility can’t check guardrails, so a task with rules to check fails at start. On Windows, and before 1.0.20, categories rest on the agent’s own approval requests. Always returned whole, with defaults filled in.
Show child attributes
Show child attributes
The agent’s tools beyond the computer: its own file system (on by default) and your HTTP tools. Part of its config, so versioned with it. Always returned whole, with defaults filled in.
Show child attributes
Show child attributes
"https://guidinghand.ai/acme/billing/{code}"
The published version (not the draft’s: it gets a number when it’s published).
x >= 0There are unpublished changes. False: this is the published version.
Who made it.
- Person
- API key
Show child attributes
Show child attributes
Who last changed it: saved its draft, published it or restored a version.
- Person
- API key
Show child attributes
Show child attributes
The published version the draft started from. When it’s lower than version, the agent was published since (with PATCH /v1/agents/{agent_id}), and publishing the draft as it is undoes that change.
x >= 0When the draft was last saved. Null without a draft.
Who last saved the draft. Null without a draft.
- Person
- API key
Show child attributes
Show child attributes