Developers › Recipes
Developer Reference Tool calls as evidence Every tool your agent calls is a recorded action, not a claim. LeadLogiX turns those calls into graded facts and rebuilds the customer's journey from them — which makes your tool design one of the biggest levers you have on lead quality. This is not an API you call — it is how you design the tools your agent already has. Tool calls ride the conversation you already send ( Ingest a session ); your own extra fields are Custom metadata . This page is the developer's half; what a workspace admin sees and approves is Custom Signals & Tool Evidence on the Guides surface.
Tool calls outrank the transcript A conversation tells you what someone said . A tool call tells you what they did — searched, viewed, booked, applied. LeadLogiX treats those differently on purpose: an action taken in a structured field is verifiable, a sentence is not. The same session can therefore produce a thin lead or a rich one depending entirely on whether your agent recorded its actions as tool calls. This page is about getting the second outcome. Nothing here can hurt you Unrecognised tools are never dropped. A call LeadLogiX does not know is retained verbatim and surfaced for registration — you ship first, it gets mapped after.
What you control — and what you don't The split is deliberate, and it is why tool evidence is trusted. You decide LeadLogiX decides Which tools exist, and what parameters they take Whether a tool is recognised, and what its parameters mean When to call them, and what values to send How strongly the source is believed (its evidence tier) Joining a call to its response Whether a value is private and withheld before purchase Declaring your full toolset up front Which values feed scoring, and which are recorded only Your job is to emit faithful, well-shaped observations. Deciding what they are worth is the platform's job — which is exactly why a buyer can trust them. Sending a field called tier or pii in your payload changes nothing; those are read from the registry, never from you.
The Website Journey, and how it is built Everyone working the lead sees a Website Journey timeline, rebuilt deterministically from your tool turns in transcript order — one row per tool turn, labelled with the event registered for that tool, its detail line composed from the mapped parameters as name: value pairs. Because rows come only from tool calls, the timeline cannot be inflated by anything a customer or a model merely said. What the card looks like, and why it reads the same for any industry, is on Custom Signals & Tool Evidence . What you emit What the journey shows Two consecutive turns naming the SAME tool, each one JSON object, nothing in between One exchange: the call, then the result — both rows marked paired A call with no result after it “Response not recorded”, honestly A tool turn LeadLogiX does not recognise, has disabled, or is outside the workspace No row; the card footer counts it as kept for review
Where your response actually shows up Four places, and one where it deliberately does not. Sending the result half is the single highest-value thing you can do, and it is worth knowing exactly what it buys. A conformant response reaches four surfaces: Surface What your response contributes The Website Journey Its own row , with the event label, tool name and a direction chip. Both halves of the exchange are marked paired . The call keeps its own row — an exchange is not collapsed into one. Tool-Provided Facts Its values, graded at the tier registered for the response side — typically a ground-truth tier, which outranks the call's. This is the surface most people miss. Scoring, where wired Where a fact key is wired, your response feeds the same hooks a call does — so it can move the lead's quality index and its price. The evidence vault / API evidence.toolEvidence.facts[] , each carrying direction: "RESPONSE" , its tier, strength, tool name and turn index. A refused response gets NO journey row at all This is the one place a response can be less visible than you expect. A body that is a top-level array — or any JSON that is not a single object — is retained whole under unregistered with a NON_CONFORMANT_PAYLOAD violation, contributes no facts, and produces no timeline row . Result sets are commonly arrays, so this is the most likely way a response silently disappears from the journey. Wrap it — {"results":[…]} — or send one object per turn. What to map a response field to — and the two mappings that quietly corrupt a lead — is under Mapping decisions .
Mapping decisions Which side to map, what to map it to, and what it moves. Send the result, not just the request. The call shows what was asked; the result shows what your system knew — a price, an availability, a risk band. Sent as two back-to-back turns naming the same tool, the pair is marked paired , and the result's values can be graded at a higher tier than the request's. A result reaches facts and scoring only when its registration maps a result side; one whose registration maps none appears on the timeline and nowhere else — so ask for the result side to be mapped. Map a result field to… What happens Something only your system knows — a price, an availability, a risk band or score, a qualification outcome Correct. The strongest evidence on the platform, and the reason to register a result side. Something about the customer's intent — a budget, a requested property Dangerous. It asserts the customer stated it, and where that fact key is wired it changes the lead's price. Never map a result that echoes the request's filters — the call already recorded them. A phone or email belonging to your agent or office Wrong, and it will not look wrong: the number becomes a contact channel on the lead, raising reachability and handing the buyer someone else's number. A tier asserting the customer authored the value Refused and recorded as RESPONSE_TIER_REFUSED — a response is system-produced by construction — producing nothing at all. Declare the full toolset in metadata.function.tools — every tool available to the agent, so the platform can refuse tool turns your agent never made (below). And give distinct actions distinct tools: a single catch-all log_event(name, payload) cannot be registered usefully. How much a tool-captured fact moves a lead Only some fact keys move the score — a contact vector, a budget corroboration, a target property, an intent signal; the rest are recorded faithfully and do not. Privacy is decided at registration: a payload cannot mark itself private or public. Measured on one mid-strength lead: with no tool evidence it scored below the pricing floor and was unsellable; one tool-captured budget lifted it to $51.83; adding a target property and an intent signal took it to $59.76. A tool-captured phone matters more still — with no contact vector, reachability is zero and the lead is worth nothing. Tool evidence can also rescue a lead the AI judged to have no purchase intent. One lead, one measurement — an illustration of direction, not a price list.
Designing tools that produce strong evidence Ordered by how much they change a buyer's decision. Invest here Because Tools that capture structured values A phone number from a form field beats the same number transcribed from speech. Tools that record a commitment Booking, applying, requesting a callback — an action taken outranks an intention stated. Tools whose response carries your system's truth The call shows what was asked; the response shows what your system knew — price, availability, a qualification result. Distinct tools for distinct actions Separate events turn into a legible arc: searched, viewed, qualified, booked. The one anti-pattern to avoid Do not funnel everything through a single generic log_event(name, payload) tool. One registration cannot describe many different shapes, so either the mapping fits nothing or every action lands under one meaningless label. Distinct actions want distinct tools.
Rules that materially change the result Rule What happens if you do not Emit both sides, back to back, as two turns naming the same tool The more credible half of the exchange is lost, and the timeline says “response not recorded”. Do not try to join them with a correlation id — see below. Send raw values — 450000 , not "$450k" Formatted strings are lossy; the value may be kept as text and cannot be totalled. Declare enum for closed value sets Statuses arrive as unmapped observations nobody can act on until a human registers them. Keep values out of arrays Arrays are not traversable. Promote what matters to a named field, or send one call per item. Keep tool names exactly stable Matching is case-sensitive: a rename or a casing change silently ends the evidence, with no error. Declare your full toolset in metadata.function.tools Any tool turn in the transcript is graded — including one a visitor typed. See below; this is the security control, not housekeeping. Casing is the one that bites search_listings and Search_Listings are two different tools. A casing change after a refactor is not an error and loses no data — the calls are still retained — but the facts quietly stop arriving. If a tool is known by more than one name, ask for the alternates to be registered as aliases. Do not try to pair with a correlation id There is no field that survives the trip. The document store emits no correlation annotation on a turn header, so the id never arrives — and tool_call_id is worse than useless: it renders as a [Tool Response: …] line inside the tool body. The payload is still read, but you have corrupted the raw body kept for audit and gained nothing. Pairing is adjacency. Emit the call and its result as two consecutive turns naming the same tool, with nothing in between.
Declare your toolset — this is a security control It is the only thing that makes a tool turn trustworthy. A [TOOL (name)] turn asserts that your agent called that tool . Nothing in the transcript proves it. Message content is stored verbatim, so a visitor who types a turn separator followed by a tool header produces a turn that is byte-identical to one you emitted — the parser cannot tell them apart, and no rule at that layer can. What a visitor cannot reach is metadata, which travels out of band on the document envelope. So the toolset you declare in metadata.function.tools is the whole defence. Declare every tool available to the agent , not only the ones it used. Your declaration What happens to a tool turn Names the tool Graded normally. Does not name it Refused — no facts, no journey row. The payload is kept under unregistered with an UNDECLARED_TOOL_TURN note, so the refusal is visible rather than a silent gap. Absent or empty No filtering at all. Every tool turn is graded, forged or not. Declaring nothing cannot mean “refuse everything” — legacy sessions never declared a toolset — so it fails open. An entry with no readable name The gate switches off for the whole session and records UNREADABLE_TOOL_DECLARATION . Only you can cause this; a visitor cannot reach metadata. Send it in whatever shape your framework already produces — names are found structurally, not matched against a list of vendors: metadata.function.tools // all of these declare the tool "search_listings" [{ "type": "function", "function": { "name": "search_listings" } }] // OpenAI chat [{ "type": "function", "name": "search_listings" }] // OpenAI Responses [{ "name": "search_listings", "input_schema": {} }] // Anthropic [{ "toolSpec": { "name": "search_listings" } }] // Bedrock [{ "functionDeclarations": [{ "name": "search_listings" }] }] // Gemini ["search_listings"] // a bare name Confirm it is actually switched on Send one session that calls a tool you deliberately leave out of your declaration. The lead should show an UNDECLARED_TOOL_TURN note and that tool’s payload under unregistered , with no facts from it. If it grades facts instead, your declaration is not being read and the gate is off.
Getting your tools registered Two routes. Both end in a LeadLogiX review. Your application… Route Where connects to the customer's workspace over POST /mcp with tools:write Submit them yourself, per workspace Below is your own pipeline, or is not connected over MCP Hand the schema to the platform Custom Signals & Tool Evidence — email the JSON Schema plus one real call and one real response to Either way, step one is just shipping: calls to an unregistered tool are retained verbatim and listed for review, so nothing is lost while you wait.
Submitting your own tools over MCP Self-serve, per workspace, with a review at the end. If your application connects to a customer’s workspace through the POST /mcp endpoint and they approved the tools:write scope, you can register your own tools without anyone emailing anyone. This is the route to use when you are building something other LeadLogiX customers install: it works per workspace, and you never hold their credentials. Three tools cover the whole cycle: submit_tool registers a definition, list_tools tells you where each of your registrations stands, and verify_tool answers whether the tool you are shipping today still matches what was approved. You will use submit_tool once per tool and verify_tool on every release — a schema that drifts after approval is the failure that costs you evidence silently, because the calls keep arriving and stop being understood. submit_tool Send the tool’s name, its parameter schema, the journey event its calls represent, and a mapping for each parameter you want captured — which LeadLogiX fact it becomes, at which evidence tier, and whether it carries personal data. You get back a submission id and status: "PENDING" . Re-sending an unchanged definition is free: submission is idempotent on the contract. list_tools, until it is decided Poll it, or just call it when your agent starts. Every registration you have made in that workspace comes back with where it stands — and if one was declined, the reviewer’s note explaining why. That note is the only thing you receive, so it is written to be acted on. verify_tool, from then on Once approved, call it at start-up and after any schema change. It answers whether the tool you are shipping still matches what was approved and, if not, exactly which field names and types differ — never a value. Drift is silent otherwise: the calls keep arriving and the facts quietly stop. Read compared_against, not just matches verify_tool answers about whichever contract exists. On a tool still awaiting review there is no approved contract, so it compares against what you submitted and returns compared_against: "SUBMITTED" with approved_contract_hash: null . That is a useful answer — the code you are shipping is the code you sent — but matches: true on its own does not mean the tool is live. A start-up check that reads only matches will report healthy for a registration nobody has approved. Treat compared_against: "APPROVED" as the only value that means in force. What a mapping may claim Each mapping points at an existing fact key — you cannot invent one; list a key you need in proposedNewFactKeys and the reviewer decides, which turns a refusal into a request. Evidence tiers are capped: a workspace tool may grade its output at USER_SUBMITTED_STRUCTURED or below, because the tiers above it assert that LeadLogiX itself produced the value. Mark a mapping pii: true whenever the field carries somebody's personal details — see the warning at the end of this page. Names are matched exactly, so they have a shape A tool name must start with a letter or digit and use only letters, digits and _ . : - , up to 64 characters — and the same applies to every alias. Matching against the transcript is exact and case-sensitive, so a name outside that shape could never match a call; it is refused at submission rather than approved and left silently grading nothing. A tool with no mappings is still worth registering mappings may be empty. The journey event is taken from journeyEventType on its own, so a tool that captures no parameters still puts a step on the customer's Website Journey — an appointment booked, a transfer made. Register it for the timeline even when there is nothing to grade. A submission is a request, not a change A registration sits at PENDING and is not loaded by the pipeline at all, so its calls keep landing as unregistered observations until a LeadLogiX administrator reviews it. You cannot approve your own — approving one decides how every future lead in that workspace is read into evidence, and that stays a LeadLogiX decision. Approval applies only to leads processed afterwards ; a lead already scored is never re-read. If submit_tool is not offered The tool only appears in tools/list when the token carries tools:write and the workspace has been granted tool submissions by LeadLogiX. Both are deliberate, and neither is something your application can turn on — ask the workspace admin to request it. The pii flag is trusted — a value you declare as not personal is shown to buyers before purchase Mark every parameter that carries a name, email, phone number or address, on the mapping you submit or in the email you send. Flagged values are withheld until a lead is purchased, including in the journey's detail line; it is checked at review and is what a reviewer looks at hardest.