agntz
RuntimeHostedSelf-hostDocsChangelog
Sign inQuickstart
Documentation
View .mdOptimized for LLMs — paste directly into ChatGPT, Claude, or Cursor.

HTTP tools

A single HTTP endpoint exposed to the model as a tool. URL placeholders define the LLM-facing parameter schema. GET, POST, PUT, PATCH, and DELETE are all supported. Works identically in embedded and hosted mode.

tools:
  - kind: http
    name: weather_lookup
    url: "https://api.weather.com/v1/forecast/{location}{?units}"
    description: "Look up weather forecast for a location"
    params:
      units: "metric"           # pin the optional query param; hidden from the LLM
    headers:
      Authorization: "Bearer {{secrets.WEATHER_TOKEN}}"

URL placeholder syntax

The URL template encodes the tool's parameter schema:

SyntaxMeaning
{X}Required path or query parameter
{X?}Optional query parameter
{?units}Required query (alt form)
{?units&format}Multiple required query params

Each placeholder becomes a parameter the model sees. The placeholder name is the parameter name; the type defaults to string. Use params: to pin a value — the parameter disappears from the model's tool schema and is filled by the template engine instead.

Headers are templated too — they can reference env vars ({{env.NAME}} in embedded mode) or secrets ({{secrets.NAME}} in hosted mode). See Templates and conditions.

POST / PUT / PATCH with a request body

tools:
  - kind: http
    name: create_user
    url: "https://api.example.com/users"
    method: POST
    body_type: json            # json (default), form, or query
    body:
      name: "{{userName}}"
      email: "{{userEmail}}"

body_type:

  • json (default) — serializes body as JSON, sets Content-Type: application/json.
  • form — URL-encoded form body.
  • query — appends body properties to the URL's query string (useful when the only "body" you want is on a GET-like request that has many params).

Body fields can be templates ({{userName}}) or pinned literals. Templated fields the LLM provides go in the body; literals don't appear in the model's parameter schema.

Dynamic auth — OAuth2 client credentials

For APIs that require fetching a short-lived access token before each call, declare an auth: block. The runner fetches the token, caches it (refreshes on 401), and applies it — no code required.

tools:
  - kind: http
    name: send_message
    url: "https://api.salesforce.com/services/data/v60.0/sobjects/Message"
    method: POST
    body_type: json
    body: { content: "{{message}}" }
    auth:
      type: oauth2_client_credentials
      token_url: "https://login.salesforce.com/services/oauth2/token"
      client_id: "{{secrets.SF_CLIENT_ID}}"
      client_secret: "{{secrets.SF_CLIENT_SECRET}}"
      scope: "messages:write"          # optional
      creds_location: basic_header     # default (RFC 6749); or "body"

Dynamic auth — generic token exchange

For login endpoints that don't match the OAuth2 spec — different field names, plain-text token responses, custom header names — use the parametric token_exchange form:

tools:
  - kind: http
    name: list_things
    url: "https://api.example.com/things"
    auth:
      type: token_exchange
      request:
        url: "https://api.example.com/auth/login"
        method: POST
        body_type: json
        body:
          username: "{{secrets.API_USER}}"
          password: "{{secrets.API_PASS}}"
      extract:
        response_format: json          # default; "text" for raw-body tokens
        token_path: "$.access_token"   # JSONPath; e.g. "$.token", "$.data.accessToken"
        expires_path: "$.expires_in"   # optional, seconds
      apply:
        location: header               # default; or "query"
        name: Authorization
        format: "Bearer {token}"       # default for header; "{token}" for query
      cache_ttl: 3000                  # optional, seconds
      refresh_on: [401]                # default

What you get for free

When you declare auth:, the runner provides:

  • Per-tenant token caching keyed by ownerId — tokens are not shared across users.
  • Single-flight dedup of concurrent token requests — only one fetch when many tools need the same token.
  • Automatic refresh-on-401 with one retry, no infinite loops.
  • Redaction of known token / secret substrings from response bodies and error messages — tokens never leak into traces.

Static auth

For APIs with long-lived keys, skip auth: and template the credential directly into headers:

tools:
  - kind: http
    name: openai_completions
    url: "https://api.openai.com/v1/chat/completions"
    method: POST
    headers:
      Authorization: "Bearer {{secrets.OPENAI_KEY}}"
    body_type: json
    body:
      model: "gpt-5.4"
      messages: "{{messages}}"

Failures

HTTP tool failures are captured in the tool.execute span. The model sees the error body (truncated, redacted) and can decide whether to retry or give up. Non-2xx responses are treated as errors by default.

← Previous
Local tools
Next →
MCP tools