Search Tools
curl --request POST \
--url https://agentos.useparagon.com/api/tools/projects/{projectId}/tools/search \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"query": "list open issues",
"topK": 8,
"connectedOnly": true,
"maxSideEffect": "read"
}
'import requests
url = "https://agentos.useparagon.com/api/tools/projects/{projectId}/tools/search"
payload = {
"query": "list open issues",
"topK": 8,
"connectedOnly": True,
"maxSideEffect": "read"
}
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({query: 'list open issues', topK: 8, connectedOnly: true, maxSideEffect: 'read'})
};
fetch('https://agentos.useparagon.com/api/tools/projects/{projectId}/tools/search', 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://agentos.useparagon.com/api/tools/projects/{projectId}/tools/search",
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([
'query' => 'list open issues',
'topK' => 8,
'connectedOnly' => true,
'maxSideEffect' => 'read'
]),
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://agentos.useparagon.com/api/tools/projects/{projectId}/tools/search"
payload := strings.NewReader("{\n \"query\": \"list open issues\",\n \"topK\": 8,\n \"connectedOnly\": true,\n \"maxSideEffect\": \"read\"\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://agentos.useparagon.com/api/tools/projects/{projectId}/tools/search")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"query\": \"list open issues\",\n \"topK\": 8,\n \"connectedOnly\": true,\n \"maxSideEffect\": \"read\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://agentos.useparagon.com/api/tools/projects/{projectId}/tools/search")
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 \"query\": \"list open issues\",\n \"topK\": 8,\n \"connectedOnly\": true,\n \"maxSideEffect\": \"read\"\n}"
response = http.request(request)
puts response.read_body{
"tools": [
{
"intentName": "EXAMPLE_LIST_RECORDS",
"integration": "example",
"sideEffect": "read",
"approvalRequired": false,
"schemaSource": "static",
"relevancy": 1,
"tool": {
"type": "function",
"function": {
"name": "EXAMPLE_LIST_RECORDS",
"description": "List records.",
"parameters": {
"type": "object",
"properties": {
"limit": {
"type": "integer"
}
}
}
}
}
}
],
"searchQuery": "list open issues",
"errors": [],
"usage": {
"strategy": "hybrid",
"candidates": 4,
"returned": 1,
"toolTokens": 120,
"omittedForBudget": 0,
"omittedForSideEffect": 0,
"hydratedIntegrations": [],
"degraded": null,
"visibility": {
"mode": "filtered",
"entitledIntegrations": 2,
"candidatesBeforeFilter": 4,
"candidatesAfterFilter": 1
}
}
}{
"error": {
"code": "REQUEST_INVALID",
"message": "The request payload failed validation.",
"hint": "Correct the fields named in details and retry.",
"retryable": false,
"requestId": "req_01hxyz",
"details": [
{
"field": "query",
"issue": "query should not be empty"
}
]
}
}{
"error": {
"code": "REQUEST_INVALID",
"message": "The request payload failed validation.",
"hint": "Correct the fields named in details and retry.",
"retryable": false,
"requestId": "req_01hxyz",
"details": [
{
"field": "query",
"issue": "query should not be empty"
}
]
}
}{
"error": {
"code": "REQUEST_INVALID",
"message": "The request payload failed validation.",
"hint": "Correct the fields named in details and retry.",
"retryable": false,
"requestId": "req_01hxyz",
"details": [
{
"field": "query",
"issue": "query should not be empty"
}
]
}
}{
"error": {
"code": "REQUEST_INVALID",
"message": "The request payload failed validation.",
"hint": "Correct the fields named in details and retry.",
"retryable": false,
"requestId": "req_01hxyz",
"details": [
{
"field": "query",
"issue": "query should not be empty"
}
]
}
}Tools
Search Tools
Search the Paragon catalog for relevant Tools to use for a conversation turn.
POST
/
api
/
tools
/
projects
/
{projectId}
/
tools
/
search
Search Tools
curl --request POST \
--url https://agentos.useparagon.com/api/tools/projects/{projectId}/tools/search \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"query": "list open issues",
"topK": 8,
"connectedOnly": true,
"maxSideEffect": "read"
}
'import requests
url = "https://agentos.useparagon.com/api/tools/projects/{projectId}/tools/search"
payload = {
"query": "list open issues",
"topK": 8,
"connectedOnly": True,
"maxSideEffect": "read"
}
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({query: 'list open issues', topK: 8, connectedOnly: true, maxSideEffect: 'read'})
};
fetch('https://agentos.useparagon.com/api/tools/projects/{projectId}/tools/search', 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://agentos.useparagon.com/api/tools/projects/{projectId}/tools/search",
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([
'query' => 'list open issues',
'topK' => 8,
'connectedOnly' => true,
'maxSideEffect' => 'read'
]),
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://agentos.useparagon.com/api/tools/projects/{projectId}/tools/search"
payload := strings.NewReader("{\n \"query\": \"list open issues\",\n \"topK\": 8,\n \"connectedOnly\": true,\n \"maxSideEffect\": \"read\"\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://agentos.useparagon.com/api/tools/projects/{projectId}/tools/search")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"query\": \"list open issues\",\n \"topK\": 8,\n \"connectedOnly\": true,\n \"maxSideEffect\": \"read\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://agentos.useparagon.com/api/tools/projects/{projectId}/tools/search")
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 \"query\": \"list open issues\",\n \"topK\": 8,\n \"connectedOnly\": true,\n \"maxSideEffect\": \"read\"\n}"
response = http.request(request)
puts response.read_body{
"tools": [
{
"intentName": "EXAMPLE_LIST_RECORDS",
"integration": "example",
"sideEffect": "read",
"approvalRequired": false,
"schemaSource": "static",
"relevancy": 1,
"tool": {
"type": "function",
"function": {
"name": "EXAMPLE_LIST_RECORDS",
"description": "List records.",
"parameters": {
"type": "object",
"properties": {
"limit": {
"type": "integer"
}
}
}
}
}
}
],
"searchQuery": "list open issues",
"errors": [],
"usage": {
"strategy": "hybrid",
"candidates": 4,
"returned": 1,
"toolTokens": 120,
"omittedForBudget": 0,
"omittedForSideEffect": 0,
"hydratedIntegrations": [],
"degraded": null,
"visibility": {
"mode": "filtered",
"entitledIntegrations": 2,
"candidatesBeforeFilter": 4,
"candidatesAfterFilter": 1
}
}
}{
"error": {
"code": "REQUEST_INVALID",
"message": "The request payload failed validation.",
"hint": "Correct the fields named in details and retry.",
"retryable": false,
"requestId": "req_01hxyz",
"details": [
{
"field": "query",
"issue": "query should not be empty"
}
]
}
}{
"error": {
"code": "REQUEST_INVALID",
"message": "The request payload failed validation.",
"hint": "Correct the fields named in details and retry.",
"retryable": false,
"requestId": "req_01hxyz",
"details": [
{
"field": "query",
"issue": "query should not be empty"
}
]
}
}{
"error": {
"code": "REQUEST_INVALID",
"message": "The request payload failed validation.",
"hint": "Correct the fields named in details and retry.",
"retryable": false,
"requestId": "req_01hxyz",
"details": [
{
"field": "query",
"issue": "query should not be empty"
}
]
}
}{
"error": {
"code": "REQUEST_INVALID",
"message": "The request payload failed validation.",
"hint": "Correct the fields named in details and retry.",
"retryable": false,
"requestId": "req_01hxyz",
"details": [
{
"field": "query",
"issue": "query should not be empty"
}
]
}
}Use this endpoint to find the most relevant Tools for a given query, rather than loading all available Tools.
This is especially useful for AI agent implementations where your user may have hundreds of available Tools — Search lets you dynamically select only the Tools relevant to the current task.
Each Tool also has an
Tools with a
Filtering
You can narrow search results using the request body parameters:integrations— Restrict results to specific integrations (e.g.["salesforce", "hubspot"]).categories— Restrict results to integration categories (e.g.["crm"]).topK— Set the number of Tools to return. Defaults to 8.maxSideEffect— Exclude Tools that can change data beyond a given level. See Side Effects.
Token Budget
UsemaxToolTokens to constrain the total token size of returned Tool schemas. Tools are included in relevance order until the budget is exhausted. This is useful for fitting tool schemas into your LLM’s context window without manual truncation.
When maxToolTokens is set:
- If
topKis also set, at mosttopKtools are returned, further constrained by the token budget. - If
topKis omitted, as many tools as fit within the budget are returned (up to 50).
Side Effects
Every Tool in the results has asideEffect that describes what it does in the connected app:
sideEffect | Meaning | Example |
|---|---|---|
read | Reads data without changing anything. | Search emails, list contacts |
write | Creates or updates data. | Create a contact, update a deal |
delete | Deletes data. | Delete a file |
send | Sends something to other people. | Send a Slack message |
unknown | The Tool has not been classified. |
approvalRequired flag. It is false for read Tools and true for everything else, including unknown. Use it to decide when your agent should ask the user to confirm before running a Tool.
Limiting results by side effect
SetmaxSideEffect to the most impactful kind of Tool you want returned. Each level includes the levels below it:
maxSideEffect | Tools returned |
|---|---|
read | read |
write | read, write |
delete | read, write, delete |
send | read, write, delete, send |
sideEffect of unknown are excluded whenever maxSideEffect is set. The number of Tools removed by this setting is returned in usage.omittedForSideEffect, so you can tell the difference between a search that matched nothing and one where results were filtered out.
{
"query": "find a contact in the CRM",
"maxSideEffect": "read"
}
Running Tools
Run Tool currently only runsread Tools. Running any other Tool, including unknown Tools, returns a 403 with the error code EXEC_SIDE_EFFECT_NOT_PERMITTED. Pass maxSideEffect: "read" when searching if you want to return only Tools your agent can run.Authorizations
Your Paragon User Token (JWT), which you can generate using your project's signing keys.
Path Parameters
Query Parameters
Available options:
1 Body
application/json
Required string length:
1 - 1024Required range:
1 <= x <= 50Required range:
1 <= x <= 100000Minimum array length:
1Minimum array length:
1Available options:
read, write, delete, send Opt out only. true cannot enable reranking when the deployment has it off.