curl --request POST \
--url https://api.humanos.tech/agents/actions/{did} \
--header 'Content-Type: application/json' \
--data '
{
"name": "payments-agent",
"tools": [
{
"name": "pay_invoice",
"params": {
"amount": {
"type": "number",
"required": true
}
}
}
],
"description": "Pays invoices from the company account.",
"grantorParams": {
"maxAmount": {
"type": "number",
"suggested": 500
}
},
"rules": [
{
"name": "amount_within_limit",
"expression": "params.amount <= userParams.maxAmount",
"description": "The amount stays within the limit the person set."
}
],
"requiredFromTools": true
}
'import requests
url = "https://api.humanos.tech/agents/actions/{did}"
payload = {
"name": "payments-agent",
"tools": [
{
"name": "pay_invoice",
"params": { "amount": {
"type": "number",
"required": True
} }
}
],
"description": "Pays invoices from the company account.",
"grantorParams": { "maxAmount": {
"type": "number",
"suggested": 500
} },
"rules": [
{
"name": "amount_within_limit",
"expression": "params.amount <= userParams.maxAmount",
"description": "The amount stays within the limit the person set."
}
],
"requiredFromTools": True
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'payments-agent',
tools: [{name: 'pay_invoice', params: {amount: {type: 'number', required: true}}}],
description: 'Pays invoices from the company account.',
grantorParams: {maxAmount: {type: 'number', suggested: 500}},
rules: [
{
name: 'amount_within_limit',
expression: 'params.amount <= userParams.maxAmount',
description: 'The amount stays within the limit the person set.'
}
],
requiredFromTools: true
})
};
fetch('https://api.humanos.tech/agents/actions/{did}', 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.humanos.tech/agents/actions/{did}",
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([
'name' => 'payments-agent',
'tools' => [
[
'name' => 'pay_invoice',
'params' => [
'amount' => [
'type' => 'number',
'required' => true
]
]
]
],
'description' => 'Pays invoices from the company account.',
'grantorParams' => [
'maxAmount' => [
'type' => 'number',
'suggested' => 500
]
],
'rules' => [
[
'name' => 'amount_within_limit',
'expression' => 'params.amount <= userParams.maxAmount',
'description' => 'The amount stays within the limit the person set.'
]
],
'requiredFromTools' => true
]),
CURLOPT_HTTPHEADER => [
"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.humanos.tech/agents/actions/{did}"
payload := strings.NewReader("{\n \"name\": \"payments-agent\",\n \"tools\": [\n {\n \"name\": \"pay_invoice\",\n \"params\": {\n \"amount\": {\n \"type\": \"number\",\n \"required\": true\n }\n }\n }\n ],\n \"description\": \"Pays invoices from the company account.\",\n \"grantorParams\": {\n \"maxAmount\": {\n \"type\": \"number\",\n \"suggested\": 500\n }\n },\n \"rules\": [\n {\n \"name\": \"amount_within_limit\",\n \"expression\": \"params.amount <= userParams.maxAmount\",\n \"description\": \"The amount stays within the limit the person set.\"\n }\n ],\n \"requiredFromTools\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
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://api.humanos.tech/agents/actions/{did}")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"payments-agent\",\n \"tools\": [\n {\n \"name\": \"pay_invoice\",\n \"params\": {\n \"amount\": {\n \"type\": \"number\",\n \"required\": true\n }\n }\n }\n ],\n \"description\": \"Pays invoices from the company account.\",\n \"grantorParams\": {\n \"maxAmount\": {\n \"type\": \"number\",\n \"suggested\": 500\n }\n },\n \"rules\": [\n {\n \"name\": \"amount_within_limit\",\n \"expression\": \"params.amount <= userParams.maxAmount\",\n \"description\": \"The amount stays within the limit the person set.\"\n }\n ],\n \"requiredFromTools\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.humanos.tech/agents/actions/{did}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"payments-agent\",\n \"tools\": [\n {\n \"name\": \"pay_invoice\",\n \"params\": {\n \"amount\": {\n \"type\": \"number\",\n \"required\": true\n }\n }\n }\n ],\n \"description\": \"Pays invoices from the company account.\",\n \"grantorParams\": {\n \"maxAmount\": {\n \"type\": \"number\",\n \"suggested\": 500\n }\n },\n \"rules\": [\n {\n \"name\": \"amount_within_limit\",\n \"expression\": \"params.amount <= userParams.maxAmount\",\n \"description\": \"The amount stays within the limit the person set.\"\n }\n ],\n \"requiredFromTools\": true\n}"
response = http.request(request)
puts response.read_body{
"actionId": "507f1f77bcf86cd799439011",
"created": true,
"userParams": [
"cap"
],
"executionParams": [
"load_id",
"rate_usd"
],
"suggested": {
"cap": 500
},
"versionId": "urn:via:action:abc-123",
"unchanged": false,
"updated": false,
"published": false,
"warnings": [
{
"kind": "unsupported",
"code": "unsupported_function",
"message": "Rule \"rate_cap\" (unsupported): dyn() is outside the supported CEL",
"rule": "rate_cap",
"ruleIndex": 0,
"param": "executionParams.rate_usd",
"publishOnly": false
}
]
}{
"statusCode": 400,
"message": "Rule \"rate_cap\" (never passes): no such overload: double + int",
"error": "Bad Request"
}{
"statusCode": 404,
"message": "actor not found",
"error": "Not Found"
}Import Action
Land the tool surface agent-sdk extracted from an already-built agent as a draft action version: tool names, parameter names, types and requiredness
Extraction derives shapes and never guesses constraints, so the draft denies until a person authors its policy in the dashboard and publishes it
A re-import creates a new version rather than editing one, because a published version may already be pinned by live mandates
Proposed rules are checked against the supported CEL: a rule that would deny every call is refused, one outside the supported CEL is saved and listed in warnings
curl --request POST \
--url https://api.humanos.tech/agents/actions/{did} \
--header 'Content-Type: application/json' \
--data '
{
"name": "payments-agent",
"tools": [
{
"name": "pay_invoice",
"params": {
"amount": {
"type": "number",
"required": true
}
}
}
],
"description": "Pays invoices from the company account.",
"grantorParams": {
"maxAmount": {
"type": "number",
"suggested": 500
}
},
"rules": [
{
"name": "amount_within_limit",
"expression": "params.amount <= userParams.maxAmount",
"description": "The amount stays within the limit the person set."
}
],
"requiredFromTools": true
}
'import requests
url = "https://api.humanos.tech/agents/actions/{did}"
payload = {
"name": "payments-agent",
"tools": [
{
"name": "pay_invoice",
"params": { "amount": {
"type": "number",
"required": True
} }
}
],
"description": "Pays invoices from the company account.",
"grantorParams": { "maxAmount": {
"type": "number",
"suggested": 500
} },
"rules": [
{
"name": "amount_within_limit",
"expression": "params.amount <= userParams.maxAmount",
"description": "The amount stays within the limit the person set."
}
],
"requiredFromTools": True
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'payments-agent',
tools: [{name: 'pay_invoice', params: {amount: {type: 'number', required: true}}}],
description: 'Pays invoices from the company account.',
grantorParams: {maxAmount: {type: 'number', suggested: 500}},
rules: [
{
name: 'amount_within_limit',
expression: 'params.amount <= userParams.maxAmount',
description: 'The amount stays within the limit the person set.'
}
],
requiredFromTools: true
})
};
fetch('https://api.humanos.tech/agents/actions/{did}', 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.humanos.tech/agents/actions/{did}",
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([
'name' => 'payments-agent',
'tools' => [
[
'name' => 'pay_invoice',
'params' => [
'amount' => [
'type' => 'number',
'required' => true
]
]
]
],
'description' => 'Pays invoices from the company account.',
'grantorParams' => [
'maxAmount' => [
'type' => 'number',
'suggested' => 500
]
],
'rules' => [
[
'name' => 'amount_within_limit',
'expression' => 'params.amount <= userParams.maxAmount',
'description' => 'The amount stays within the limit the person set.'
]
],
'requiredFromTools' => true
]),
CURLOPT_HTTPHEADER => [
"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.humanos.tech/agents/actions/{did}"
payload := strings.NewReader("{\n \"name\": \"payments-agent\",\n \"tools\": [\n {\n \"name\": \"pay_invoice\",\n \"params\": {\n \"amount\": {\n \"type\": \"number\",\n \"required\": true\n }\n }\n }\n ],\n \"description\": \"Pays invoices from the company account.\",\n \"grantorParams\": {\n \"maxAmount\": {\n \"type\": \"number\",\n \"suggested\": 500\n }\n },\n \"rules\": [\n {\n \"name\": \"amount_within_limit\",\n \"expression\": \"params.amount <= userParams.maxAmount\",\n \"description\": \"The amount stays within the limit the person set.\"\n }\n ],\n \"requiredFromTools\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
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://api.humanos.tech/agents/actions/{did}")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"payments-agent\",\n \"tools\": [\n {\n \"name\": \"pay_invoice\",\n \"params\": {\n \"amount\": {\n \"type\": \"number\",\n \"required\": true\n }\n }\n }\n ],\n \"description\": \"Pays invoices from the company account.\",\n \"grantorParams\": {\n \"maxAmount\": {\n \"type\": \"number\",\n \"suggested\": 500\n }\n },\n \"rules\": [\n {\n \"name\": \"amount_within_limit\",\n \"expression\": \"params.amount <= userParams.maxAmount\",\n \"description\": \"The amount stays within the limit the person set.\"\n }\n ],\n \"requiredFromTools\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.humanos.tech/agents/actions/{did}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"payments-agent\",\n \"tools\": [\n {\n \"name\": \"pay_invoice\",\n \"params\": {\n \"amount\": {\n \"type\": \"number\",\n \"required\": true\n }\n }\n }\n ],\n \"description\": \"Pays invoices from the company account.\",\n \"grantorParams\": {\n \"maxAmount\": {\n \"type\": \"number\",\n \"suggested\": 500\n }\n },\n \"rules\": [\n {\n \"name\": \"amount_within_limit\",\n \"expression\": \"params.amount <= userParams.maxAmount\",\n \"description\": \"The amount stays within the limit the person set.\"\n }\n ],\n \"requiredFromTools\": true\n}"
response = http.request(request)
puts response.read_body{
"actionId": "507f1f77bcf86cd799439011",
"created": true,
"userParams": [
"cap"
],
"executionParams": [
"load_id",
"rate_usd"
],
"suggested": {
"cap": 500
},
"versionId": "urn:via:action:abc-123",
"unchanged": false,
"updated": false,
"published": false,
"warnings": [
{
"kind": "unsupported",
"code": "unsupported_function",
"message": "Rule \"rate_cap\" (unsupported): dyn() is outside the supported CEL",
"rule": "rate_cap",
"ruleIndex": 0,
"param": "executionParams.rate_usd",
"publishOnly": false
}
]
}{
"statusCode": 400,
"message": "Rule \"rate_cap\" (never passes): no such overload: double + int",
"error": "Bad Request"
}{
"statusCode": 404,
"message": "actor not found",
"error": "Not Found"
}Headers
Pin request, response, and webhook shapes to a specific dated API version (YYYY-MM-DD). Omit to use the version pinned to your API key (set when the key is created; new keys default to the latest version). New integrations should target the latest version.
^\d{4}-\d{2}-\d{2}$"2026-10-16"
Path Parameters
The agent's DID, URL-encoded.
"did:web:humanos.tech:agent:2f8b6c41-9d37-4e5a-8b02-6c1d9e7a4f35"
Body
The action name. A re-import under the same name adds a version to that action.
"payments-agent"
The tools, as agent-sdk's toWireTools gives them: { name, description?, params }, each parameter { type, description?, required?, role? }. Each tool is read by the import, which owns its shape.
[
{
"name": "pay_invoice",
"params": {
"amount": { "type": "number", "required": true }
}
}
]
"Pays invoices from the company account."
The values the person fixes in the mandate, by name: { type, items?, values?, description?, required?, suggested? }. suggested is echoed back for the agent's request and never stored in the action.
{
"maxAmount": { "type": "number", "suggested": 500 }
}
CEL rules the agent proposes for the draft. A rule that would deny every call is a 400; one outside the supported CEL is saved and listed in warnings.
Show child attributes
Show child attributes
Carry each tool parameter's required into the draft, so verification enforces it.
Response
Returns the draft action version and the split of who supplies each value, with warnings when the draft holds something to change before publishing.
MongoDB identifier of the action the surface landed on.
"507f1f77bcf86cd799439011"
True when this import created the action; false when it added a version to an existing one.
true
The parameters the person fixes in the mandate.
["cap"]
The parameters the agent supplies at each call.
["load_id", "rate_usd"]
The agent's proposed values for the person's parameters, echoed for its later request. Never stored in the action.
{ "cap": 500 }
URN of the action version the import wrote, or of the one it found unchanged. Use it with the version endpoints.
"urn:via:action:abc-123"
True when the same surface was already the action's latest version: nothing was written.
false
True when the latest version was a draft and its declarations were refreshed in place, its rules kept.
false
Whether the version returned is published, so a mandate can be asked under it now. An import never publishes.
false
What the draft was saved with although the organization cannot publish it as it is, such as a rule outside the supported CEL. Present only when there is something to say.
Show child attributes
Show child attributes