Create a skill
curl --request POST \
--url https://agp.eu.hcompany.ai/api/v2/skills \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"description": "<string>",
"body": "<string>",
"source": "<string>",
"url_pattern": "<string>"
}
'import requests
url = "https://agp.eu.hcompany.ai/api/v2/skills"
payload = {
"name": "<string>",
"description": "<string>",
"body": "<string>",
"source": "<string>",
"url_pattern": "<string>"
}
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: '<string>',
description: '<string>',
body: JSON.stringify('<string>'),
source: '<string>',
url_pattern: '<string>'
})
};
fetch('https://agp.eu.hcompany.ai/api/v2/skills', 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://agp.eu.hcompany.ai/api/v2/skills",
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' => '<string>',
'description' => '<string>',
'body' => '<string>',
'source' => '<string>',
'url_pattern' => '<string>'
]),
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://agp.eu.hcompany.ai/api/v2/skills"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"body\": \"<string>\",\n \"source\": \"<string>\",\n \"url_pattern\": \"<string>\"\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://agp.eu.hcompany.ai/api/v2/skills")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"body\": \"<string>\",\n \"source\": \"<string>\",\n \"url_pattern\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://agp.eu.hcompany.ai/api/v2/skills")
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\": \"<string>\",\n \"description\": \"<string>\",\n \"body\": \"<string>\",\n \"source\": \"<string>\",\n \"url_pattern\": \"<string>\"\n}"
response = http.request(request)
puts response.read_bodySkills
Create a skill
Create a reusable skill in your catalog.
POST
/
api
/
v2
/
skills
Create a skill
curl --request POST \
--url https://agp.eu.hcompany.ai/api/v2/skills \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"description": "<string>",
"body": "<string>",
"source": "<string>",
"url_pattern": "<string>"
}
'import requests
url = "https://agp.eu.hcompany.ai/api/v2/skills"
payload = {
"name": "<string>",
"description": "<string>",
"body": "<string>",
"source": "<string>",
"url_pattern": "<string>"
}
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: '<string>',
description: '<string>',
body: JSON.stringify('<string>'),
source: '<string>',
url_pattern: '<string>'
})
};
fetch('https://agp.eu.hcompany.ai/api/v2/skills', 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://agp.eu.hcompany.ai/api/v2/skills",
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' => '<string>',
'description' => '<string>',
'body' => '<string>',
'source' => '<string>',
'url_pattern' => '<string>'
]),
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://agp.eu.hcompany.ai/api/v2/skills"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"body\": \"<string>\",\n \"source\": \"<string>\",\n \"url_pattern\": \"<string>\"\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://agp.eu.hcompany.ai/api/v2/skills")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"body\": \"<string>\",\n \"source\": \"<string>\",\n \"url_pattern\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://agp.eu.hcompany.ai/api/v2/skills")
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\": \"<string>\",\n \"description\": \"<string>\",\n \"body\": \"<string>\",\n \"source\": \"<string>\",\n \"url_pattern\": \"<string>\"\n}"
response = http.request(request)
puts response.read_bodyCreates a new skill in your catalog. Returns
201.
Returns the created Skill object.
Request body
The body is the Skill object. See that page for the full meaning of each field. The constraints that matter when creating one are below.string
required
Catalog identifier, kebab-case with an optional single
org/ namespace prefix. The h/ prefix is reserved for H’s catalog (rejected with 403) and marks the skill as reserved. Any other name creates a custom skill, private to your organization. Immutable after creation.string
required
One-line routing hint used for discovery. Non-empty.
string
required
The Markdown prompt fragment the agent receives at runtime. Non-empty.
string
Optional provenance URL.
string
Optional, informational regex hinting at URLs where this skill applies. 1 to 1024 characters.
Examples
curl -X POST https://agp.eu.hcompany.ai/api/v2/skills \
-H "Authorization: Bearer $HAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "extract-table-data",
"description": "Extract structured data from HTML tables into JSON.",
"body": "When you encounter an HTML table, extract all rows and columns into a JSON array of objects. Each object should use the table headers as keys.",
"source": "https://github.com/myorg/skills"
}'
from hai_agents import Client
client = Client()
skill = client.skills.create_skill(
name="extract-table-data",
description="Extract structured data from HTML tables into JSON.",
body="When you encounter an HTML table, extract all rows and columns into a JSON array of objects. Each object should use the table headers as keys.",
source="https://github.com/myorg/skills",
)
print(skill.name)
import { HaiAgentsClient } from "hai-agents";
const client = new HaiAgentsClient();
const skill = await client.skills.createSkill({
name: "extract-table-data",
description: "Extract structured data from HTML tables into JSON.",
body: "When you encounter an HTML table, extract all rows and columns into a JSON array of objects. Each object should use the table headers as keys.",
source: "https://github.com/myorg/skills",
});
console.log(skill.name);
Response
{
"name": "extract-table-data",
"description": "Extract structured data from HTML tables into JSON.",
"body": "When you encounter an HTML table...",
"source": "https://github.com/myorg/skills",
"url_pattern": null
}
Errors
| Status | Cause |
|---|---|
403 | Attempted to use the reserved h/ namespace. |
409 | A skill with this name already exists in your catalog. |
422 | Body fails validation. Common cases: empty body, invalid name shape. |
Last modified on September 11, 2026
Was this page helpful?