Tool Sets
Rooted in
your stack.
Connect the systems your business runs on. Choose what agents can do, what needs approval, and what stays in your hands.
Connect an MCP server and discover its tools. Start from a ready-made integration, or bring your own server and decide which tools are available.
Tool
set
Search
Read
Update
Create
Turn an OpenAPI specification into tools. Point to a URL or upload JSON or YAML, then filter the operations your agent can use.
OpenAPI connection
- Specification
- orders.openapi.yaml
- GET /orders
- listOrders
- GET /orders/{id}
- getOrder
- POST /orders
- Filtered out
Define HTTP tools with a shared base URL, headers, and templated paths or request bodies. Give the model a simple schema; shape the request yourself.
HTTP tool / createTicket
- Request
- POST /tickets
- Model fills in
- { subject, description }
- Request body
- { "subject": "{{ arguments.subject }}" }
- Authorization
- Bearer {{ secrets.API_TOKEN }}
Define Bare tools your application answers. Read the current page, display a card, or ask a visitor a question. The objective waits for your result.
Auto mode / Approve calls
- Applies to
- createTicket
- Question
- Did the customer ask for a ticket?
- Threshold
- Score above 0.80
- When denied
- Skip the call, tell the agent why
Tool
set
Search
Read
Update
Create
OpenAPI connection
- Specification
- orders.openapi.yaml
- GET /orders
- listOrders
- GET /orders/{id}
- getOrder
- POST /orders
- Filtered out
HTTP tool / createTicket
- Request
- POST /tickets
- Model fills in
- { subject, description }
- Request body
- { "subject": "{{ arguments.subject }}" }
- Authorization
- Bearer {{ secrets.API_TOKEN }}
Auto mode / Approve calls
- Applies to
- createTicket
- Question
- Did the customer ask for a ticket?
- Threshold
- Score above 0.80
- When denied
- Skip the call, tell the agent why
Human
in the loop.
Tool approvals work out of the box.
Get a webhook when one is waiting.
import Cadenya from '@cadenya/cadenya';
const cadenya = new Cadenya();
// On objective_event.tool_approval_requested
await cadenya.objectives.approveToolCall(
objectiveId,
toolCallId,
); Make any API an agent
Connect an MCP server
await cadenya.toolSets.create({
metadata: { name: "Support" },
spec: { adapter: { type: "mcp",
mcp: { url: "https://api.example.com/mcp" }
} }
}); Import only what you need
await cadenya.toolSets.create({
metadata: { name: "Orders" },
spec: { adapter: { type: "openapi", openapi: {
type: "url",
url: "https://api.example.com/orders.openapi.yaml",
includeTools: {
operator: "OPERATOR_OR",
filters: ["listOrders", "getOrder"].map((exact) => ({
attribute: "ATTRIBUTE_TITLE",
matcher: { type: "exact", exact },
})),
},
} } },
}); Use overlays to remove parameters, set fixed values, or pin them to trusted objective context. Hide customer IDs from the model while every call gets the right value.
Overlay / Customer context
- Applies to
- listOrders, getOrder
- Parameter path
- customerId
- Action
- Pin → customerId
- When not pinned
- Fail the call
Require approval for every tool, or only matching tools. Add Auto mode questions and confidence thresholds to an overlay for more specific approval decisions.
Approval policy
- Read tools
- No approval required
- Matching tools
- createTicket
- Approval
- Required
- Auto mode question
- Is this change requested by the user?
Transform a tool’s text result with a Liquid template before the model sees it. Keep the fields that matter and retain the raw response in the debug log.
Result transform
- Raw response
- Orders + metadata + pagination
- Liquid template
- {{ result.json.orders | json }}
- Model receives
- [{ "id": "1234", "status": "shipped" }]
- On transform error
- Keep raw result or fail
Discover MCP tools when each objective starts, using its resolved secrets. Keep credentials scoped to the tool set and choose whether discovery failures stop the objective.
Just-in-time discovery
- Load tools
- At objective start
- Headers
- Bearer {{ secrets.API_TOKEN }}
- Secrets
- Tool set overrides workspace
- On discovery failure
- Fail objective · optional
Overlay / Customer context
- Applies to
- listOrders, getOrder
- Parameter path
- customerId
- Action
- Pin → customerId
- When not pinned
- Fail the call
Approval policy
- Read tools
- No approval required
- Matching tools
- createTicket
- Approval
- Required
- Auto mode question
- Is this change requested by the user?
Result transform
- Raw response
- Orders + metadata + pagination
- Liquid template
- {{ result.json.orders | json }}
- Model receives
- [{ "id": "1234", "status": "shipped" }]
- On transform error
- Keep raw result or fail
Just-in-time discovery
- Load tools
- At objective start
- Headers
- Bearer {{ secrets.API_TOKEN }}
- Secrets
- Tool set overrides workspace
- On discovery failure
- Fail objective · optional
Know what
your tools are doing.
01 / Analytics
See what gets used.
Track tool calls over time and see which tools do the most work. Follow usage for a whole set or inspect a single tool.
02 / Sync events
Keep up with change.
See when discovery starts, completes, or fails. MCP and URL-based OpenAPI sources can sync ahead of the next objective.
03 / Debugger
Get to the source.
Inspect recent tool-call diagnostics. Result transforms keep the raw response in the debug log, so the original is still there.
A few things
to know.
Can I connect an API without an MCP server?
Yes. Import an OpenAPI specification from a URL or file, or define HTTP tools with templated requests.
Where do Bare tools run?
Your application supplies their results. Objectives wait for that content, unless a tool has an immediate fixed result.
Can I assign just one tool?
Yes. Assign individual tools or an entire tool set to an agent variation. The Used By views show where each is assigned.
Put your tools
to work.
Connect your stack. Set the boundaries. Let agents get on with it.