curl --request POST \
--url https://api.kordio.io/control/v1/workspaces/{workspace_slug}/agents \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "procurement agent",
"mode": "test",
"status": "active",
"scopes": [
"payment.*",
"tool.invoke"
],
"skip_starter_policy": false
}
'import requests
url = "https://api.kordio.io/control/v1/workspaces/{workspace_slug}/agents"
payload = {
"name": "procurement agent",
"mode": "test",
"status": "active",
"scopes": ["payment.*", "tool.invoke"],
"skip_starter_policy": False
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'procurement agent',
mode: 'test',
status: 'active',
scopes: ['payment.*', 'tool.invoke'],
skip_starter_policy: false
})
};
fetch('https://api.kordio.io/control/v1/workspaces/{workspace_slug}/agents', 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.kordio.io/control/v1/workspaces/{workspace_slug}/agents",
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' => 'procurement agent',
'mode' => 'test',
'status' => 'active',
'scopes' => [
'payment.*',
'tool.invoke'
],
'skip_starter_policy' => false
]),
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.kordio.io/control/v1/workspaces/{workspace_slug}/agents"
payload := strings.NewReader("{\n \"name\": \"procurement agent\",\n \"mode\": \"test\",\n \"status\": \"active\",\n \"scopes\": [\n \"payment.*\",\n \"tool.invoke\"\n ],\n \"skip_starter_policy\": false\n}")
req, _ := http.NewRequest("POST", 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.post("https://api.kordio.io/control/v1/workspaces/{workspace_slug}/agents")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"procurement agent\",\n \"mode\": \"test\",\n \"status\": \"active\",\n \"scopes\": [\n \"payment.*\",\n \"tool.invoke\"\n ],\n \"skip_starter_policy\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.kordio.io/control/v1/workspaces/{workspace_slug}/agents")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"procurement agent\",\n \"mode\": \"test\",\n \"status\": \"active\",\n \"scopes\": [\n \"payment.*\",\n \"tool.invoke\"\n ],\n \"skip_starter_policy\": false\n}"
response = http.request(request)
puts response.read_body{
"data": {
"max_budget_cents": 50000,
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"status": "active",
"mode": "test",
"scopes": [
"<string>"
],
"api_key_prefix": "krt_test_9f3",
"last_used_at": "2023-11-07T05:31:56Z",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"api_key": "krt_test_9f3a1c7e42b8d05a6e1f8c3d",
"starter_policy": {
"mode": "blocklist",
"per_transaction_cap_cents": 123,
"velocity_window_seconds": 123,
"velocity_cap_cents": 123,
"approval_threshold_cents": 123,
"monthly_cap_cents": 123,
"counterparty_allowlist": [
"<string>"
],
"imports": [
"<string>"
],
"rules": [
{
"kind": "action_allowlist",
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"rule_name": "<string>",
"action_types": [
"<string>"
],
"allow": [
"<string>"
],
"max_cents": 123,
"window_seconds": 2,
"max_actions": 2,
"above_cents": 123,
"effect": "deny",
"when": {
"all_of": "<array>",
"any_of": "<array>",
"not": "<unknown>",
"field": "metadata.preapproved",
"operator": "eq",
"value": "<unknown>"
}
}
],
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"agent_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"status": "active",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z"
}
}
}{
"error": {
"message": "Insufficient role",
"code": "insufficient_role"
}
}{
"error": {
"message": "<string>",
"code": "runtime_key_required"
}
}{
"error": {
"message": "<string>",
"code": "runtime_key_required"
}
}Requires the manage_policy capability.
The response carries api_key exactly once. Kordio stores only a digest and
compares it in constant time; if you lose the key, rotate the agent.
Unless skip_starter_policy is set, the agent is created with an active starter
policy that caps a single action at 50000 cents and holds anything above 10000
cents for a person. It is returned as starter_policy, and it stays in force
until you disable it.
Creating an agent consumes plan headroom, and creating a live agent requires a
plan with live mode. Either limit returns 422.
curl --request POST \
--url https://api.kordio.io/control/v1/workspaces/{workspace_slug}/agents \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "procurement agent",
"mode": "test",
"status": "active",
"scopes": [
"payment.*",
"tool.invoke"
],
"skip_starter_policy": false
}
'import requests
url = "https://api.kordio.io/control/v1/workspaces/{workspace_slug}/agents"
payload = {
"name": "procurement agent",
"mode": "test",
"status": "active",
"scopes": ["payment.*", "tool.invoke"],
"skip_starter_policy": False
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'procurement agent',
mode: 'test',
status: 'active',
scopes: ['payment.*', 'tool.invoke'],
skip_starter_policy: false
})
};
fetch('https://api.kordio.io/control/v1/workspaces/{workspace_slug}/agents', 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.kordio.io/control/v1/workspaces/{workspace_slug}/agents",
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' => 'procurement agent',
'mode' => 'test',
'status' => 'active',
'scopes' => [
'payment.*',
'tool.invoke'
],
'skip_starter_policy' => false
]),
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.kordio.io/control/v1/workspaces/{workspace_slug}/agents"
payload := strings.NewReader("{\n \"name\": \"procurement agent\",\n \"mode\": \"test\",\n \"status\": \"active\",\n \"scopes\": [\n \"payment.*\",\n \"tool.invoke\"\n ],\n \"skip_starter_policy\": false\n}")
req, _ := http.NewRequest("POST", 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.post("https://api.kordio.io/control/v1/workspaces/{workspace_slug}/agents")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"procurement agent\",\n \"mode\": \"test\",\n \"status\": \"active\",\n \"scopes\": [\n \"payment.*\",\n \"tool.invoke\"\n ],\n \"skip_starter_policy\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.kordio.io/control/v1/workspaces/{workspace_slug}/agents")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"procurement agent\",\n \"mode\": \"test\",\n \"status\": \"active\",\n \"scopes\": [\n \"payment.*\",\n \"tool.invoke\"\n ],\n \"skip_starter_policy\": false\n}"
response = http.request(request)
puts response.read_body{
"data": {
"max_budget_cents": 50000,
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"status": "active",
"mode": "test",
"scopes": [
"<string>"
],
"api_key_prefix": "krt_test_9f3",
"last_used_at": "2023-11-07T05:31:56Z",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"api_key": "krt_test_9f3a1c7e42b8d05a6e1f8c3d",
"starter_policy": {
"mode": "blocklist",
"per_transaction_cap_cents": 123,
"velocity_window_seconds": 123,
"velocity_cap_cents": 123,
"approval_threshold_cents": 123,
"monthly_cap_cents": 123,
"counterparty_allowlist": [
"<string>"
],
"imports": [
"<string>"
],
"rules": [
{
"kind": "action_allowlist",
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"rule_name": "<string>",
"action_types": [
"<string>"
],
"allow": [
"<string>"
],
"max_cents": 123,
"window_seconds": 2,
"max_actions": 2,
"above_cents": 123,
"effect": "deny",
"when": {
"all_of": "<array>",
"any_of": "<array>",
"not": "<unknown>",
"field": "metadata.preapproved",
"operator": "eq",
"value": "<unknown>"
}
}
],
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"agent_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"status": "active",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z"
}
}
}{
"error": {
"message": "Insufficient role",
"code": "insufficient_role"
}
}{
"error": {
"message": "<string>",
"code": "runtime_key_required"
}
}{
"error": {
"message": "<string>",
"code": "runtime_key_required"
}
}Authorizations
An identity bearer token for a person or your backend. Capabilities are per member, per workspace. This credential can manage the workspace and can never authorize an action as an agent.
Path Parameters
Body
"procurement agent"
test, live active, suspended, revoked Which action types this key may even ask about. An exact match (payment.create), a namespace wildcard (payment.*), or *. An empty array means unrestricted.
["payment.*", "tool.invoke"]
Create the agent with no policy at all. Every authorization then denies with the rule no_policy until you write one.
Response
The agent, including its plaintext key.
Show child attributes
Show child attributes