Skip to main content
POST
Test a workflow tool
This endpoint answers “does this tool work the way the agent will call it?”. It runs one of a task’s custom HTTP tools once, through the same path the agent uses in a real conversation, and returns what was sent, what came back, and what the agent would read. Use it right after you set up or change a tool, before you turn the task live.

What the test does

  • It builds the request exactly like the agent: {{env.KEY}} secrets, context placeholders, {argument} path parameters, the remaining arguments as query parameters (GET) or as the body (other methods), and the tool’s saved headers.
  • It works on inactive tools, so you can test a tool before you turn it on.
  • It calls your external system for real.
  • Unlike a conversation, it only reaches public hosts, does not follow redirects, and runs at most once. A URL that points to a loopback, private, link-local, or cloud metadata address is refused before anything is sent.
  • Nothing changes in Nexor: no lead, stage, field, or conversation is touched, and the run does not appear in Tool health.

Before you start

  • MCP keys need workflows:write, because the test reaches your system for real. Full-access REST keys need nothing else.
  • Get toolId from List workflow tools. Only the task’s custom tools can be tested.
  • Nexor platform tools return 400 internal_tool_not_testable. Test those in Playground.

Tools that change data

GET tools run directly. A tool whose method is POST, PUT, PATCH, or DELETE changes data in your system, so the test only runs with confirm_write: true. Without it the answer is 409 write_requires_confirmation and nothing is sent.
Send confirm_write: true only after the person who owns the external system agreed, use test data, and define the cleanup before the call. Cancel an appointment created by a booking test. For rescheduling and cancellation, use a disposable fixture or a restore operation supported by the provider.

What to send

A test has no real lead. Placeholders that read other lead data, such as {{lead.phone}}, stay unresolved and appear in checks.unresolved_placeholders. {{lead_id}} is sent empty.

Placeholders in the tool URL

A tool argument in double braces, such as /appointments/{{appointment_id}}, never gets a value: the literal text reaches your system. Saving a tool like that is rejected with 400 invalid_url_placeholder, which names the arguments in fields and proposes the corrected URL in suggested_url:
Tools saved before this check existed are not changed. Test them: a leftover argument in double braces shows up in checks.unresolved_placeholders.

How to read the result

success only says the test could run. The verdict is passed, which is true when the request was sent, your system answered with a 2xx and a usable body, and the final URL has no unresolved placeholder.

Limits

  • One attempt per request, up to the tool’s timeout. A test that times out is not retried, so a tool that changes data runs at most once.
  • body_excerpt and agent_sees are cut at 2,000 characters.
  • Values that come from {{env.KEY}} appear in request.url as [Redacted]. Headers are not returned. Values you send in args or lead_metadata are returned as sent.

Authorizations

X-API-Key
string
header
required

API key for authentication. Keys are prefixed with nxr_live_.

Path Parameters

id
string<uuid>
required

Task ID (workflow in the API) that owns the tool.

toolId
string<uuid>
required

Tool ID, as returned by List workflow tools.

Body

application/json
args
object

The arguments the AI agent would pass, checked against the tool's parameters. Arguments named in the URL as {argument} fill the path; the rest go as query parameters on GET or in the body on other methods. Default {}. Anything other than an object returns 400 Invalid input.

lead_metadata
object

Sample lead metadata used to fill {{lead.metadata.X}} and {X} placeholders, as a real lead's metadata would. Default {}. Anything other than an object returns 400 Invalid input.

confirm_write
boolean
default:false

Required as true for tools whose method is POST, PUT, PATCH, or DELETE, because the test really changes data in the external system. Send it only after the operator agreed, with test data, and undo the effect afterwards. The test runs at most once: a timeout is not retried. Ignored for GET tools.

Response

The test ran. success only means the test could run; read passed for the verdict. passed is true when the request was sent, the external system answered with a 2xx and a usable body, and the final URL has no unresolved {{...}} placeholder.

success
boolean
required
tool_id
string<uuid>
required
name
string
required

Tool name as the agent calls it.

method
enum<string>
required
Available options:
GET,
POST,
PUT,
PATCH,
DELETE
passed
boolean
required

true when called is true, response.ok is true, and checks.unresolved_placeholders is empty.

called
boolean
required

false when no answer came back. Usually the request never left Nexor, for example because args do not match the tool's parameters, a {{env.KEY}} secret is missing, or the final URL points to a host that is not public; it is also false when the single attempt timed out. agent_sees then explains why.

request
object | null
required

What Nexor sent. null when called is false. Headers are not returned.

response
object | null
required

What the external system answered. null when called is false.

agent_sees
string | null
required

What the AI model receives, as text, cut at 2,000 characters. It can differ from body_excerpt, because Nexor cleans the response and keeps only the fields in the tool's llm_response_fields when they are set.

checks
object
required
Last modified on October 2, 2026