Create a tool manually
Building a tool manually is like wiring up a connection one screw at a time — slower than letting the AI do it, but every choice is yours. This is the right route when you already know the service well, when it's a private or internal service the AI can't read about online, or when you want every field to be deliberate.
Image: The configuration page with endpoint, method, and parameter fields
Before you start
- A clear idea of what the tool should do — one action per tool works best ("list contacts", not "do everything contact-related").
- The address the tool should call and the kind of request — usually copied from the service's documentation page for that action.
- A saved credential (the sign-in details Nirvai keeps so it can talk to the service for you), if the service needs one. Set one up in Credentials first if you haven't.
- A real sample value for each field, so you can test the tool with a real call before saving.
Step-by-step
The manual builder has two pages: Configuration first, then Testing.
1. Name the tool and pick a sign-in
- Open Custom Tools and click New tool.
- Give the tool a short, plain-language name ("Get HubSpot contacts"). The alias is filled in for you in snake_case (
get_hubspot_contacts). - Write a description that says exactly what the tool does. Your agent reads this to decide when to use it, so a specific description ("Looks up contacts in HubSpot by email or name") beats a vague one ("HubSpot contacts").
- Write a usage note with an example of when to reach for this tool ("Use this when the user asks about leads, customers, or contacts").
- Pick a saved sign-in for the service. Leave it empty if the service doesn't need one.
2. Set the address and the kind of request
- Paste the full URL — the specific address that does one thing, for example
https://api.hubapi.com/crm/v3/objects/contacts. - Pick the kind of request (GET, POST, PUT, PATCH, or DELETE) — the documentation page for the action usually says which one to use.
If the request types are unfamiliar, here's the everyday version:
| Kind of request | What it does | Everyday analogy |
|---|---|---|
| GET | Reads information without changing anything | Looking someone up in your address book. |
| POST | Creates something new | Adding a new contact to your address book. |
| PUT / PATCH | Updates something that already exists | Editing a contact's phone number. |
| DELETE | Removes something | Crossing a contact out. |
3. Add the fields the tool sends
Tools send pieces of information with each request, called parameters. There are four places a field can go, depending on what the service expects:
| Where the field goes | When to pick this | Example |
|---|---|---|
| Path | The field is part of the address itself, like /users/{user_id}. | user_id → 12345 |
| Query | The field is tacked onto the end of the address after a ?. | query → shoes, limit → 10 |
| Header | The field is hidden info attached to the request — common for things like an API version. | X-API-Version → 2.0 |
| Body | The field is sent inside the request itself, used by POST / PUT / PATCH. | name → John, email → john@example.com |
For each field, you fill in:
| Setting | What it means |
|---|---|
| Name | The exact field name the service expects. |
| Type | Whether it's text, a number, a yes-or-no, a list, or an object. |
| Required | Whether the request fails without this field. |
| Who fills it in | The agent fills it in = your agent picks a value from the conversation. Always the same value = you set the value once and the tool uses it every time. |
| Description | A short note that tells the agent what to put here (only matters when the agent fills it in). |
Image: The parameter editing drawer with name, type, required, and description fields
For fields the agent fills in, write descriptions that tell it exactly what to look for. Instead of "The ID", write "The customer's order number, usually mentioned as 'order #12345' or 'order 12345' in the conversation". Specific descriptions mean the agent picks the right value far more often.
Body fields must be added as named fields — one row per field, with a name and a type. Don't paste a whole JSON blob into a single body parameter; the tool needs to know each field individually so the agent can fill them in correctly.
4. Test the tool
- Click through to the Testing page.
- Fill in a real sample value for each field.
- Click Test — Nirvai makes a real call to the service using your sign-in.
- Look at the response. If the service returned what you expected, you're done. If not, go back to Configuration and adjust.
- When the test passes, click Save.
Image: The testing page with test parameter inputs and the API response
For more on reading test answers and tracking down failures, see Test your tools.
Shortcut: paste a cURL command
If the service's documentation gives you a ready-made cURL command (or you have one from a tool like Postman), you can skip most of the typing.
- On the Configuration page, click Import cURL.
- Paste the full cURL command.
- The builder fills in the address, the kind of request, the headers, and the body fields automatically.
- Review what it filled in, fix anything that needs fixing, and continue to Testing.
This is a big time-saver when you already have a working example call.
Troubleshooting
| Problem | What to check |
|---|---|
| The test returns a "not signed in" or "401" error | The sign-in is wrong, missing, or expired. Open the credential in Credentials and re-enter the private code. |
| The test returns a "not found" or "404" error | The address is wrong, or a value you put in a path field doesn't exist. Re-read the service's documentation page for that action and compare. |
| The test returns a "missing field" error | One of the fields you marked as required isn't being sent, or the field name doesn't exactly match what the service expects (watch for capital letters and underscores). |
| The agent never seems to use the tool | The description or usage note isn't specific enough. Rewrite it to mention the exact words users say ("order number", "phone", "lead") so the agent recognises when to reach for it. |
| The agent fills in a field with the wrong value | The field's description isn't clear. Rewrite it with examples of what the value looks like, or change the field to "always the same value" if the agent shouldn't be choosing. |
| I want to send a whole JSON object | Add each top-level field of the JSON as its own body parameter — one row per field. The builder assembles them into JSON for you. |
What's next
Once your tool passes its test, continue to Use tools with agents to give the new tool to the agents that should be able to use it.