GUIDES

Connect tools

A tool is just an HTTP endpoint you own. The agent decides when to call it, EERRAA makes the request, and the result comes back into the conversation.

Talk is cheap. A tool is what lets the agent act: look up an order, create a ticket, refund a charge. You register an endpoint, describe what it does and what arguments it takes, and the agent calls it when the conversation calls for it.

Register a webhook tool

In your project, add a custom tool and point it at your endpoint. You give it a name, a plain description (the agent reads this to decide when to use it), a method and URL, and a JSON schema for its inputs. EERRAA fills the arguments the model chose into the request you describe.

  • Name and description. Write the description for the model. Say what it does and when to use it.
  • Parameters. A JSON schema. The model produces values that match it.
  • Request. Method, URL, headers, and body, with the parameters templated in.

Request and response shape

EERRAA sends the arguments the model produced to your endpoint. Return JSON. Whatever you return is handed back to the agent as the tool result, so keep it tight and readable: the model reads it to write its reply.

json
// POST https://api.acme.com/orders/lookup
// (the body EERRAA sends, built from the model's arguments)
{
  "order_id": "A-40912"
}
Return a clear error shape too (for example { "error": "order not found" }). The agent will read it and can recover, ask a follow-up, or explain the problem to the user.

Template per-user values

Headers, URLs, and params support {{user.*}} templating, so a tool call can be scoped to whoever is chatting without the model ever seeing the raw secret. The values come from the user context you set (see Identify users).

text
# In a header value:
Authorization: Bearer {{user.auth_token}}

# From the per-user credential vault (decrypted at call time):
X-Api-Key: {{user.creds.stripe_key}}

# From the user context data you passed:
X-Tenant-Id: {{user.data.tenant_id}}
{{user.creds.<name>}} pulls from the Fernet-encrypted vault and is substituted at request time. The raw secret is injected into your outbound call only, it never reaches the model. {{user.auth_token}} forwards the live JWT you signed the identity with.

The SSRF guard

Because tools make outbound HTTP from EERRAA's servers, every webhook URL passes an SSRF guard. Requests that resolve to private, loopback, or link-local addresses are refused, so a tool cannot be tricked into probing internal infrastructure. Point tools at real, publicly reachable endpoints (your API, behind its own auth).

If your endpoint lives inside a private network, expose it through a proper gateway or tunnel with a public hostname. A URL that resolves to a private range will be blocked before the request is made.

Gate write actions

Reads can run freely. Writes should pause. Mark a tool as a write action and the agent will not fire it silently: the widget surfaces an Approve / Cancel confirmation first, showing the user exactly what is about to happen and with what inputs.

On the API this arrives as a confirmation_required event in the stream, carrying the tool name, a display_name, and the input the model chose. Nothing runs until the user approves.

json
// SSE event on a write tool awaiting approval
{
  "type": "confirmation_required",
  "id": "call_88f2",
  "name": "refund_charge",
  "display_name": "Refund a charge",
  "input": { "charge_id": "ch_9921", "amount": 4200 }
}
The widget renders the Approve and Cancel buttons for you. Combined with the budget hard stop and per-user throttle, this keeps an agent that can act from acting recklessly.