curl "https://api.signalmd.dev/v1/agents/6f1d2c3b-4a5e-4f60-8b7a-9c0d1e2f3a4b/tests/3f1c2d4e-5a6b-4c7d-8e9f-0a1b2c3d4e5f" \
-H "Authorization: Bearer $SIGNAL_API_KEY"import requests
url = "https://api.signalmd.dev/v1/agents/{agentId}/tests/{testId}"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.signalmd.dev/v1/agents/{agentId}/tests/{testId}', 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://api.signalmd.dev/v1/agents/{agentId}/tests/{testId}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.signalmd.dev/v1/agents/{agentId}/tests/{testId}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.signalmd.dev/v1/agents/{agentId}/tests/{testId}")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.signalmd.dev/v1/agents/{agentId}/tests/{testId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"object": "test",
"id": "3f1c2d4e-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
"title": "Books a cleaning when the lookup is slow",
"source": "production",
"lane": "integrations",
"intentSlug": "book_appointment",
"tier": "text",
"sourceCallId": "0b9e8d7c-6f5a-4b3c-9d2e-1f0a9b8c7d6e",
"sourceIssueKey": "tool_timeout:check_availability",
"persona": {
"slug": "@source",
"label": "The call's own caller"
},
"revision": 2,
"state": "accepted",
"acceptedAt": "2026-09-20T16:12:00.000Z",
"criteriaApprovedAt": "2026-09-20T16:12:00.000Z",
"expect": "pass",
"guard": false,
"gates": true,
"gateReason": "Calibrated: reproduces the failure on version 7 and passes on 8.",
"written": true,
"calibration": {
"state": "stable",
"expect": "pass",
"version": 8,
"k": 3,
"n": 3,
"results": [
"passed",
"passed",
"passed"
],
"runId": "d1e2f3a4-b5c6-4d7e-8f9a-0b1c2d3e4f5a",
"revision": 2,
"epoch": {
"simulatorModel": "caller-setup-a",
"judgeModel": "review-setup-a",
"judgePromptHash": "9f2c1a7e",
"scorerVersion": "2026-09-18"
},
"at": "2026-10-02T11:07:41.000Z",
"reason": "Passed every run on version 8."
},
"inRelease": true,
"testSets": [
{
"id": "c7d8e9f0-a1b2-4c3d-8e4f-5a6b7c8d9e0f",
"name": "Release"
}
],
"tags": [
"booking"
],
"criteriaCount": 2,
"fixtureCounts": {
"total": 1,
"recorded": 1,
"fromOtherCall": 0,
"ownerSet": 0,
"none": 0
},
"lastAttempt": {
"result": "passed",
"startedAt": "2026-10-02T11:01:15.000Z"
},
"autoImprove": {
"status": "ready",
"label": "Ready for calls",
"active": false,
"updatedAt": "2026-09-28T09:44:02.000Z"
},
"archivedAt": null,
"createdAt": "2026-09-20T16:12:00.000Z",
"updatedAt": "2026-09-28T09:40:31.000Z"
}{
"error": {
"type": "not_found_error",
"code": "agent_not_found",
"message": "Agent not found.",
"param": null,
"requestId": "req_8c1f0e2b4a6d9e3f7a5c1b0d"
}
}{
"error": {
"type": "not_found_error",
"code": "agent_not_found",
"message": "Agent not found.",
"param": null,
"requestId": "req_8c1f0e2b4a6d9e3f7a5c1b0d"
}
}{
"error": {
"type": "not_found_error",
"code": "agent_not_found",
"message": "Agent not found.",
"param": null,
"requestId": "req_8c1f0e2b4a6d9e3f7a5c1b0d"
}
}{
"error": {
"type": "not_found_error",
"code": "agent_not_found",
"message": "Agent not found.",
"param": null,
"requestId": "req_8c1f0e2b4a6d9e3f7a5c1b0d"
}
}{
"error": {
"type": "not_found_error",
"code": "agent_not_found",
"message": "Agent not found.",
"param": null,
"requestId": "req_8c1f0e2b4a6d9e3f7a5c1b0d"
}
}{
"error": {
"type": "not_found_error",
"code": "agent_not_found",
"message": "Agent not found.",
"param": null,
"requestId": "req_8c1f0e2b4a6d9e3f7a5c1b0d"
}
}Get a test
One test with its spec, the shape create and edit take, and its criteria resolved against the current brief. Personal values stay masked.
curl "https://api.signalmd.dev/v1/agents/6f1d2c3b-4a5e-4f60-8b7a-9c0d1e2f3a4b/tests/3f1c2d4e-5a6b-4c7d-8e9f-0a1b2c3d4e5f" \
-H "Authorization: Bearer $SIGNAL_API_KEY"import requests
url = "https://api.signalmd.dev/v1/agents/{agentId}/tests/{testId}"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.signalmd.dev/v1/agents/{agentId}/tests/{testId}', 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://api.signalmd.dev/v1/agents/{agentId}/tests/{testId}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.signalmd.dev/v1/agents/{agentId}/tests/{testId}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.signalmd.dev/v1/agents/{agentId}/tests/{testId}")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.signalmd.dev/v1/agents/{agentId}/tests/{testId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"object": "test",
"id": "3f1c2d4e-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
"title": "Books a cleaning when the lookup is slow",
"source": "production",
"lane": "integrations",
"intentSlug": "book_appointment",
"tier": "text",
"sourceCallId": "0b9e8d7c-6f5a-4b3c-9d2e-1f0a9b8c7d6e",
"sourceIssueKey": "tool_timeout:check_availability",
"persona": {
"slug": "@source",
"label": "The call's own caller"
},
"revision": 2,
"state": "accepted",
"acceptedAt": "2026-09-20T16:12:00.000Z",
"criteriaApprovedAt": "2026-09-20T16:12:00.000Z",
"expect": "pass",
"guard": false,
"gates": true,
"gateReason": "Calibrated: reproduces the failure on version 7 and passes on 8.",
"written": true,
"calibration": {
"state": "stable",
"expect": "pass",
"version": 8,
"k": 3,
"n": 3,
"results": [
"passed",
"passed",
"passed"
],
"runId": "d1e2f3a4-b5c6-4d7e-8f9a-0b1c2d3e4f5a",
"revision": 2,
"epoch": {
"simulatorModel": "caller-setup-a",
"judgeModel": "review-setup-a",
"judgePromptHash": "9f2c1a7e",
"scorerVersion": "2026-09-18"
},
"at": "2026-10-02T11:07:41.000Z",
"reason": "Passed every run on version 8."
},
"inRelease": true,
"testSets": [
{
"id": "c7d8e9f0-a1b2-4c3d-8e4f-5a6b7c8d9e0f",
"name": "Release"
}
],
"tags": [
"booking"
],
"criteriaCount": 2,
"fixtureCounts": {
"total": 1,
"recorded": 1,
"fromOtherCall": 0,
"ownerSet": 0,
"none": 0
},
"lastAttempt": {
"result": "passed",
"startedAt": "2026-10-02T11:01:15.000Z"
},
"autoImprove": {
"status": "ready",
"label": "Ready for calls",
"active": false,
"updatedAt": "2026-09-28T09:44:02.000Z"
},
"archivedAt": null,
"createdAt": "2026-09-20T16:12:00.000Z",
"updatedAt": "2026-09-28T09:40:31.000Z"
}{
"error": {
"type": "not_found_error",
"code": "agent_not_found",
"message": "Agent not found.",
"param": null,
"requestId": "req_8c1f0e2b4a6d9e3f7a5c1b0d"
}
}{
"error": {
"type": "not_found_error",
"code": "agent_not_found",
"message": "Agent not found.",
"param": null,
"requestId": "req_8c1f0e2b4a6d9e3f7a5c1b0d"
}
}{
"error": {
"type": "not_found_error",
"code": "agent_not_found",
"message": "Agent not found.",
"param": null,
"requestId": "req_8c1f0e2b4a6d9e3f7a5c1b0d"
}
}{
"error": {
"type": "not_found_error",
"code": "agent_not_found",
"message": "Agent not found.",
"param": null,
"requestId": "req_8c1f0e2b4a6d9e3f7a5c1b0d"
}
}{
"error": {
"type": "not_found_error",
"code": "agent_not_found",
"message": "Agent not found.",
"param": null,
"requestId": "req_8c1f0e2b4a6d9e3f7a5c1b0d"
}
}{
"error": {
"type": "not_found_error",
"code": "agent_not_found",
"message": "Agent not found.",
"param": null,
"requestId": "req_8c1f0e2b4a6d9e3f7a5c1b0d"
}
}Authorizations
An API key (sig_...), or a session token from the web app.
Path Parameters
The agent's id.
^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"3f1c2d4e-5a6b-4c7d-8e9f-0a1b2c3d4e5f"
The test's id.
^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"3f1c2d4e-5a6b-4c7d-8e9f-0a1b2c3d4e5f"
Response
The test.
test ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"3f1c2d4e-5a6b-4c7d-8e9f-0a1b2c3d4e5f"
What the test list calls it. Null on tests made before titles.
production: a stored call replayed. custom: written as a spec. probe: written for a brief line no call exercises; never gates.
production, custom, probe The lane a defect lives in: hearing, understanding, flow, speaking or integrations.
hearing, understanding, flow, speaking, integrations, null The caller's intent the test covers.
text runs a simulated chat; phone is not built yet.
text, phone The production call it was made from, or based on.
^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"3f1c2d4e-5a6b-4c7d-8e9f-0a1b2c3d4e5f"
The issue it reproduces, for a test made from an issue.
The caller the test plays when a run does not name personas.
Show child attributes
Show child attributes
Bumped by every accepted edit. GET .../revisions has each one.
draft: made by a key or the copilot and not accepted yet; it runs and reports and never gates or counts. accepted: counts. POST .../tests/accept accepts drafts.
draft, accepted When it was accepted. Null on a draft.
"2026-10-02T14:03:07.120Z"
When a person approved its criteria. From then on a change to them needs a person's approval; anyone else's is filed as a criteria proposal.
"2026-10-02T14:03:07.120Z"
What the test claims: an issue test expects the defect (fail) until its fix ships.
pass, fail Marked a guard test: it runs several times every release and must pass every time.
Whether its results count toward a release. Only a calibrated test in the current scoring epoch gates.
Why it gates or does not, in a few words.
SignalMD generated the caller (a generated test). Such a test reports and never gates.
Show child attributes
Show child attributes
In the release set, which runs on every new version and from CI.
The test sets it belongs to.
Show child attributes
Show child attributes
Criteria lines after resolving against the current brief.
Where each tool's mocked answer comes from.
Show child attributes
Show child attributes
The latest attempt with the test's own caller. Null when it never ran.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Set when retired. An archived test is not run.
"2026-10-02T14:03:07.120Z"
"2026-10-02T14:03:07.120Z"
"2026-10-02T14:03:07.120Z"
A test as a JSON document: who calls, what each tool answers, and what must hold. GET .../tests/schema has its JSON Schema; POST .../tests/validate checks one.
Show child attributes
Show child attributes
The criteria as they will be checked against the current brief.
Show child attributes
Show child attributes
Was this page helpful?