Custom tools are the core mechanism of TengineAI. Every tool the model can call is one you define — there are no prebuilt connectors. You register an HTTP endpoint, describe the input schema, and TengineAI handles execution, authentication, and identity injection.
Every tool call follows this exact sequence:
{variable_name} placeholders in endpoint_path, query_template, headers_template, and body_template using both model-provided arguments and reserved session variablesX-Tengine-* headers to the outbound requestauth_strategy is hmac_signature or static_bearer, TengineAI authenticates the outbound requestbase_url + rendered endpoint_path| Field | Required | Description |
|---|---|---|
name | ✅ | Unique per project. Convention: {category}-{api}-{method} |
description | ✅ | Shown to the model for tool selection. Be specific. |
input_schema | ✅ | JSON Schema defining model-provided parameters |
base_url | ✅ | HTTPS origin only — no path, query string, or fragment |
http_method | ✅ | GET, POST, PUT, PATCH, or DELETE |
endpoint_path | ✅ | Path template starting with /. May contain {variable} placeholders. |
headers_template | — | Static or templated request headers |
query_template | — | Static or templated query parameters |
body_template | — | Static or templated JSON request body |
require_member | — | If true, rejects calls without a valid member session |
inject_member_identity | — | Which member identity headers to include outbound (id, email, roles) |
auth_strategy | — | none, static_bearer, or hmac_signature |
encrypted_auth_secret | — | Required when auth_strategy is not none |
{category}-{api-name}-{method}
Examples: crm-contacts-get_by_id, billing-invoices-list, analytics-events-track
The name is what the model sees when selecting a tool. Make it unambiguous and descriptive.
TengineAI uses {variable_name} syntax in path, query, header, and body templates.
Injected automatically from the authenticated session. Cannot be used as model input parameter names.
| Variable | Value | Available When |
|---|---|---|
{member_id} | The authenticated member's external ID | Member session active |
{project_id} | The TengineAI project ID | Always |
{integration_id} | The TengineAI integration ID | Always |
Any parameter defined in input_schema is available as a template variable. If the model passes {"contact_id": "c_001"}, you can reference {contact_id} anywhere in the templates.
Injected into every outbound request regardless of auth strategy:
| Header | Always Present | Description |
|---|---|---|
X-Tengine-Project-Id | ✅ | Your TengineAI project ID |
X-Tengine-Integration-Id | ✅ | The integration ID |
X-Tengine-Request-Id | ✅ | UUID per request — use for deduplication |
X-Tengine-Timestamp | ✅ | Unix seconds — use for replay protection |
X-Tengine-Member-Id | When inject_member_identity.id = true | Member's external ID |
X-Tengine-Member-Email | When inject_member_identity.email = true | Member's email (opt-in) |
X-Tengine-Member-Roles | When inject_member_identity.roles = true | Member's roles (opt-in) |
base_url RequirementsMust be an HTTPS origin with no path, query string, or fragment:
✅ https://api.yourcompany.com
✅ https://api.yourcompany.com:8443
❌ https://api.yourcompany.com/v1 (no paths)
❌ http://api.yourcompany.com (HTTPS required)
http:// is never allowed. For local development, expose your server with a tunnel (e.g. ngrok) and use the https:// tunnel URL.
When the model or SDK retries a tool call (e.g. after a timeout or transient error), TengineAI handles it safely:
Use X-Tengine-Request-Id in your API to correlate and deduplicate. If you see the same Request ID twice, the second is a retry — you can return the same response or short-circuit.
require_member Behavior| Session type | require_member: true | require_member: false |
|---|---|---|
| API key | ❌ Returns error | ✅ Always accessible |
| Member session | ✅ Accessible | ✅ If member_sessions_include_project_tools: true on the integration (default) |
When a member session is active, X-Tengine-Member-Id and other configured identity headers are injected regardless of require_member setting.