- you already have an API to call
- the URL is a deployment choice, not something to hardcode
- you want no code of your own to write or review
webhook: tool works on livekit and pipecat. It is refused on an slng
target: SLNG owns a tool’s code, version and gate pipeline, so there is
nowhere in a package for a URL and its credential to write to there.
Reference a tool your organisation already has on the platform with
slng: instead.
On this page:
- The block - the four keys
- The path renders per call - variables in the URL
- Authentication - bearer or API key
- What the model fills in, and what it cannot - input against inject
- Advanced - naming the base URL, describing the result
- Troubleshooting - the refusals, and their fixes
tools/confirm_appointment.yaml
url_env and base_url this way compiles to livekit and pipecat; an slng
target refuses it, for the reason in the note above. examples/hotel-concierge
ships no webhook tool: its places-search tool reaches SLNG through the
hosted-tool block instead.
announce: is the one line worth knowing about here, because a webhook is the
tool most likely to keep the caller waiting. The agent speaks that exact sentence
as the call starts and does not wait for it to finish, so the answer arrives no
later than it would in silence. It is a fixed sentence, and {{variables}} are
refused. Full rules in the behavior fields.
The block
string
An UPPER_SNAKE environment variable name holding the base URL. Required on LiveKit and
Pipecat. At least one of
url_env and base_url must be present; no URL is inferred.string
A literal HTTPS base URL. Omit it on code targets, which read
url_env instead. The
SLNG target refuses authored webhooks: publish the tool on SLNG and use a hosted slng
reference.string
Path appended to the base URL. A non-empty path starts with
/ and may use
{{variable}} tokens, whose values are URL-encoded. Omit to use the base URL alone.object
Authentication using the fields below. Omit to add no authentication header.
url_env holds a name, so the base URL is a deployment choice rather than a
package one: staging and production run the same package against different APIs.
Pipecat and LiveKit read it at run time and never look at base_url.
The path renders per call
{{customer_id}} is a variable, rendered when the tool is
called, and the rendered value is URL-encoded for you. Because it renders per
call rather than once at session start, a variable that only gets its value
once a task assigns it partway through the call is fine here.
If the variable has no value when the model calls the tool, the call is refused
and the model is told what to ask the caller for, rather than sending a
half-formed request.
Authentication
string
required
Accepts
bearer or api_key. Required when auth is present; no scheme is inferred.UPPER_SNAKE name
required
The environment variable holding the token. Always a name, never a value.
header name
default:"X-API-Key"
Legal on
api_key only.agent.yaml under
secrets:. The compiler also infers these fields as
required environment names, so leaving one out of secrets: warns without
dropping it from generated environment instructions or checks.
api_key and its header reach livekit and pipecat exactly as written. An
slng target never sees this field at all: webhook: is refused there, so
there is no bearer-only rewrite to plan around any more.
What the model fills in, and what it cannot
input is the model’s half of the request. inject is yours.
{{token}} keeps that variable’s declared type, so a
number stays a number.
Every injected value must be a scalar. Strings, numbers, booleans, and null are
legal; maps and lists are refused.
Advanced
Naming the base URL
base_url exists for a hosted target: that is where SLNG used to store the
URL in the tool body it pushed, since there was no environment for it to read
at run time there. An slng target refuses a webhook: block outright now,
for the reason at the top of this page, so there is no longer a target that
reads base_url. Name url_env for livekit and pipecat, which read it at
run time and never look at base_url.
Describing the result
output is optional author documentation. The compiler checks that it is a
JSON Schema object, but no generator sends it to the model or writes it to the
compile report, and nothing checks the API’s response against it either. The
example records the shape the API is expected to return; teach the model how
to use that data in the tool description or prompt.
A local: handler’s output: was the one exception,
checked on an slng target because SLNG ran that handler itself. That block is
refused there now, and the check moved with the code: a hosted code tool’s
module carries its own Output model, and SLNG reads the result shape off
that. See Python tools
and Hosted tools.
Troubleshooting
Both code targets refuse a tool with no url_env
Drop url_env and both code targets refuse, and the message still names a
hosted target as the reason the field exists at all:
url_env with the UPPER_SNAKE name of the variable that holds the
base URL, and keep base_url if the package also has a hosted build.
A {{token}} in the path names nothing
A token that names nothing at all fails at compile time:
variables:, or correct the spelling in the
path.
token_env holds a value instead of a name
Again a name, never a value. A token written in place of a name is refused:
An auth field belongs to the other scheme
A field from the other scheme is refused too, and the message says why:
header from a bearer block, or switch type to api_key if
the API really wants a named header.
A key is in both input and inject
A key cannot be in both lists, and the refusal explains the reason rather than
just the rule:
inject: for a value the model must
never see, or in input: for one the model fills in.
Where to go next
Python tools
When the request needs code of your own, like a signature.
Variables
Where
{{customer_id}} comes from.