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

Signed callback tools

Callback tools let a hosted model call application-owned business logic without moving authorization, database access, or domain code into Agntz. The manifest declares only the model-visible input contract; Agntz injects trusted runtime context and signs the complete request.

Manifest

agents/hosted-nutritionist.yaml
id: hosted-nutritionist
kind: llm

model:
  provider: openai
  name: gpt-5.4

instruction: |
  Help the user find recipes. Call find_recipes when application data is needed.

tools:
  - kind: callback
    name: find_recipes
    description: Search recipes visible to the current trusted user.
    url: https://api.example.com/agntz/tools/find-recipes
    secret: nutritext_callback
    timeoutMs: 10000
    maxRetries: 2
    inputSchema:
      type: object
      properties:
        query: { type: string }
        savedOnly: { type: boolean }
        limit:
          type: integer
          minimum: 1
          maximum: 20
      required: [query]
      additionalProperties: false

inputSchema must be a canonical object-root JSON Schema. Agntz presents that exact schema to the model and validates the tool arguments before delivery. secret names an owner-scoped secret configured in the hosted workspace or self-hosted SecretStore; the secret value never appears in the manifest.

Timeouts are clamped to 1–120 seconds. Retries are clamped to 0–5. Agntz retries network failures, 408, 429, and 5xx responses with a short exponential delay.

Request body

{
  "tool": "find_recipes",
  "args": {
    "query": "quick tomato pasta",
    "savedOnly": true,
    "limit": 10
  },
  "runtime": {
    "sessionId": "session_...",
    "runId": "run_...",
    "agentId": "hosted-nutritionist"
  },
  "delivery": {
    "id": "cbd_...",
    "timestamp": "2026-07-28T18:30:00.000Z"
  }
}

runtime is injected from the active invocation. The model cannot choose a user id, namespace grant, run id, session id, or trusted application identity. Your endpoint should resolve authorization from the signed runtime context and its own application data.

Signature headers

HeaderValue
X-Agntz-Signaturesha256=<hex HMAC>
X-Agntz-TimestampISO timestamp from the delivery body
X-Agntz-Delivery-IdStable delivery id
Idempotency-KeySame stable delivery id

The signed bytes are:

timestamp + "." + deliveryId + "." + rawRequestBody

Verify the signature against the raw request body before parsing JSON. Then reject stale timestamps and deduplicate the delivery id.

verify-callback.ts
import { createHmac, timingSafeEqual } from "node:crypto";

function verifyCallback(
  secret: string,
  timestamp: string,
  deliveryId: string,
  rawBody: string,
  received: string,
) {
  const expected = "sha256=" + createHmac("sha256", secret)
    .update(timestamp + "." + deliveryId + "." + rawBody)
    .digest("hex");

  const left = Buffer.from(expected);
  const right = Buffer.from(received);
  return left.length === right.length && timingSafeEqual(left, right);
}

The body, timestamp, signature, and delivery id remain identical across retry attempts. Store the delivery id with the completed response so a retry cannot repeat a database mutation.

Endpoint response

Return a 2xx response with JSON when possible. The parsed JSON becomes the tool result visible to the model; a non-JSON success body is returned as text. Response bodies are capped before they are returned to the model.

Return a non-retryable 4xx response for invalid arguments or forbidden work. Use 408, 429, or 5xx only when retrying the same idempotency key is safe.

Security checklist

  • Require HTTPS outside trusted local development.
  • Verify HMAC using the raw body and constant-time comparison.
  • Enforce a timestamp tolerance.
  • Deduplicate X-Agntz-Delivery-Id.
  • Derive the authorized application principal server-side.
  • Treat args as untrusted even though it passed JSON Schema.
  • Keep callback responses small and free of secrets.
  • Allowlist callback destinations in the worker outbound URL policy.

Callback tools are different from async run-completion webhooks. A callback tool is invoked by the model during a run and its result feeds the model loop. A run webhook is configured by trusted application code when starting a durable run and reports lifecycle completion.

← Previous
HTTP tools
Next →
MCP tools