The tool endpoint
Endpoint requirements
A service that posts JSON to a customer-supplied URL is a request forgery engine unless it is picky about the URL. Tether is picky, and refuses rather than warns.
The rules
| Requirement | Refused when | Error |
|---|---|---|
| Absolute URL | Relative or unparseable | invalid_endpoint |
| HTTPS scheme | http://, or any other scheme | invalid_endpoint |
| Public address | Resolves to loopback, private, or link-local | invalid_endpoint |
| Resolvable host | DNS lookup fails | invalid_endpoint |
| Configured at all | The tenant has no endpoint | not_configured |
A refusal is returned to the model as a failed tool call, and logged with the reason. The turn continues and the assistant says the lookup failed — it does not crash.
Blocked address ranges
Checked against every address the hostname resolves to, not just the first:
| Range | Why |
|---|---|
127.0.0.0/8, ::1, localhost | Tether's own loopback — its database, its admin surfaces |
10.0.0.0/8 | RFC 1918 |
172.16.0.0/12 | RFC 1918 |
192.168.0.0/16 | RFC 1918 |
169.254.0.0/16 | Link-local, and the cloud instance metadata endpoint |
0.0.0.0/8, :: | "This network" and the unspecified address |
100.64.0.0/10 | Shared address space, used for carrier-grade NAT and by many private networks |
198.18.0.0/15 | Reserved for network benchmarking |
224.0.0.0/4 and above, IPv6 ff00::/8 | Multicast and reserved |
| IPv6 link-local, site-local, unique-local | The v6 equivalents |
::ffff:a.b.c.d, ::a.b.c.d, 64:ff9b::a.b.c.d | IPv6 forms that carry an IPv4 address. They are judged by the IPv4 address inside, so [::ffff:169.254.169.254] is refused exactly like 169.254.169.254 |
Numeric spellings of an address, such as 2130706433 or 0x7f.0.0.1, are read as the address they
are and refused the same way.
An unresolvable hostname is refused too, with the message Endpoint host could not be resolved.
Refusing to guess is the point: the alternative is letting the request through and finding out
where it went afterwards. A refused address answers Endpoint resolves to a private or loopback address. followed by a sentence saying Tether cannot reach a server on your own machine or
network. The same answer is given to http://localhost:3000/..., which fails on the address
before it fails on the scheme, because the address is the problem you cannot fix by changing
http to https.
How the address check works
Developing on your laptop against a hosted Tether
Tether calls your endpoint from its own servers, so http://localhost:3000 cannot work however it
is spelled: https://localhost is refused as a loopback address and http:// is refused as
insecure. Give your local server a public HTTPS address instead. Any tunnel that forwards a public
https:// address to a local port will do; run one against the port node server.js prints, then
register the tunnel's address with the path your handler is mounted at:
tether init --endpoint https://your-tunnel-address.example/tether
The tunnel supplies the valid certificate the client requires. Tether's signature check still applies to every call, so the tunnel does not need to be private or authenticated.
Local development
This section is for running Tether itself on your machine. Both guards can be relaxed, and both should be off everywhere else:
{
"ToolTransport": {
"AllowInsecureEndpoint": true,
"AllowPrivateNetworkEndpoint": true
}
}
AllowInsecureEndpoint permits http://. AllowPrivateNetworkEndpoint disables the address
check, which is what lets you point a local Tether at http://localhost:3000/tether/invoke.
These are process-wide, not per-tenant. Enabling either in a hosted environment turns the address guard off for every customer at once.
Practical requirements beyond the guard
A valid certificate chain. Self-signed certificates are rejected by the HTTP client, and there is no per-tenant trust store.
Reachable from Tether's egress. If your endpoint sits behind an IP allowlist, it needs the service's egress addresses.
Sized for bursts. One turn can dispatch up to four tool calls concurrently
(AI:Orchestration:MaxConcurrentTools), and a turn can make several rounds of them.
Fast. 20 seconds per attempt is a ceiling, not a budget. See Returning results.