← ElevenLabsCONTENT HISTORY

Update to ElevenLabs

Snapshot Sep 30, 2026 · 22:53 UTC · version 1.0.0

Collection source: not recorded for this historical snapshot.

WHAT CHANGED · RULE-BASED ANALYSIS

First saved snapshot

No earlier snapshot is available to establish a change.

Compare saved observations

Download comparison JSON
Full technical diff · 0 changed fields
Full snapshot data
{
  "name": "architect-create-webhook-tool",
  "description": "Use when the user wants to give an agent a NEW webhook / server / HTTP tool so it can call an external API (look up a customer, create a ticket, check inventory, hit their backend). Fires on \"add a webhook tool\", \"connect my agent to my API\", \"make a tool that calls my endpoint\", or when a webhook-tool create fails with schema_mismatch / validation. For editing an existing tool see the edit-existing-tool skill; for a tool that saves but misbehaves at runtime see the troubleshoot-tool-errors skill.",
  "included_files": [],
  "skill_md_contents": "---\nname: architect-create-webhook-tool\ndescription: Use when the user wants to give an agent a NEW webhook / server / HTTP tool so it can call an external API (look up a customer, create a ticket, check inventory, hit their backend). Fires on \"add a webhook tool\", \"connect my agent to my API\", \"make a tool that calls my endpoint\", or when a webhook-tool create fails with schema_mismatch / validation. For editing an existing tool see the edit-existing-tool skill; for a tool that saves but misbehaves at runtime see the troubleshoot-tool-errors skill.\n---\n\nCreating a webhook tool is the most common way to connect an agent to an external API, and it fails a lot, almost all from schema mistakes in `api_schema.request_body_schema`. This skill gets it right on the first write.\n\nAll calls use `xi-api-key: $API_KEY` against `https://api.elevenlabs.io`.\n\n## 1. Gather current state first\n\nBefore writing anything, make these reads (in parallel where independent):\n\n- `GET /v1/convai/agents/$AGENT_ID?branch_id=$BRANCH_ID` to confirm the agent and whether it is a single-node agent or a workflow (the workflow is in this config; it changes where you attach the tool later).\n- `GET /v1/convai/tools` to check the tool does not already exist and to match the naming style already in use.\n\nGet the endpoint URL, method, auth method, and request/response shape from the user before you construct the tool. If any are missing, ask for them or the API docs first.\n\n## 2. Create the tool\n\n```\nPOST /v1/convai/tools\n```\n\nwith the tool config discriminated by type (webhook/server). The webhook config lives under `api_schema`, not at the top level.\n\n## 3. Schema gotchas (the specific things that cause failures)\n\n1. STATIC URL. `api_schema.url` must be a static string. Do NOT put `{{variables}}` in the path. Dynamic values go into `request_body_schema` (or `path_params_schema` / `query_params_schema`), never interpolated into the URL.\n2. EXACTLY ONE value source per property. Every property in `request_body_schema.properties` gets its value from exactly one of: a non-empty `description` (LLM fills it), `dynamic_variable` (e.g. `\"user_phone_number\"` or a system var like `\"system__conversation_id\"`), `constant_value` (a fixed literal), or `is_system_provided: true`. Two sources on one property is the most common validation failure; ZERO sources is equally invalid. A bare `{\"type\":\"string\"}` or a property whose only non-type field is an empty `constant_value` has zero sources and is rejected. `constant_value: \"\"` does NOT count as a constant.\n3. path_params_schema / query_params_schema are ARRAYS of parameter objects, NOT a `{properties:{...}}` object. Each item needs: `id`, `type` as a BARE string (`\"string\"`|`\"number\"`|`\"integer\"`|`\"boolean\"`; nullable uses a 2-element array like `[\"string\",\"null\"]`, never `{\"type\":\"string\"}`), `description`, `value_type` (`\"llm_prompt\"`|`\"dynamic_variable\"`|`\"constant\"`), `dynamic_variable` (empty string unless bound), `constant_value` (always a string/number/boolean, NEVER null or omitted), and `required` (boolean). A working llm_prompt item: `{\"id\":\"city\",\"type\":\"string\",\"description\":\"The city to look up.\",\"value_type\":\"llm_prompt\",\"dynamic_variable\":\"\",\"constant_value\":\"\",\"required\":true}`.\n4. ARRAY properties REQUIRE an `items` schema and MUST NOT carry `constant_value`.\n5. `required` must reference only property names that exist in `properties`.\n6. `request_headers` is an OBJECT, not an array. For secret API keys, reference a workspace secret by id (`{\"secret_id\": \"...\"}`, list existing via `GET /v1/convai/secrets`) rather than pasting the key.\n7. `response_timeout_secs` defaults to 20, max 120. Raise it only for genuinely slow APIs; high timeouts hurt voice latency.\n8. Name and description drive INVOCATION. Make the description specific (\"Look up a customer by phone number\", not \"Customer lookup\"); a vague description is the top reason a correctly-saved tool never gets called.\n\n## 4. Extract response values into the conversation\n\nTo feed API response fields into `{{dynamic_variables}}`, add entries to the tool's top-level `assignments` array (a sibling of `api_schema`). Each maps a response field to a variable: source `response`, a dot-notation `value_path` (`data.items.0.id`, NOT `data.items[0].id`, bracket indexing silently misses), and the target `dynamic_variable`. Then reference `{{customer_name}}` in the prompt so the agent speaks it.\n\n## 5. Attach and wire usage\n\nAfter creating, attach the tool to the agent. On a single-node agent add its id to the base `tool_ids`; on a workflow agent keep base `tool_ids: []` and add it to the right node's `additional_tool_ids` so it is only in scope where it fires. Apply the attachment via a targeted `PATCH /v1/convai/agents/$AGENT_ID?branch_id=$BRANCH_ID` on the relevant path. In the prompt, tell the agent exactly when to call the tool and add a fallback line (\"If the lookup returns an error or no results, apologize and offer to take a message\").\n\n## 6. Recovery\n\n- `schema_mismatch` (often no field detail): re-check the section-3 rules one by one, most often two value sources on one property, a `{{var}}` in the URL, or `constant_value` on an array. Fix and resend; do not blind-retry the identical payload.\n- `validation`: a concrete arg is wrong (a `required` name with no matching property, an array missing `items`, a bad `value_path`, a non-object `request_headers`). The message names the field; correct that one.\n- `not_found`: a bad agent id or a workflow node id that does not exist. Re-read current ids and retry.\n"
}

SHA-256: 9fbf6a3c86676752435087531d494933412b90b4c38c2a9c1bc526b460e38b0e